From 62c049a62777a1f7dea93436849e4a7be504111d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=AE=E1=86=AB?= Date: Tue, 3 Dec 2024 18:43:53 +0900 Subject: [PATCH] =?UTF-8?q?Docs:=20=EB=B0=95=EC=8A=B9=ED=9B=88=2013?= =?UTF-8?q?=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\353\260\225\354\212\271\355\233\210.md" | 210 ++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 "\354\261\225\355\204\260_13/\353\260\225\354\212\271\355\233\210.md" diff --git "a/\354\261\225\355\204\260_13/\353\260\225\354\212\271\355\233\210.md" "b/\354\261\225\355\204\260_13/\353\260\225\354\212\271\355\233\210.md" new file mode 100644 index 0000000..11ae197 --- /dev/null +++ "b/\354\261\225\355\204\260_13/\353\260\225\354\212\271\355\233\210.md" @@ -0,0 +1,210 @@ +## 들어가며 + +> 다양한 렌더링 패턴에 대해 알아보고, 요구사항에 가장 적합한 패턴을 선택하기 + +- 콘텐츠를 어디서 렌더링할 것인가 : 웹 서버, 빋르 서버, 엣지 네트워크 또는 클라이언트 +- 콘텐츠를 어떻게 렌더링할 것인가 : 한 번에, 부분적으로, 점진적으로 + +## 렌더링 패턴의 중요성 + +- 뛰어난 사용자 경험을 제공하기 위해서는, 핵심 웹 지표(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에 대한 렌더링 전략부터 생소했던 스트리밍이나 아일랜드 등 다양한 렌더링 패턴에 대해 알아봤는데요, 정말 어질어질한 것 같아요. 많이 몰랐다는 걸 다시 체감하기도 했고, 그래서 이번 장은 공부하듯이 밑줄 치면서 읽고 정리하듯이 글을 정리했네요. 제 생각이 많이 담기지 않아서 아쉽기도 하지만, 이번 장을 접하며 지식을 잘 다져내고 싶다는 생각을 했어요. \ No newline at end of file