Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[박승훈] 챕터 13: 렌더링 패턴 #109

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
210 changes: 210 additions & 0 deletions 챕터_13/박승훈.md
Original file line number Diff line number Diff line change
@@ -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에 대한 렌더링 전략부터 생소했던 스트리밍이나 아일랜드 등 다양한 렌더링 패턴에 대해 알아봤는데요, 정말 어질어질한 것 같아요. 많이 몰랐다는 걸 다시 체감하기도 했고, 그래서 이번 장은 공부하듯이 밑줄 치면서 읽고 정리하듯이 글을 정리했네요. 제 생각이 많이 담기지 않아서 아쉽기도 하지만, 이번 장을 접하며 지식을 잘 다져내고 싶다는 생각을 했어요.
Loading