1. React의 변화흐름과 React18
- React의 핵심 추구사항(동시성을 활용한 메커니즘)을 적용하기 위한 첫 단계
동시성
Server Component
- 주요 변경 사항
automatic batching
startTransition
SSR 에서의 Suspense 지원
1.1) 동시성
내가 생각한(내가 이해한) 핵심은 여러 개의 Task를 잘게 쪼개어, 번갈아가며 수행하며, 마치 동시에 여러일 을 처리하는 것 처럼 작업을 수행하는 것.
- 여러개의 코어가 여러개의 Task를 처리하는 병렬적 방식과 대비되는 방법
- 다른 작업은 주로, 새로운 UI를 미리 준비하는 것
- 큰 렌더링 작업 중에도, side에서 input 변화와 같은 추가 UI 변경에 대한 작업을 동시처리 가능
- startTransition 등을 이용하여, 작업의 우선순위를 지정할 수 있다.
사용하는 입장에서는 ‘어떻게 화면에 보여줄 것인가’에서 ‘화면에 무엇을 보어줄 것이냐’로의 패러다임 전환
- 동시성 개념
- React가 동시에 여러 버전의 UI를 준비할 수 있게 해주는 새로운 비하인드 메커니즘입니다. (by react)
- 어떻게 화면을 보여줄 것에서 화면에 무엇을 보여줄 것이냐에 대한 패러다임의 전환
- React의 렌더링 모델의 update의 핵심

- 특징
- 렌더링과정에 개입할 수 있다는 것
- 기존 (single, uninterrupted, synchronous transaction)
- 렌더링이 한 번 시작되면, 사용자가 변화된 화면을 볼 때까지 개입할 수 없었다.
- blocking rendering 문제의 해결
- 개입된 상황에서도 일관된 UI를 보장할 수 있다. (suspense의 fallback)
- main thread를 block하지 않고, 백그라운드에서 새로운 UI를 준비한다.
- 기능
- "우선순위에 따른 화면 렌더", "컴포넌트의 지연 렌더" , "로딩 화면의 유연한 구성” 등 가능
- 명령형 컴포넌트 방식(기존)과 선언형 컴포넌트 방식(동시성) by kakaopay
- 명령형 프로그래밍은 “어떻게(How)”에 집중
- API 호출 상태에 따라 ‘화면을 어떻게 그릴지’ 고민
- 로딩일 때는 -게, 에러있을 때는 -게, 정삭적이면 -게 되는 것을 표현
- 선언형 프로그래밍은 “무엇을(What)”에 집중
- API 로딩 중과, 완료 상태에 따라 ‘무엇을 보여줄 지’를 선언
- 로딩상태일 때는 fallback, data가 받아왔음을 전제로 컴포넌트를 구성
- Error Boundary 컴포넌트
- 에러가 발생할 경우 보여줄 Fallback을 나타내는 컴포넌트
- ‘컴포넌트 내부’에서 state를 통해 에러 UI를 관리하는 것이 아니라, 에러가 발생하는 상황에서는 “에러에 해당하는 fallback”을 보여주어라와 같이 무엇을 보여줄지에 집중한다.
- 핵심은 컴포넌트 복잡도를 낮추고, 관심사를 분리한다는 것
예시
User
컴포넌트의 역할이이 컴포넌트 (및 하위 컴포넌트)를 UI로 어떻게 표현할 것인가
만 담당하느냐, 아니면이 컴포넌트의 UI를 어떻게 표현할 것인지, 그리고 하위 컴포넌트들에서 사용할 데이터들을 불러오기
를 담당하느냐의 기준으로 생각해보면 컴포넌트의 복잡도가 한층 낮아지고 관심의 분리 를 더 명확하게 달성할 수 있음이 느껴집니다.
1.2) 서버 컴포넌트 (Server Component)
server 컴포넌트는 server에서 필요 데이터를 fetching함으로 기존의 waterfall 문제를 해결하려는 시도
- 등장 배경 (문제/해결)
- 리액트 컴포넌트의 효율적인 Data fetching을 위한 방법
- Data fetching의 2가지 방식
- 1) 모든 정보를 부모 컴포넌트로 부터 받아, 내려주는 방식 2) 컴포넌트에 필요한 API를 각 컴포넌트에서 호출하는 방식
- 1번 방법은, API 요청수는 줄어들지만, 부모-자식 컴포넌트의 결합도가 높아져 유지보수가 어렵다.
- API가 변경되고, 컴포넌트 구조가 바뀐다면, over-fetching 문제 발생
- 2번 방법은, 필요한 데이터만을 보여줄 수 있다는 장점이 있지만, waterfall 현상 발생
- waterfall현상은 자식 컴포넌트들의 API 호출 및 렌더링으로 연속된 API 요청이 발생하고, 부모컴포넌트의 지연이 발생하는 현상
- 2번 방법의 문제 해결을 위해 Server Component 등장
- Server Componpnet는 client가 아닌 서버에서 동작하는 리액트 컴포넌트
- 서버에서 바로 API 요청을 하기 때문에, 시간/비용적인 효과
- 서버리소스 접근성
- DB, 파일시스템 등의 물리적으로 가깝게, 직접 접근 가능
- 제로 번들 사이즈 컴포넌트
- 컴포넌트 렌더링을 위해 필요했던 패키지들을 브라우저가 다운로드할 필요 없어지므로, 초기로딩 시간의 감소 가능
2. Suspense
- 개념
- Suspense는 React Component 내부에서 비동기적으로 다른 요소를 불러올 때 해당 요소가 불러와질 때까지 Component의 렌더링을 잠시 멈추는 용도로 사용할 수 있는 컴포넌트입니다.
- SSR과 Suspense
- CSR
- SSR 과정
- fetch data → Render as HTML → Load JS → Hydrate
- 서버 사이드 렌더링의 가장 큰 목적은 non-interactive한 버전의 클라이언트 컴포넌트를 최대한 빠르게 브라우저에 전달하여 초기 페이지의 First Contentful Paint 또는 Largest Contentful Paint 속도를 향상시는 것


