1. Intro
CSR, SSR 렌더링 방식에 대해 알아보고, 각각의 장단점을 알아보자.
2. Web Vitals terminology
자세히 알아보기 전에 이 포스트에서 이해를 편하게 하기 위한 약어를 정하고 넘어가자.
- Time To First Byte (TTFB) : 컨텐츠의 첫 데이터를 클라이언트가 받는데 걸리는 시간
- First Paint (FP) : 사용자가 첫 픽셀을 받는데 걸리는 시간
- First Contentful Paint (FCP) : 컨텐츠가 처음 보이기 시작하는 시간
- Largest Contentful Paint (LCP) : 페이지의 메인페이지가 로딩되는데 걸리는 시간
- Time To Interactive (TTI) : 페이지가 상호작용이 가능해지고, 사용자의 이벤트에 반응할 수 있게 되는 시간
3. 현재 랜더링 패턴
현재 React에서 가장 많이 사용되는 패턴은 Client-side rendering(CSR), Server-side rendering(SSR),
여기에 더해 nextjs같은 프레임워크에 사용하는
3.1 Client-Side Rendering (CSR)
next같은 메타 프레임워크가 나오기 전에는 create-react-app을 이용해 리액트 앱을 빌드할 때, 디폴트로 CSR 방식을 사용했다.
CSR 방식을 사용하면 서버는 모든 페이지에서 필수적인 script와 link tag가 있는 부분적인 HTML 만을 제공한다.
> 연관된 JS가 브라우저에 들어오면
> React는 트리를 랜더링하고 DOM 노드들을 생성한다.
> 라우팅과 데이터 fetching에 대한 로직도 client-side의 JS에서 다루어진다.
이렇기 때문에 CSR app은 처음 (데이터 fetching 같은게 필요없는) static한 요소들을 띄워주는 건 빠르지만, JS가 다운로드 되기 전까지는 기다려야 하는 시간이 있다. 그러고 나서도 데이터를 API로부터 fetch하고 유저에게 보여주는 걸 또 기다려야해서 LCP가 더 느려진다.
i) CSR의 장점
- static file은 CDN을 이용해 쉽게 랜더링할 수 있다.
( *CDN : content delivery network)
- client에서 랜더링이 끝나므로 전체 페이지를 다시 불러올 필요 없이 네비게이션을 제공할 수 있다.
- 첫 데이터 랜더링이 빠르므로 브라우저가 바로 font, css, JS를 로딩할 수 있다.
ii) CSR의 문제점
- client에서 모든 컨텐츠가 렌더링되므로, 사용자가 페이지의 컨텐츠를 보려면 다운로드와 처리를 거쳐야 한다. 이 과정에서 퍼포먼스가 느려진다.
- CSR 어플리케이션은 컴포넌트를 마운트하는데 데이터를 fetch하고, 첫 페이지 로딩 시 loading이 다수 진행될 경우가 많기 때문에 사용자 입장에서는 느리다고 느껴진다. child 컴포넌트들이 또 데이터 fetch가 필요할 경우는 더 심한데, 이는 parent 컴포넌트가 먼저 데이터를 fetch할때까지는 랜더링이 안되기 때문.
- SEO (serch engine optimization) 에서 불리하다. web crawler는 서버 랜더 HTML은 잘 읽지만, JS가 다운로드 되고, 그걸 실행하고 client side 데이터를 기다리고.. 하는 걸 하지 않기 때문. 인덱싱의 순서가 꼬일 수 있기 때문이다.
3.2 Server-side rendering (SSR)
‘renderToString’ 메소드를 이용해 데이터를 fetch하고, client-side의 js를 서버에서 구동함으로써, 페이지를 보여주는데 필요한 HTML을 모두 가져올 수 있다.
> 이 HTML을 이용해 첫 번쨰 컨텐츠를 렌더링한다.
> 이 후, client-side JS를 다운 받고 실행해서 페이지를 interactive하게 만들 server-generated HTML과 JS logic을 연결한다. (hydration)
( * hydration에 대해 좀 더 알고싶다면 여기로..)
먼저 html을 불러서 놓고, js를 받아와서 hydrate한다.
이외 next.js등이 사용하는 SSG, ISR 방식이 있다.
(* SSG : Static Site Generation - 빌드시 페이지를 미리 생성하고, 클라이언트가 요청할 때 이를 줌)
(* ISR : Increment Static Regeneration - 빌드 시점에 페이지를 렌더링 한 후, 설정한 시간마다 페이지를 새로 렌더링)
i) SSR의 장점
- 서버에서 HTML이 이미 생성되어 있고, web crawler가 이를 가져오는 것에 문제가 없으므로 SEO가 훨씬 유리하다.
- FCP, LCP가 나름 빠르다. CSR app에 비해 사용자가 텅 빈 스크린을 보는 시간이 그나마 적다.
ii) SSR의 단점
- 우선 모든 요청마다 페이지를 서버에서 처음 렌더링하고 그 페이지에 필요한 데이터를 기다려야 하기 때문에 TTFB가 느리다. 요청이 한 번에 많이 들어오거나 서버 코드가 깨끗하지 않을 경우 사용자가 로딩을 기다리는 시간이 길어진다. 이는 SSG, ISR처럼 미리 응답으로 줄 데이터를 캐싱해두더라도 예외는 아니다.
- 첫 로딩은 빠를지라도, 사용자는 페이지와 상호작용을 위해 필요한 JS가 다운로드 되길 기다려야한다.
(*cache : 데이터나 값을 미리 복사해두는 임시 장소. 캐시의 접근 시간에 비해 원본 데이터에 접근하는 시간이 길거나, 값을 다시 계산하는 데 걸리는 시간을 절약하고 싶을 때 사용)
이렇기 때문에 TTFB가 좀 오래 걸리는데, 우선 서버에서 데이터를 fetch하고 이를 html로 바꿔야 하기 때문