Skip to main content Link Menu Expand (external link) Document Search Copy Copied

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은 클라이언트 측에서 화면을 구성하는 것이다.

  1. 클라이언트가 웹에 들어가면 서버는 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에 좋음.

단점

  1. 링크 이동 시 전체적인 웹사이트를 다시 서버에서 받아 보여주는 방식으로 깜빡임 현상이 있을 수도 있음. 현대에는 새로운 페이지를 받기 전까지 기존 페이지를 보여주는 형태로 발점함. 그렇지만 해당 페이지를 받아오는 데 시간(TTFB)이 오래 걸리면 사용자는 불편함을 겪음.(페이지 이동 시 로딩을 보여주고 서버 자원을 신경써야 함.)
  2. 사용자가 많아지거나 페이지 이동 요청이 많아지면 서버에 과부하가 걸림.
  3. TTV 이후에 TTI가 이루어지기 때문에 사용자의 클릭 이벤트 같은 인터랙션이 먹히지 않을 때가 있다.(hydration이 느려지는 경우)

출처

  • https://helloinyong.tistory.com/315
  • https://talkwithcode.tistory.com/17