Case 01
웹 애플리케이션 초기 로딩 속도 개선 및 리렌더링 최적화
515ms → 185ms
로드 시간
64% 단축
2.2MB → 5.7KB
리소스 크기
688회 → 338회
리렌더링
약 51% 감소
3.7s → 2.7s
FCP
12.4s → 10.2s
LCP
Problem
네트워크 탭을 분석한 결과 초기 페이지 로드 시 필요하지 않은 리소스까지 모두 로드되는 문제가 있었습니다. 또한 React Profiler로 확인한 결과, 발언자가 변경될 때마다 VideoFeed 컴포넌트가 불필요하게 리렌더링되어 한 라운드 진행 중 총 688회의 리렌더링이 발생했고 이는 게임 진행 중 체감되는 UI 반응성 저하로 이어졌습니다.
Solution
React.lazy와 Suspense로 코드 스플리팅을 적용해, 사용자의 실제 진입 경로(게임 페이지 중심)에 따라 필요한 컴포넌트만 동적으로 로딩되도록 했습니다. 폰트를 WOFF2 포맷으로 전환해 리소스 크기를 줄였습니다. React Profiler로 렌더링 병목을 분석한 뒤, props 변화가 없는데도 리렌더링되던 VideoFeed·VideoStream 등 주요 컴포넌트에 React.memo를 적용했습니다.
Result
코드 스플리팅과 폰트 최적화로 메인 페이지 기준 로드 시간이 515ms에서 185ms로 64% 단축되고, 리소스 다운로드 크기는 2.2MB에서 5.7KB로 크게 줄었습니다. Lighthouse 지표로도 First Contentful Paint가 3.7초에서 2.7초로, Largest Contentful Paint가 12.4초에서 10.2초로 개선된 것을 확인했고, Total Blocking Time은 최적화 전후 모두 0ms를 유지해 메인 스레드를 오래 막는 작업은 없었다는 것도 함께 확인했습니다. React Profiler로 측정한 결과, 게임 시작부터 1라운드 진행까지 VideoFeed 컴포넌트의 리렌더링 횟수가 688회에서 338회로 약 51% 감소했습니다.

최적화 전 · 네트워크 515ms · 2.2MB

최적화 후 · 네트워크 185ms · 5.7KB

최적화 전 · Lighthouse FCP 3.7s · LCP 12.4s

최적화 후 · Lighthouse FCP 2.7s · LCP 10.2s

최적화 전 · React Profiler 688회 렌더링

최적화 후 · React Profiler 338회 렌더링
기술적 의사결정
번들 크기 자체를 줄이는 대신 "실제 사용자 진입 경로"를 기준으로 코드를 나눈 이유는, 실시간 화상 게임 서비스 특성상 사용자 대부분이 게임 페이지에 머무는 시간이 압도적으로 길다는 점에 주목했기 때문입니다. 첫 진입 경로에 불필요한 코드를 걷어내는 것이 전체 번들을 균등하게 줄이는 것보다 체감 성능에 더 크게 기여했습니다.
트레이드오프
React.lazy/Suspense 기반 라우트 단위 코드 스플리팅 vs. 번들러 설정만으로 전체 번들 크기 축소
진입 경로가 명확한 서비스 구조상, 전체 최적화보다 게임 페이지 중심의 선택적 로딩이 체감 개선 폭이 컸습니다.
React.memo로 핵심 컴포넌트 리렌더링 방지 vs. 가상화 라이브러리 도입
문제의 원인이 리스트 렌더링 비용이 아니라 "불필요한 리렌더링"이었기 때문에, 근본 원인에 맞는 메모이제이션을 우선 적용했습니다.


