아래 글을 읽으면서 정리한 글입니다.
https://web.dev/rendering-on-the-web/
개발하면서 앱 로직과 렌더링을 어디서 해야하는가에 대한 고민은 중요합니다. 어려운 부분이지만 웹사이트를 만드는 방법은 너무나도 다양합니다. 크롬에서는 개발자들에게 서버 렌더링이나 정적 렌더링을 권고하고 있습니다. 이를 제대로 이해하기 위해서는 각각의 방법을 이해해야 하고, 용어를 잘 알고 있어야 합니다.
SSR
: server side rendering, 클라이언트 사이드나 유니버설 앱을 서버에서 HTML로 렌더링합니다.CSR
: client side rendering, 브라우저에서 앱을 렌더링 합니다. 보통 DOM을 사용합니다.Rehydration
: 클라이언트에서 JavaScript 뷰를 "booting up"하여,서버에서 렌더된 HTML 돔 트리와 데이터를 재사용할 수 있도록 합니다.Prerendering
: 빌드타임에 클라이언트 사이드에서 실행되는 앱으로, 정적 HTML로 초기 상태를 캡쳐합니다. TTFB
: Time to First Byte, 링크를 클릭해서 콘텐츠의 첫번째 비트가 들어오는 시간FP
: First Paint, 사용자가 볼 수 있는 픽셀이 처음으로 보여지는 시간 FCP
: First Contentful Paint, 요청된 콘텐츠(글 body 등)가 보이는 시간TTI
: Time To Interactive, 페이지가 interactive(이벤트 연결 등)해지는 시간서버 렌더링은 네비게이션에 대한 응답으로, 서버에서 전체 HTML 페이지를 생성합니다.
서버 렌더링 vs 클라이언트 사이드 렌더링에 대한 논쟁은 많지만, 서버 렌더링은 페이지에 따라 선택할 수 있다는 걸 기억해야 합니다. Netflix
의 경우, 정적 랜딩 페이지를 서버 렌더링하고, interaction이 있는 무거운 페이지있는 JS는 prefecthing하여 클라이언트 렌더링 페이지가 빨리 로딩될 수 있도록 합니다.
리액트의 경우 renderToString()
이나 Next.js
를 사용해서 서버 렌더링을 할 수 있고, 뷰의 경우 서버렌더링 가이드나 Nuxt
, 앵귤러의 경우 Universal
이 있습니다. 많이 쓰이는 이러한 툴들은 hydration
을 어떤 형태로든 쓰고 있기 때문에 사용시 잘 고려해보아야 합니다.
정적 렌더링은 빌드타임에 일어나기 때문에, FP, FCP, TTI가 빠릅니다. 서버 렌더링과는 달리 TTFB가 빠른데, 그 이유는 HTML 페이지가 생성되지 않아도 되기 때문입니다. 보통, 정적 렌더링이라 함은, 각 URL 마다 HTML 파일을 생성하는 것을 의미합니다. HTML 응답으로 미리 만들어진 파일은 정적 렌더를 통해서 edge-caching의 이점을 취하기 위해 여러 CDN을 통해 배포될 수 있습니다.
정적 렌더링의 단점중 하나는 모든 URL에 맞는 HTML 파일이 있어야 한다는 것입니다. 미리 URL을 알기 어렵거나 색다른 페이지가 많은 큰 사이트의 경우 이는 어려운 문제일 수 있습니다.
정적 렌더페이지는 클라이언트 JS를 실행하지 않고도 interactive할 수 있지만, SPA의 FP or FCP를 향상시켜주는 프리렌더링의 경우 클라이언트가 booted
되어야만 페이지가 interactive 해집니다.
서버렌더링만이 무조건 해결책인 것은 아닙니다. 서버 렌더링의 경우 flush가 일찍 일어나지 않고, TTFB가 지연될 수 있고, 전송되는 데이터가 많아질 수 있습니다.
리액트의 경우, renderToString()
는 동기적으로 실행되고 싱글스레드기 때문에 느릴 수 있습니다. 서버 렌더링을 "올바르게"한다는 것은, 컴포넌트 캐싱, 메모리 사용 관리, 메모이제이션 기술 등을 고려하는 것입니다. 서버 렌더링으로 화면이 더 빨리 보인다고 해서 신경을 덜 써도 된다는 것이 아닙니다.
서버 렌더링은 요청한 URL마다 HTML을 생성하지만, 정적 렌더링 콘텐츠보다는 느릴 수 있습니다. 좀 더 시간을 들여,서버 렌더링 + HTML 캐싱
작업을 한다면 서버 렌더리 시간이 엄청나게 감소할 수 있습니다.
서버 렌더링의 좋은점은 더 많은 "live" 데이터를 끌어와서 정적 렌더링보다 더 많은 요청에 대응하는 응답을 한다는 것입니다. 사람마다 다른 페이지를 보여주는 페이지의 경우 정적 렌더링과 잘 맞지 않습니다.
CSR은 자바스크립트를 이용해서 브라우저에서 바로 페이지를 렌더링하는 것을 말합니다. 모든 로직, 데이터 fetching, 템플릿 구성, 라우팅이 모두 서버가 아닌 클라이언트에서 이루어집니다.
클라이언트 사이드 렌더링의 경우 모바일에서 빠르게 만들기 어려울 수 있습니다. <linke rel=preload>
를 사용해서 중요한 스크립트나 데이터를 빨리 전달할 수도 있는데, 그러면 파서parser가 더 빨리 일을 시작합니다. PRPL과 같은 패턴으로 빠르게 느껴질 수 있도록 할 수 있습니다.
CSR의 안좋은 점은, 앱이 커짐에 따라 필요한 JS또한 커진다는 것입니다. 특히 최신 JS 라이브러리의 경우, 폴리필,서드 파티 등으로 더 어려워질 수 있습니다.대용량 JS 번들에 의존하는 경우, code-splitting을 고려해야하고, lazy-load JavaScript(필요한 것을, 필요할때 사용하기
)를 사용해야 합니다.
interactivity가 거의 없는 애플리케이션의 경우, 서버 렌더링이 더 좋은 해결책이 될 수 있습니다.