1. 서론
React 18에서는 많은 기능이 추가되고 기존 기능이 변화되었다. 특히 Suspense의 기능과 작동 방식에 큰 변화가 있어, 이를 이해하면 React 애플리케이션의 퍼포먼스와 사용자 경험을 크게 향상시킬 수 있다. 이번 글에서는 React 18에서 변경된 Suspense의 작동 원리와 주요 특징에 대해 알아보겠다.
2. Suspense의 기본 개념
Suspense는 React 컴포넌트의 일부가 아직 준비되지 않은 경우 React가 표시할 내용을 선언적으로 지정할 수 있게 해주는 기능이다. 예를 들어, 다음과 같이 사용할 수 있다
<Suspense fallback={<loading />}>
<RightColumn>
<ProfileHeader />
</RightColumn>
<LeftColumn>
<Suspense fallback={<LeftColumnGlimmer />}>
<Comments />
<Photos />
</Suspense>
</LeftColumn>
</Suspense>
위 코드는 특정 컴포넌트가 로딩 중일 때 fallback으로 지정한 요소를 화면에 표시한다. 이때 Suspense는 마치 JavaScript의 catch 블록처럼 작동하며, 가장 가까운 상위 Suspense 컴포넌트가 ‘캐치’하여 준비되지 않은 콘텐츠를 대체한다.
React 16.6.0에서는 Suspense가 React.lazy를 통한 코드 스플리팅에만 사용될 수 있었으나, React 18에서는 Promise를 지원하도록 확장되었다. 이제는 어떤 컴포넌트라도 비동기로 준비되지 않은 상태라면 Promise로 인해 Suspense에 잡히게 되며, Suspense는 이를 적절한 로딩 상태로 대체할 수 있게 된다. 이로 인해 다양한 비동기 데이터 소스와 더 유연하게 통합될 수 있게 되었다.
2.1 서버 사이드 렌더링과 스트리밍 지원
React 18에서는 서버 사이드 렌더링에 스트리밍 기능을 추가했다. 기존의 서버 렌더러는 HTML을 한 번에 문자열로 반환해 pipe를 block하여 bottleneck이 되는 문제가 있었다. 새로운 서버 렌더러는 HTML 스트림을 생성하여 필요한 부분부터 점진적으로 렌더링할 수 있다. 이렇게 하면 메인 번들이 준비되자마자 하이드레이션을 시작할 수 있어 초기 로딩 성능을 크게 향상시킬 수 있다.
새로운 서버 렌더러는 Suspense와 완벽히 통합되어, 클라이언트와 서버 모두에서 로딩 상태를 선언적으로 관리할 수 있게 되었다.
2.2 Transitions와 기존 콘텐츠 유지
React 18에서 Suspense가 중요한 이유는 업데이트 중에도 기존 UI를 유지할 수 있도록 하는 Transitions 기능과 관련이 있다. Transitions는 React가 특정 상태 변화를 ‘비긴급 업데이트’로 처리하도록 지시할 수 있는 기능이다. 예를 들어, 탭 전환과 같은 상황에서 ‘댓글’ 탭을 로딩하는 동안 기존 UI를 유지하고, 준비가 완료되면 새로운 콘텐츠로 자연스럽게 전환하는 방식이다.
Transitions 기능은 Suspense와 결합되어 기존 콘텐츠를 유지하면서 로딩 피드백을 제공할 수 있게 해준다. 예를 들어, useTransition 훅은 [isPending, startTransition] 튜플을 반환하며, isPending으로 사용자에게 로딩 중임을 시각적으로 표시할 수 있다.
2.3 Suspense 경계와 새로운 업데이트 로직
React 18에서는 Suspense 경계가 기존 콘텐츠를 유지하면서 새 콘텐츠를 준비할 수 있도록 개선되었다. 기본적으로 Suspense는 콘텐츠를 처음 렌더링할 때만 fallback을 보여주며, 기존 콘텐츠가 있을 경우 다시 fallback을 보여주지 않는다. 이로 인해 로딩 중임에도 불구하고 기존 UI를 유지할 수 있다.
하지만, 경우에 따라 강제로 fallback을 다시 보여주어야 할 때도 있다. 이 경우, Suspense 경계에 변하는 key 값을 할당하여 매번 새로운 경계로 렌더링되도록 설정할 수 있다. 이렇게 하면 매번 새로운 fallback이 표시된다.
2.4 레이아웃 효과의 변경
React 18에서는 Suspense와 관련된 레이아웃 효과의 처리 방식이 개선되었다. 이제 콘텐츠가 숨겨지거나 나타날 때에만 레이아웃 효과가 다시 실행된다. 이로 인해 레이아웃 관련 로직이 Suspense로 인해 중단되거나 비정상적으로 동작하는 문제를 줄일 수 있다. 예를 들어, AutoSize와 같은 레이아웃 관련 컴포넌트가 예상한 대로 동작하게 된다.
3. React 18으로의 전환
React 18로 업그레이드하면 Suspense와 관련된 새로운 기능을 사용할 수 있다. 기존 ReactDOM.render에 ReactDOM.createRoot로 전환하고, 서버 렌더링에서는 ReactDOMServer.renderToString 대신 ReactDOMServer.renderToPipeableStream을 사용하면 스트리밍 및 새로운 하이드레이션 기능을 적용할 수 있다.
4. Reference
- Reactjs RFCs. (n.d.). RFCs/text/0213-suspense-in-react-18.md at main. Retrieved from https://github.com/reactjs/rfcs
- React Blog. (2022, March 29). React v18 [Blog post]. Retrieved from https://react.dev/blog/2022/03/29/react-v18
- Vercel. (n.d.). Instant Search Params with React Server Components. Retrieved from https://vercel.com
'React' 카테고리의 다른 글
React useState의 동작방식과 Lazy Initialization (0) | 2024.11.16 |
---|---|
React.memo에 대하여 (1) | 2024.11.16 |
React에서 hook을 통해 결합도 줄이기 (0) | 2024.11.04 |
React Custom Hook에 대하여 (1) | 2024.10.28 |
React에서 virtual dom을 쓰는 이유 (2) | 2024.10.07 |