TOC
- 참고
- 들어가며
- 렌더링 패턴의 중요성
- 클라이언트 사이드 렌더링(CSR)
- 서버 사이드 렌더링(SSR)
- 정적 렌더링
- 스트리밍 SSR
- 엣지 SSR
- 하이브리드 렌더링
- 점진적 하이드레이션
- 아일랜드 아키텍처
- 리액트 서버 컴포넌트
- 총평
참고
본 내용은 자바스크립트+리액트 디자인 패턴(링크) 를 읽고 정리한 내용입니다. 책의 내용과 함께 개인적인 의견과 생각을 담아 작성하였습니다.
들어가며
다양한 렌더링 패턴에 대해 알아보고, 요구사항에 가장 적합한 패턴을 선택하기
- 콘텐츠를 어디서 렌더링할 것인가 : 웹 서버, 빋르 서버, 엣지 네트워크 또는 클라이언트
- 콘텐츠를 어떻게 렌더링할 것인가 : 한 번에, 부분적으로, 점진적으로
렌더링 패턴의 중요성
- 뛰어난 사용자 경험을 제공하기 위해서는, 핵심 웹 지표(CWV:Core Web Vitals)를 준수해야 함
항목 | Full Name | 내용 |
---|---|---|
TTFB | Time to First Byte | 페이지 콘텐츠의 첫 번째 바이트를 받는 데 걸리는 시간 |
FCP | First Contentful Paint | 페이지 콘텐츠의 첫 번째 요소를 렌더링하는 데 걸리는 시간 |
TTI | Time to Interactive | 페이지 로드 시작부터 상호작용 가능한 상태가 되는 시점 |
LCP | Largest Contentful Paint | 페이지 콘텐츠 중 가장 큰 요소를 렌더링하는 데 걸리는 시간 |
CLS | Cumulative Layout Shift | 페이지 콘텐츠의 레이아웃이 변경되는 빈도 |
FID | First Input Delay | 사용자가 페이지와 상호작용한 이후로 이벤트 핸들러가 실행되는 데 걸리는 시간 |
- CWV 지표는 사용자 경험과 가장 관련이 높은 요소들을 측정
- CWV를 최적화하면 뛰어난 UX와 SEO 보장 가능
클라이언트 사이드 렌더링(CSR)
특징
- 모든 UI가 클라이언트에서 생성
- 전체 웹앱이 처음 요청 시에 모두 로드
장점
- 페이지 렌더링을 위한 새로운 요청을 서버로 보내지 않음
- 페이지간 라우팅이 빠른 편
단점
- 페이지의 복잡도가 증가하면 페이지 렌더링에 필요한 JS 코드의 복잡성과 코드도 증가
- 큰 JS 번들을 만들어 FCP와 TTI가 증가
- 크롤러가 색인하기 전에 렌더링이 안 되어 SEO에 좋지 않음
서버 사이드 렌더링(SSR)
특징
- 모든 요청마다 HTML 생성
- 모든 콘텐츠가 서버에서 렌더링
- 가장 고전적인 웹 콘텐츠 렌더링 방식
- 페이지 렌더링을 위한 새로운 요청을 서버로 보냄
- 모든 요청이 독립적으로 처리, 서버에 의해 새로운 요청으로 간주됨
활용
- 사용자 쿠키 정보나 요청 데이터를 기반으로 하는 등, 개인 맞춤형 데이터를 포함하는 페이지에 적합
- 인증 상태에 따라 렌더링 여부를 결정해야 하는 페이지에도 적합
단점
- 서버의 데이터 처리 능력은 주어진 시간에 모든 사용자가 공유
- 페이지간 라우팅이 느림
핵심 원칙
- HTML을 서버에서 렌더링하고 클라이언트에서 다시 하이드레이션하는데 필요한 JS를 함께 제공
- 하이드레이션에는 비용이 따르기 때문에, SSR은 언제나 하이드레이션 과정을 최적화하려고 함
정적 렌더링
- 전체 페이지의 HTML을 빌드 시점에 미리 생성
- 다음 빌드 때까지 변경되지 않음
- 정적 콘텐츠는 CDN이나 엣지 네트워크에 쉽게 캐싱
- 일반적인 SSR에 비해 페이지 요청을 처리, HTML 렌더링 및 응답 시간이 단축
- 기본적으로 순수 정적 렌더링은 동적 데이터 포함하지 않음
점진적 렌더링(ISR)
- 정적 렌더링과 SSR을 결합한 방식
- 정적 페이지만 미리 렌더링
- 동적 페이지는 사용자 요청 시에 on-demand 방식으로 렌더링
- 빌드 시간 단축 및 주기적으로 캐시 갱신으로 페이지 재생성 가능
새로운 페이지 추가 허용
- 빌드 후 웹사이트에 새로운 페이지를 추가하기 위해 지연 로딩 사용
- 새로운 페이지는 첫 요청 즉시 생성
기존 페이지 업데이트
- 각 페이지에 적절한 타임아웃 정의
- 시간이 경과할 때마다 페이지가 다시 유효한지 검증
- 페이지 재검증이 완료될 때까지 사용자는 이전 버전 페이지를 계속 보게 됨
SWR(Stale-While-Revalidate)
패턴 사용
On-demand ISR
- 정해진 시간 간격이 아니라 특정 이벤트 발생 시에 페이지가 재생성
- 엣지 네트워크 전체에 페이지를 다시 생성하고 재분배하여, 전 세계 사용자가 최신 버전의 페이지 확인 가능
- (일반 ISR에서는 해당 페이지에 대한 사용자 요청을 처리한 엣지 네트워크 노드에서만 캐시)
- 불필요한 페이지 재생성과 서버리스 함수 호출 방지 가능
스트리밍 SSR
현재 페이지에 필요한 마크업을 모두 담은 큰 HTML파일 하나를 작은 조각(chunk)로 나눠 전송
- Node.js의 스트림 기능을 사용하면 응답 객체에 데이터를 스트리밍 가능
- 클라이언트에 데이터를 지속적으로 전송할 수 있음
- 클라이언트는 데이터 조각을 받는 즉시 콘텐츠 렌더링 시작 가능
열악한 환경에서의 스트리밍
- 네트워크의 혼잡으로 바이트 전송이 불가한 경우, 렌더러는 신호를 받아 스트리밍 중단
- 서버는 메모리를 덜 사용하고 I/O가 필요한 상황에 더욱 민첩하게 반응 가능
- 무거운 요청이 가벼운 요청을 장시간 차단하는 것을 방지
- 열악한 환경에서도 사이트가 빠른 응답성을 유지하도록 보장
React에서의 스트리밍
2016년에 출시된 리액트 16부터 스트리밍 지원
ReactDOMServer.renderToNodeStream()
메서드 사용ReactDOM.hydrate()
메서드로 페이지 하이드레이션ReactDOMServer.renderToStaticMarkup()
메서드로 정적 페이지 스트리밍
엣지 SSR
- CDN의 모든 지역에서 서버 렌더링을 가능케 함
- 콜드 부트 시간을 거의 0에 가깝게 줄여줌
- 콜드 부트 : 함수가 처음 실행될 때 발생하는 지연 시간
- 서버리스 함수를 사용하면 전체 페이지를 서버 사이드에서 생성 가능
- 엣지 런타임은 HTTP 스트리밍도 지원
하이브리드 렌더링
- 어떤 상황에서든 최적의 결과를 제공하기 위해 여러 가지 렌더링 방식을 결합
- 정적으로 제공될 수 있는 페이지는 미리 렌더링, 다른 페이지에서는 동적인 전략 선택 가능
- 제공되는 기능에 따라 다른 진영으로 쉽게 전환 가능
점진적 하이드레이션
- 각 노드를 시간에 따라 개별적으로 하이드레이션
- 필요한 최소한의 JS만 요청하는 방식
- 페이지의 상대적으로 덜 중요한 부분의 하이드레이션 지연
- 사용자에게 필요한 노드만 하이드레이션
완전한 점진적 하이드레이션을 위한 요구사항
- 모든 컴포넌트에 SSR 사용 가능
- 개별 컴포넌트 또는 조각 단위로 코드 스플리팅 지원
- 개발자가 정의한 순서대로 클라이언트 사이드에서 각 조각 별 하이드레이션 지원
- 이미 하이드레이션된 조각에서 사용자 입력 가능 상태 유지
- 지연된 하이드레이션이 적용되는 조각에 로딩 중임을 표시 가능
React에서의 점진적 하이드레이션
- 동시성 모드로 위의 요구사항 충족 가능
- 여러 작업을 동시에 처리하면서도 우선순위에 따라 작업간 전환 가능
- 더 높은 우선순위의 작업(ex. 사용자 입력)이 필요하면 하이드레이션(낮은 우선순위)을 일시 중단하고 작업 전환
아일랜드 아키텍처
- 정적인 HTML 위에 독립적으로 전달될 수 있는 상호작용 아일랜드를 통해 자바스크립트의 전송량을 줄이는 패러다임
- 컴포넌트 기반 아키텍처
- 정적, 그리고 동적 아일랜드로 구분된 페이지 뷰 제안
- 정적 콘텐츠 위에 상호작용 영역이 구분 가능하게 흩어져 있는 형태로 구성되는 게 일반적
특징
- 정적 콘텐츠로 이루어진 페이지의 SSR을 지원
- 렌더링된 HTML에는 동적 콘텐츠를 위한 자리가 미리 마련
- 이 자리에는 자체적으로 완성된 컴포넌트 위젯이 위치
- 각 위젯은 독립적인 앱처럼 동작, 서버에서 렌더링된 결과물과 클라이언트에서 위젯을 활성화하는 데에 사용될 JS 코드를 포함
장점
성능
- 클라이언트에 전송되는 JS 코드의 양 감소
- 상호작용이 필요한 컴포넌트에만 스크립트 전송
- 전체 페이지의 가상 DOM을 다시 생성하고 모든 요소를 하이드레이션하는 데 필요한 스크립트보다 필요한 코드의 양이 훨씬 적음
- 페이지 로드 시간의 단축
SEO
- 모든 정적 컨텐츠가 서버에서 렌더링
- SEO에 유리
컴포넌트 기반
- 재사용성과 유지보수 용이성과 같은 컴포넌트 기반 아키텍처의 모든 이점을 제공
단점
- 아직 개발이 초기 단계에 머무름
- 상호작용을 위주로 한 페이지에는 적합하지 않음
리액트 서버 컴포넌트
서버 주도 방식으로 현대적인 사용자 경험을 제공하는 것이 목표
- 서버에서 실행되도록 설계
- 상태를 가지지 않는 리액트 컴포넌트
- 번들 크기를 0으로 줄임
- 서버 컴포넌트와 클라이언트 컴포넌트 사이의 매끄러운 코드 전환 경험(knitting) 가능
- 기존의 SSR 방식과 차별화
- 클라이언트 사이드 JS 번들의 크기를 크게 줄임
총평
이번에는 잘 알고 있던 CSR, SSR에 대한 렌더링 전략부터 생소했던 스트리밍이나 아일랜드 등 다양한 렌더링 패턴에 대해 알아봤는데요, 정말 어질어질한 것 같아요. 많이 몰랐다는 걸 다시 체감하기도 했고, 그래서 이번 장은 공부하듯이 밑줄 치면서 읽고 정리하듯이 글을 정리했네요. 제 생각이 많이 담기지 않아서 아쉽기도 하지만, 이번 장을 접하며 지식을 잘 다져내고 싶다는 생각을 했어요.