React 19 및 웹 성능을 위한 부분 수화 그 이상
Ethan Miller
Product Engineer · Leapcell

성능 병목 현상에 대한 소개
웹 개발의 까다로운 세계에서 사용자 경험은 무엇보다 중요하며, 느리게 로딩되는 웹사이트만큼 이를 저해하는 것은 없습니다. JavaScript 프레임워크로 구축된 최신 웹 애플리케이션의 경우, 초기 로드 시간은 클라이언트 측 수화 과정으로 인해 상당한 성능 저하를 동반하는 경우가 많습니다.
수화는 서버에서 렌더링한 정적 HTML에 이벤트 리스너를 연결하고 인터랙티브하게 만드는 행위입니다. 서버 측 렌더링(SSR)은 더 빠른 초기 콘텐츠 표시를 제공하지만, 후속 전체 애플리케이션의 전체 수화는 메인 스레드를 차단하여 답답할 정도로 응답하지 않는 경험으로 이어질 수 있습니다. 이 병목 현상은 사용자 참여, 전환율, 심지어 검색 엔진 순위에도 직접적인 영향을 미칩니다. 다행히 부분 수화와 같은 혁신적인 기술이 강력한 솔루션으로 등장하고 있으며, React 19와 같은 프레임워크가 이러한 진화의 선두에 서서 성능 좋은 웹 애플리케이션의 새로운 시대를 약속하고 있습니다.
부분 수화를 통한 성능 개선 분석
부분 수화가 웹 성능을 혁신하는 방법을 이해하려면 먼저 몇 가지 기본 개념을 정의해야 합니다.
주요 용어
- 서버 측 렌더링(SSR): 웹 페이지를 서버에서 렌더링하여 클라이언트 브라우저로 보내기 전에 처리하는 프로세스입니다. 이는 더 빠른 첫 번째 콘텐츠풀 페인트(FCP)와 더 나은 SEO를 제공합니다.
- 클라이언트 측 렌더링(CSR): 브라우저가 최소한의 HTML 페이지만 다운로드한 다음 JavaScript를 사용하여 클라이언트에서 페이지를 빌드하고 렌더링하는 프로세스입니다.
- 수화: SSR이 제공한 정적 HTML을 JavaScript로 '재수화'하고, 이벤트 핸들러를 연결하며, 애플리케이션을 인터랙티브하게 만드는 클라이언트 측 프로세스입니다. 전체 수화는 전체 DOM 트리와 모든 구성 요소를 처리하는 것을 포함합니다.
- 부분 수화: SSR로 렌더링된 페이지의 특정 인터랙티브 부분 또는 구성 요소만 전체 애플리케이션이 아닌 클라이언트에서 수화하는 기술입니다.
- 점진적 수화: 구성 요소가 뷰포트에서 보이는 위치나 우선 순위에 따라 단계별로 수화되는 부분 수화의 특정 형태입니다.
- **섬 아키텍처:**otherwise 정적인 HTML 페이지에 작고 독립적인 인터랙티브 구성 요소(섬)가 개별적으로 렌더링되고 수화되는 패턴입니다. Astro와 같은 프레임워크가 이 개념을 대중화했습니다.
- 선택적 수화: 종종 React의 부분 수화 접근 방식을 설명하는 데 사용되는 용어로, 단일 구성 요소 트리 내에서도 어떤 부분의 애플리케이션을 먼저 수화할지 우선 순위를 정합니다.
전체 수화의 문제점
전체 수화는 애플리케이션을 인터랙티브하게 만들기는 하지만, 종종 많은 양의 JavaScript를 다운로드하고 실행해야 합니다. 이 프로세스는 차단됩니다. 페이지 전체에 대한 모든 JavaScript가 다운로드, 구문 분석 및 실행될 때까지 페이지는 응답하지 않는 상태로 유지됩니다. 사용자는 콘텐츠를 볼 수는 있지만 버튼을 클릭하거나, 양식과 상호 작용하거나, 클라이언트 측 논리를 트리거할 수는 없습니다. 이 '상호 작용까지의 시간'(TTI) 메트릭은 매우 중요하며, 전체 수화는 종종 이를 연장합니다.
부분 수화의 힘
부분 수화는 사전에 실행해야 하는 JavaScript 양을 줄여 TTI 문제를 직접적으로 해결합니다. 모든 것을 수화하는 대신, 필요한 것만 전략적으로 수화합니다. 이는 다음을 유도합니다:
- 더 빠른 상호 작용까지의 시간: 사용자는 애플리케이션의 중요한 부분에 훨씬 더 일찍 상호 작용할 수 있습니다.
- JavaScript 페이로드 감소: 클라이언트에서 다운로드하고 구문 분석해야 하는 JavaScript 양이 줄어듭니다.
- 주요 스레드 차단 개선: 중요하지 않은 구성 요소의 수화를 연기함으로써 메인 스레드는 사용자 상호 작용을 위해 계속 사용할 수 있습니다.
React 19의 부분 수화 접근 방식: 선택적 수화
React 19는 React 18에 도입된 동시 렌더링 및 Suspense와 같은 기능을 기반으로 선택적 수화를 통해 부분 수화 개념을 더욱 정교하게 만듭니다. 이러한 발전 이전에 React는 깊이 우선 방식으로 구성 요소를 수화했습니다. 트리의 중간에 있는 구성 요소가 수화하는 데 느린 경우, 해당 구성 요소의 모든 형제 및 후속 구성 요소의 수화를 차단했습니다.
React 19는 React 18의 아키텍처 변경과 함께 React가 다음을 수행할 수 있도록 합니다.
- HTML이 도착하는 대로 수화 시작:
renderToReadableStream
및 Suspense와 같은 기능을 사용하면 React는 애플리케이션의 일부가 준비되는 즉시 HTML을 클라이언트로 스트리밍할 수 있습니다. - 수화 우선 순위 지정: HTML이 스트리밍되는 동안 React는 모든 것이 도착할 때까지 기다리지 않습니다. 이미 스트리밍된 구성 요소의 수화를 시작할 수 있습니다. 또한 사용자가 애플리케이션의 일부와 상호 작용하는 경우(예: 버튼 클릭), React는 아직 로드 중이거나 아직 상호 작용하지 않은 다른 구성 요소보다 해당 특정 구성 요소 및 해당 종속성의 수화를 우선시할 수 있습니다. 이것이 선택적 수화의 핵심입니다.
복잡한 댓글 섹션과 간단한 "장바구니에 담기" 버튼이 있는 페이지를 고려해 보세요. 전체 수화 시나리오에서는 잠재적으로 무거운 댓글 섹션의 JavaScript를 포함한 전체 페이지가 "장바구니에 담기" 버튼을 클릭할 수 있기 전에 수화해야 합니다. React 19의 선택적 수화를 사용하면 다음과 같습니다.
import { Suspense, lazy } from 'react'; // 이 컴포넌트는 서버 렌더링된 컴포넌트라고 가정 function ProductPage() { return ( <div> <h1>Product Title</h1> <ProductDetails /> <AddToCartButton productId="xyz" /> {/* 이 컴포넌트는 무겁고 로드하는 데 느릴 수 있습니다 */} <Suspense fallback={<LoadingComments />}> <LazyCommentSection /> </Suspense> </div> ); } const LazyCommentSection = lazy(() => import('./CommentSection')); // ProductDetails 및 AddToCartButton에서 이벤트 핸들러가 연결됩니다. // AddToCartButton과 상호 작용하는 경우 React는 해당 수화를 우선시합니다. // CommentSection의 수화는 보기 영역에 들어오거나 다른 중요 상호 작용 후에 연기될 수 있습니다.
이 예시에서 CommentSection
은 lazy
및 Suspense
를 사용하여 지연 로드됩니다. ProductPage
가 서버 렌더링될 때 ProductTitle
, ProductDetails
, AddToCartButton
의 HTML이 먼저 전송됩니다. LazyCommentSection
은 자리 표시자(예: LoadingComments
)를 갖게 됩니다. React는 ProductDetails
및 AddToCartButton
구성 요소의 HTML 세그먼트가 도착하는 즉시 해당 구성 요소를 수화합니다. 사용자가 AddToCartButton
을 클릭하면 React는 CommentSection
의 JavaScript가 백그라운드에서 다운로드 또는 구문 분석되는 동안에도 해당 버튼의 상호 작용 가능성을 높이는 데 리소스를 집중합니다.
이 접근 방식은 많은 인터랙티브 구성 요소가 있는 대규모 애플리케이션에 매우 유용하며, 사용자는 전체 페이지가 인터랙티브해질 때까지 기다리지 않고 중요한 요소와 상호 작용할 수 있습니다.
기타 프레임워크 및 섬 아키텍처
React 19가 선택적 수화를 정교하게 만드는 동안, Astro와 같은 다른 프레임워크는 강력한 형태의 부분 수화인 섬 아키텍처 패턴을 채택했습니다.
Astro와 같은 섬 아키텍처 프레임워크에서:
- 페이지의 대다수는 서버에서 렌더링된 순수한 정적 HTML입니다.
- 작고 독립적인 인터랙티브 구성 요소( "섬")만 클라이언트 측 JavaScript와 함께 제공됩니다.
- 각 섬은 독립적으로 수화될 수 있는 자체 포함 단위입니다.
블로그 게시물 페이지를 생각해 보세요. 기사 내용은 정적입니다. "좋아요" 버튼, 댓글 양식, 탐색 메뉴만 JavaScript가 필요할 수 있습니다. 전체 페이지를 수화하는 대신 Astro는 이러한 특정 "섬"만 수화합니다.
--- // Astro 컴포넌트 - 기본적으로 서버 측에서 생성됩니다. --- <main> <h1>My Blog Post</h1> <p>This is static content, no JS needed.</p> {/* 인터랙티브 React 컴포넌트 섬 */} <LikesButton client:load /> {/* 또 다른 인터랙티브 Vue 컴포넌트 섬 */} <CommentForm client:visible /> </main>
Astro의 경우 client:load
는 페이지가 로드되는 즉시 LikesButton
을 수화하도록 Astro에 지시합니다. client:visible
은 뷰포트에서 CommentForm
이 보일 때만 해당 컴포넌트를 수화하도록 Astro에 지시합니다. 수화에 대한 이러한 세분화된 제어는 초기 JavaScript 실행을 극적으로 줄여 탁월한 성능을 제공합니다.
실질적인 영향 및 이점
- 향상된 핵심 웹 바이탈: 부분 수화는 콘텐츠를 더 빠르게 제공하고 페이지를 더 빨리 인터랙티브하게 만들어 LCP(가장 큰 콘텐츠풀 페인트) 및 FID(첫 번째 입력 지연)와 같은 메트릭의 점수를 직접적으로 개선합니다.
- 최적화된 리소스 사용: JavaScript에 대한 네트워크 요청 감소, 구문 분석 및 실행에 대한 CPU 시간 감소.
- 향상된 사용자 경험: 페이지가 로드되는 순간부터 더 반응적이고 유연한 경험.
- 복잡성 관리: 새로운 패턴을 도입하지만, 인터랙티브 구성 요소를 격리하는 데 도움이 되어 특정 인터랙티브 부분의 디버깅 및 유지 관리를 잠재적으로 단순화합니다.
결론
부분 수화는 웹 성능을 위한 게임 체인저로, 전체 수화의 전부 아니면 전무 접근 방식에서 벗어나는 강력한 패러다임 전환을 제공합니다. React 19의 정교한 선택적 수화와 섬 아키텍처를 활용하는 다른 프레임워크는 무엇을과 언제 수화할지를 지능적으로 결정함으로써 더 빠르고 반응이 좋으며 궁극적으로 더 나은 웹 경험을 제공하는 데 중요한 발전을 이루고 있습니다. 프론트엔드 개발의 미래는 이러한 혁신적인 성능 향상 기술 덕분에 의심할 여지 없이 가볍고 인터랙티브할 것입니다.