Files
2nd/10_Wiki/Topics/Frontend_Mastery/단일 페이지 애플리케이션(SPA) UI 성능 관리.md
T
2026-04-30 22:42:02 +09:00

5.4 KiB

단일 페이지 애플리케이션(SPA) UI 성능 관리

📌 brief Summary

단일 페이지 애플리케이션(SPA)은 클라이언트 사이드 렌더링(CSR)을 기반으로 동작하여 동적이고 부드러운 상호작용을 제공하지만, 초기 로드 속도가 느리고 자바스크립트 실행 비용이 크다는 단점이 있습니다 [1-4]. SPA UI 성능 관리는 브라우저의 중요 렌더링 경로(CRP)를 이해하여 비용이 큰 리플로우(Reflow)와 리페인트(Repaint)를 최소화하는 과정을 포함합니다 [5-7]. 또한, React와 같은 프레임워크의 가상 DOM(Virtual DOM) 구조, 자동 배칭(Automatic Batching), 동시성 렌더링 및 메모이제이션(Memoization) 기술을 활용해 불필요한 재렌더링을 방지함으로써 메인 스레드 차단을 막고 매끄러운 사용자 경험을 유지하는 것을 핵심 목적으로 합니다 [8-11].

📖 Core Content

SPA와 CSR의 성능적 특징 SPA는 클라이언트 사이드 렌더링(CSR)을 사용하여 브라우저가 최소한의 HTML을 받은 후 자바스크립트를 통해 동적으로 UI를 구성합니다 [1, 3, 12]. 이는 매끄러운 화면 전환과 풍부한 상호작용을 제공하지만, 사용자가 첫 화면을 보기 전(FCP)에 대규모 자바스크립트 번들을 다운로드하고 실행해야 하므로 초기 로딩 속도가 느리고 기기 성능에 의존하게 된다는 단점이 있습니다 [2, 4, 13].

브라우저 렌더링 경로(CRP) 최적화 화면에 UI를 렌더링하기 위해 브라우저는 HTML과 CSS를 파싱해 각각 DOM과 CSSOM 트리를 생성하고, 이를 결합하여 렌더 트리(Render Tree)를 만듭니다 [5, 14, 15]. 이후 화면 내 요소의 크기와 위치를 계산하는 레이아웃(Reflow) 과정과 픽셀을 그리는 페인트(Repaint) 과정을 거칩니다 [15-17]. 성능 최적화를 위해 리플로우를 유발하는 DOM 조작(너비, 높이, 마진 등 변경)을 최소화하고, DOM 업데이트를 일괄 처리해야 합니다 [7, 18-20]. 또한 애니메이션 처리 시 transform과 같은 속성을 사용해 GPU 가속을 활용함으로써 렌더링 파이프라인의 병목을 줄여야 합니다 [20-22].

가상 DOM과 메모이제이션(Memoization) 기법 직접적인 DOM 조작의 비효율성을 극복하기 위해 React는 가상 DOM(Virtual DOM)을 활용하여 실제 DOM과 동기화하는 휴리스틱 O(n) 알고리즘(Reconciliation)을 사용합니다 [8, 23-25]. 하지만 부모 컴포넌트의 상태가 변경되면 하위 트리의 모든 컴포넌트가 불필요하게 렌더링되는 '연쇄 재렌더링(Re-render Cascade)' 문제가 발생할 수 있습니다 [26-28]. 이를 방지하기 위해 얕은 비교를 수행하는 React.memo와 안정적인 참조를 유지하는 useMemo, useCallback을 선별적으로 적용해야 합니다 [29, 30]. 최신 React 19 컴파일러는 빌드 타임에 AST(Abstract Syntax Tree)를 분석하여 이러한 메모이제이션을 자동으로 삽입, 개발자의 수동 최적화 부담을 줄여줍니다 [31-33].

자동 배칭 및 동시성(Concurrent) 기능 활용 React 18에 도입된 자동 배칭(Automatic Batching)은 타이머, 프로미스, 네이티브 이벤트 핸들러 등에서 발생하는 여러 상태 업데이트를 단일 재렌더링 작업으로 묶어주어 불필요한 DOM 업데이트 횟수를 크게 줄입니다 [9, 10, 34, 35]. 더불어 [[useTransition]][[useDeferredValue]]와 같은 동시성 기능을 활용하면 무거운 계산 작업보다 사용자 입력과 같은 긴급한 UI 업데이트를 우선적으로 처리할 수 있어 애플리케이션의 반응성(INP)을 획기적으로 높일 수 있습니다 [36-39].

자원 및 번들 최적화 초기 로드 속도를 단축하기 위해 React.lazy()를 활용한 라우트 수준의 코드 스플리팅(Code Splitting)으로 자바스크립트 번들 크기를 줄이는 것이 중요합니다 [40]. 또한 100개 이상의 긴 목록을 렌더링할 때는 화면에 보이는 항목의 DOM 노드만 생성하는 가상화(Virtualization) 기술을 적용하면 렌더링 시간을 수 초에서 즉시 수준으로 단축할 수 있으며 [41, 42], DOM 트리 깊이를 줄이기 위해 불필요한 래퍼 대신 React.Fragment를 사용하는 것도 렌더링 효율을 높이는 방법입니다 [43-45].

🔗 Knowledge Connections

  • Related Topics: 클라이언트 사이드 렌더링(CSR), Critical Rendering Path (CRP), 가상 DOM과 Reconciliation, Reflow 및 Repaint 최적화
  • Projects/Contexts: React Compiler를 활용한 메모이제이션 자동화, React 18 자동 배칭 및 Concurrent 기능 적용, 긴 목록 렌더링 가상화(Virtualization)
  • Contradictions/Notes: 소스 [30]은 모든 컴포넌트에 무조건적인 수동 메모이제이션(useMemo 등)을 적용하는 것은 오버헤드를 발생시켜 오히려 성능을 떨어뜨릴 수 있으므로 프로파일링을 통한 선별적 적용을 주장합니다. 그러나 소스 [11, 46, 47]에 따르면 React 19 컴파일러의 등장으로 이러한 수동 메모이제이션 방식 자체가 구식이 되어가고 있으며, 컴파일러가 최적의 메모이제이션 지점을 자동으로 판단하므로 개발자는 복잡한 최적화 작업의 90%를 덜어낼 수 있다고 설명합니다.

Last updated: 2026-04-25