한 번 변환할 코드를 모두에게 보내지 않아
전통적인 클라이언트 React 앱은 화면을 만드는 컴포넌트 코드와 그 의존성을 방문자의 브라우저로 전부 보냈어. 글 하나를 HTML로 바꾸기 위해 Markdown 파서와 구문 강조기를 사용한다면, 변환은 한 번뿐인데도 모든 방문자가 그 라이브러리를 내려받고 실행해야 했지.
서버에 둘 때 얻는 네 가지
- 번들이 작아져. 서버 컴포넌트와 데이터 가공 라이브러리는 클라이언트 JavaScript에 0바이트를 더해.
- 데이터에 바로 닿아. 같은 프로세스나 데이터센터의 DB와 내부 서비스를 공개 API 왕복 없이 호출할 수 있어.
- 비밀이 서버를 떠나지 않아. API 키, DB 자격 증명, 내부 URL이 브라우저 번들에 섞일 길을 차단해.
- 준비된 부분부터 보낼 수 있어. 싼 부분은 즉시 보내고 느린 데이터가 도착하면 뒤이어 스트리밍해.
숫자로 보면 차이가 선명해
marked가 약 200KB, highlight.js가 약 800KB라고 해 보자. 클라이언트에서 글을 변환하면 방문자마다 약 1MB의 JavaScript 비용을 내. 서버 컴포넌트에서 변환하면 두 라이브러리는 전송량에 0바이트만 더하고, 브라우저는 완성된 HTML만 받아.
bundle analyzer에서 큰 클라이언트 의존성을 찾으면 먼저 그 라이브러리가 사용자 이벤트 뒤에도 필요한지 물어봐. Markdown 변환이나 날짜 묶음처럼 렌더 결과만 필요하면 서버 컴포넌트로 옮기고 직렬화된 결과만 내려. 옮긴 뒤 번들 크기뿐 아니라 서버 계산 시간과 캐시도 함께 측정해.
클라이언트 JavaScript 0바이트라는 문구가 전체 비용 0을 뜻하지 않아. 서버는 라이브러리를 실행하고 결과 HTML을 전송해야 하며, 요청마다 반복하면 compute가 커질 수 있어. 재사용 가능한 결과를 캐시하고, 정말 상호작용하는 부분만 브라우저에 남기는 균형이 필요해.
무거운 Markdown 라이브러리를 클라이언트와 서버에 각각 둔 두 build를 만들어 전송 JavaScript, 서버 응답, hydration 시간을 비교해. 요청마다 변환하는 버전과 캐시한 버전도 재서 비용이 브라우저에서 서버로 단순 이동한 건 아닌지 확인해. 같은 페이지를 서버 가공과 클라이언트 가공으로 각각 만들어 전송된 원자료와 JavaScript 크기를 비교해. 민감한 원본이 브라우저에 오지 않는지도 함께 확인해야 해.