- SSR 과정에서의 3가지 문제점
- 1) 모든 data fetching을 기다려야하는 문제
- Suspense를 통한 부분 data fetching
- 궁금한 점
- 일부는 Suspense 사용하고, 일부는 Suspense 해주지 않는다면 어떻게 로딩될까?
- fallback의 Spinner가 바뀌는 시점은 HTML 렌더이후? 혹은 Hydration 까지 완료된 이후?
- HTML렌더 이후 시점이다! (사용자는 Hydration 이전에 볼 수 있기 때문에)
- 2) js로드 이후에 hydration 과정이 가능했던 문제
- lazy와 Suspense의 React18 지원
- 선택적 Hydration
- ‘부하가 많이 걸리는 컴포넌트’ 혹은 ‘중요도가 떨어지는 컴포넌트’ 를 lazy 처리하여, 다른 컴포넌트들이 먼저 Hydration 할 수 있도록 설정
- Hydration 우선순위 자동 고려
- 클릭과 같은 상호작용이 발생한 컴포넌트가 우선적으로 Hydration이 진행되도록 한다.
- 궁금한점
- lazy란?
기타
1) useTransition
- debounce와 throttle과의 비교
- startTransition을 통한 우선순위의 지정
- 대규모 화면 업데이트 중의 응답성을 유지
- 상태 전환 중에, 적절한 피드백을 제공
- setTimeout과 다른 점
- setTimeout은 브라우저에서 처리되어 TaskQueue에 들어가기 때문에, 순서대로 작동하며 중간에 처리 및 취소 불가하다
참고
- 공식문서
- 우테코 React18
- React Server Component
- 동시성 UI Pattern