CSR vs SSR
사전 지식
- TTV(Time To View): 사용자가 웹사이트를 볼 수 있는 시간
- TTI(Time to Interact): 사용자가 클릭 이벤트와 같은 인터랙션이 가능한 시간
- TTFB(Time to First Byte): 어떤 리소스를 요청하고 난 뒤, 해당 요청에 대한 첫 번째 바이트가 도착하기 까지 걸리는 시간
- SEO(Search Engine Optimization): 구글, 네이버와 같은 검색엔진들이 올라와져있는 html을 분석하여 검색 결과를 보여주는 것
CSR(Client Side rendering)
CSR은 클라이언트 측에서 화면을 구성하는 것이다.
- 클라이언트가 웹에 들어가면 서버는
index.html
을 넘겨준다.index.html
에는 SPA에서 흔히 볼 수 있는 형태이다. ```html
이와 같이 내용물이 없는 빈 문서이다.
2. 클라이언트는 넘겨받은 `html` 속 `app.js`를 다시 서버한테 요청한다.
서버에서는 `app.js`에 해당하는 정보를 넘겨준다. `app.js`에는 웹 앱에서 필요한 로직, 구동하기 위한 소스코드들이 포함되어 있다. 사이즈가 크기 때문에 시간이 걸릴 수도 있다.
커다란 js 파일을 전달받은 후 DOM을 조작하여 컴포넌트들을 렌더링하는 과정으로 인해 초기 페이지의 보이는 속도가 느리다는 단점이 있다.
3. 클라이언트는 추가적으로 필요한 데이터들을 한 번 더 요청한다.
4. 클라이언트 측에서 앞서 2, 3번 순서에서 받은 데이터들을 기반으로 동적으로 html을 생성 후 사용자에게 보여준다.
-> `TTI`와 `TTV`가 동시에 일어나기 때문에 사용자가 첫 화면을 보기까지 오래 걸릴 수도 있다. 또한, 비워져 있는 html로 인해 seo가 좋지 못하다.
## SSR(Server Side Rendering)
`Next.js`는 클라이언트에게 웹 페이지를 보내기 전에 `Server` 측에서 미리 웹 페이지를 `Pre-Rendering` 한다. 그리고 `Pre-Redering`으로 인해 생성된 `HTML document`를 클라이언트에게 전송한다.
현재 클라이언트가 받은 웹 페이지는 단순히 웹 화면만 보여주는 `HTML`일 뿐이고, 자바스크립트 요소들이 하나도 없는 상태이다. 이는 웹 화면을 보여주고 있지만, 특정 JS 모듈 뿐 아니라 단순 클릭과 같은 이벤트 리스너들이 각 웹 페이지의 `DOM 요소`에 하나도 적용되어 있지 않은 상태임을 말한다.
`Next.js Server`에서는 `Pre-Rendering`된 웹 페이지를 클라이언트에게 보내고 나서, 바로 `리액트가 번들링 된 자바스크립트 코드들`을 클라이언트에게 전송한다.
### react와 Next.js의 hydration
js 코드들이 이전에 보내진 `HTML DOM` 요소 위에서 한 번 더 렌더링을 하면서, 각자 자기 자리를 찾아가며 매칭이 된다. 이 과정이 `hydration`이다. 마치 **js 코드들이 DOM 요소 위에 물을 채우 듯 필요로 하던 요소들을 채운다** 하여 수화라는 용어를 쓴다고 한다.
**요약**
1. 서버에서 필요한 데이터들을 토대로 html을 만들어 보낸 후 사용자에게 번들링된 js파일도 보내준다. 이 과정을 `hydration`이라 한다. -> CSR과는 달리 html이 모두 채워져 있는 형태로 SEO에 유리하다.
2. `pre rendering`된 `html`을 사용자에게 보여준다. -> js 파일을 연결하는 시간동안 사용자는 클릭과 같은 상호작용을 하지 못한다. but `TTV`는 빠르다.
**Server에서 한번 렌더링하고 Client에서도 한번 더 렌더링 하면 비효율적인 렌더링 방식 아닐까?**
서버 단에서 빠르게 Pre-Rendering하고 유저에게 빠른 웹 페이지로 응답할 수 있다는 것에 더욱 큰 이점을 가져갈 수 있다. 심지어 이 Pre-Rendering 한 Document는 모든 자바스크립트 요소들이 빠진 굉장히 가벼운 상태이므로 클라이언트에게 빠른 로딩이 가능하다. 이는 같은 화면에 대해 두 번 렌더링이 일어난다는 단점을 보완하고도 남는다. 더 나아가서 클라이언트 단에서 자바스크립트가 렌더링을 할 때, 단지 각 DOM 요소에 자바스크립트 속성을 매칭 시키기 위한 목적이므로 실제 웹 페이지를 다시 그리는 과정까지는 하지 않는다.(Paint 함수 호출 X)
> 출처: 아래 링크
**Hydrate 과정은 Next.js에서만 일어나는 과정인가?**
사실 Hydrate는 Next.js에 종속된 동작이 아니라 ReactDOM 함수이다.
```js
ReactDOM.render(element, container, [callback]);
ReactDOM.render()
함수는 특정 컴포넌트를 두 번째 파라미터인 지정된 DOM 요소
에 하위로 주입하여 렌더링을 처리
해주는 함수이다. 그리고 렌더링이 완료되면 특정 이벤트를 처리할 콜백 함수를 세 번째 파라미터로 넣어줄 수 있다.
ReactDOM.hydrate(element, container, [callback]);
ReactDOM.hydrate()
함수는 특정 컴포넌트를 두 번째 파라미터인 지정된 DOM 요소
에 하위로 hydrate 처리만
한다. 이는 렌더링을 통해 새로운 웹 페이지를 구성할 DOM을 생성하는 것이 아니라, 기존 DOM Tree에서 해당되는 DOM 요소를 찾아 정해진 자바스크립트 속성(이벤트 리스너 등)들만 부착시키겠다는 말이다.
결론은 react의 hydration은 자동기능이 아니라 SSR을 할 때에 굳이 render트리를 만들지 않고 기존에 형성된 DOM에 이벤트만 붙이면 되므로 해당 과정을 실행하는 메소드이다.
출처: 아래 링크
장점
- CSR보다 빠른 속도로 사용자에게 화면을 보여준다. TTV가 빠름. 브라우저가 js코드를 평가하는 과정과 관계없이 html이 먼저 보이기 때문에 CSR보다 빠름.
- html안에 모든 콘텐츠들이 있기 때문에 SEO에 좋음.
단점
- 링크 이동 시 전체적인 웹사이트를 다시 서버에서 받아 보여주는 방식으로 깜빡임 현상이 있을 수도 있음. 현대에는 새로운 페이지를 받기 전까지 기존 페이지를 보여주는 형태로 발점함. 그렇지만 해당 페이지를 받아오는 데 시간(
TTFB
)이 오래 걸리면 사용자는 불편함을 겪음.(페이지 이동 시 로딩을 보여주고 서버 자원을 신경써야 함.) - 사용자가 많아지거나 페이지 이동 요청이 많아지면 서버에 과부하가 걸림.
- TTV 이후에 TTI가 이루어지기 때문에 사용자의 클릭 이벤트 같은 인터랙션이 먹히지 않을 때가 있다.(hydration이 느려지는 경우)
출처
- https://helloinyong.tistory.com/315
- https://talkwithcode.tistory.com/17