Files
2nd/10_Wiki/Topics/Frontend/React Application Scaling.md
T

5.4 KiB

React Application Scaling

📌 Brief Summary

리액트 애플리케이션 스케일링(React Application Scaling)은 애플리케이션의 크기와 복잡성이 증가함에 따라 발생하는 아키텍처, 성능, 상태 관리, 그리고 협업 문제를 체계적으로 해결하는 과정입니다 [1-3]. 이는 단순히 렌더링 속도를 높이는 것을 넘어, 비즈니스 로직과 UI의 결합을 막고, 예측 가능한 폴더 구조를 도입하며, 불필요한 리렌더링과 번들 크기를 최적화하는 것을 포함합니다 [2-5]. 결과적으로 대규모 팀이 안정적이고 유지보수하기 쉬운 프론트엔드 시스템을 구축할 수 있도록 돕는 핵심 엔지니어링 패러다임입니다 [3, 6].

📖 Core Content

  • 구조적 아키텍처 및 폴더 구성 (Architectural Paradigms): 초기 리액트 앱은 컴포넌트나 훅을 기술적 파일 타입(Type-Based)으로 분리하지만, 앱이 커지면 기능 기반(Feature-Based) 또는 도메인 주도 구조로 전환해야 확장성을 확보할 수 있습니다 [7, 8]. 특히 **FSD(Feature-Sliced Design)**는 애플리케이션을 app, pages, widgets, features, entities, shared 등의 계층화된 슬라이스로 나누고, 하위 계층만 참조하도록 하는 단방향 의존성을 강제하여 코드 결합도를 낮추고 리팩토링을 용이하게 합니다 [9-11].
  • 상태 관리 아키텍처 (State Management Evolution): 단일한 전역 상태 도구에서 벗어나 데이터 특성에 맞는 도구를 선택해야 합니다 [12]. 테마나 로케일처럼 정적이고 변경이 적은 데이터는 Context API가 적합합니다 [13]. 반면 빈번하게 변경되는 동적 상태는 선택자(Selector) 패턴을 통해 리렌더링을 방지하는 Zustand가 유리하며, 복잡한 비동기 로직과 대규모 팀 협업에는 구조를 강제하는 Redux가 권장됩니다 [14-17]. 서버 상태 처리는 TanStack Query와 같은 API 계층용 도구로 완전히 분리해야 합니다 [16, 18].
  • 성능 및 번들링 최적화 (Performance & Bundling): 리액트는 상태나 프롭스가 변경될 때마다 하위 트리를 리렌더링합니다 [19]. 이를 방지하기 위해 React.memo, useCallback, useMemo를 전략적으로 사용하여 참조 안정성(Reference Equality)을 유지해야 합니다 [20, 21]. 초기 로딩 속도 개선을 위해서는 React.lazy와 라우트 레벨의 코드 스플리팅을 적용하고, Vite의 manualChunks를 활용해 React 코어 등 무거운 벤더 라이브러리를 별도 파일로 분리하여 캐싱 효율을 높입니다 [22-25]. 최근에는 React Compiler를 도입해 빌드 타임에 자동 메모이제이션을 수행하는 기법도 활용됩니다 [26-29].
  • 코드 품질 및 복원력 (Quality & Resilience): SOLID, DRY, KISS, YAGNI 원칙을 준수하여 컴포넌트를 단일 책임(SRP)을 갖도록 간결하게 유지합니다 [30-32]. 파일명은 운영체제 호환성을 위해 kebab-case를, 리액트 컴포넌트는 PascalCase를 사용하는 등 네이밍 컨벤션을 통일합니다 [33-36]. 또한 특정 컴포넌트의 렌더링 오류가 전체 앱을 다운시키는 것을 막기 위해 에러 바운더리(Error Boundaries)를 중요 UI 섹션마다 배치하여 Fallback UI를 제공하는 복원력 있는 설계가 필수적입니다 [37-39].

⚖️ Trade-offs & Caveats

  • 과도한 엔지니어링 (Over-Engineering): FSD나 Redux와 같은 고도화된 아키텍처와 상태 관리 도구를 소규모 프로젝트나 경험이 적은 팀에 도입하면, 학습 곡선이 크게 상승하고 불필요한 보일러플레이트 코드가 양산되어 오히려 개발 속도를 늦출 수 있습니다 [40-43].
  • 메모이제이션의 오용에 따른 성능 저하: React.memouseMemo를 무분별하게 사용하면, 이전 props 및 상태를 비교하는 과정에서 발생하는 연산 비용이 렌더링 비용 자체를 초과하여 오히려 애플리케이션의 성능을 악화시킬 수 있습니다 [44, 45].
  • React Compiler의 가시성 저하 및 호환성 제약: 자동화된 최적화 도구인 React Compiler는 블랙박스처럼 작동하므로 성능 병목 발생 시 디버깅이 더 까다로워집니다 [46]. 또한 매 렌더링 시 의도적으로 불안정한 참조를 반환하는 서드파티 라이브러리(예: React Router, TanStack Query 일부 훅)와는 최적화 호환이 깨질 수 있으며, React 규칙을 지키지 않은 레거시 코드베이스에서는 적용이 어렵습니다 [47, 48].
  • Context API의 리렌더링 폭풍 (Re-render Storm): Context API를 빈번하게 변하는 데이터 관리에 사용하면, 데이터 중 일부분만 변경되더라도 해당 컨텍스트를 구독하는 모든 하위 컴포넌트가 불필요하게 리렌더링되는 치명적인 성능 병목 현상을 유발합니다 [49, 50].

🔗 Knowledge Connections

[아키텍처 및 폴더 구조 (Architecture & Structure)]

  • Feature-Sliced Design (FSD)
    • 연결 이유: 확장 가능한 리액트 앱을 구축하기 위한 핵심 도메인 주도 아키텍처 방법론입니다.
    • 이 개념을 통해 더 깊게 이해할 수 있는 부분: 기능, 위젯, 엔티티를 분리하고 단방향 의존성 규칙을 강제하여 결