Conceptly
← 전체 목록
✂️

Code Splitting

performance번들을 분리해 초기 로드를 줄이는 성능 패턴

Code Splitting은 빌드 결과물인 JavaScript 번들을 여러 청크로 나누고, 각 청크를 필요한 시점에만 내려받는 성능 최적화 기법입니다. SPA가 앱 전체 코드를 하나의 번들로 묶는 방식의 한계를 극복하기 위해 등장했습니다.

아키텍처 다이어그램

🔍 구조 다이어그램

점선 애니메이션은 데이터 또는 요청의 흐름 방향을 나타냅니다

왜 필요한가요?

SPA는 앱 전체 코드를 단 하나의 번들로 만들어 처음 방문 시 한꺼번에 내려받습니다. 앱이 커질수록 이 번들도 커져서, 사용자가 첫 페이지 하나만 보려고 해도 회원가입, 관리자 화면, 통계 대시보드의 코드까지 모두 받아야 합니다. 번들이 수백 킬로바이트를 넘으면 JavaScript 파싱과 실행 시간이 늘어나고, 느린 네트워크 환경에서는 빈 화면이 몇 초씩 지속됩니다. 기능을 추가할수록 모든 사용자의 초기 로딩이 함께 느려지는 구조입니다.

왜 이런 방식이 등장했나요?

웹 초창기에는 각 페이지마다 HTML과 스크립트를 별도로 내려받는 방식이라 번들 크기 문제가 없었습니다. React, Angular 같은 SPA 프레임워크가 등장하면서 클라이언트가 앱 전체 로직을 담당하게 됐고, 번들 크기는 자연스럽게 성능의 병목이 됐습니다. 초기에는 vendor chunk 분리 정도로 대응했지만, 앱 규모가 커지면서 라우트나 기능 단위로 필요한 코드만 그때그때 내려받는 방식이 필요해졌습니다. webpack의 dynamic import() 지원과 ECMAScript 표준화(2020)를 거치면서 이 패턴이 생태계 전반의 기본 최적화 방식으로 자리잡았습니다.

내부적으로 어떻게 동작하나요?

Code Splitting은 빌드 과정에서 번들을 여러 청크로 나누고, 각 청크를 런타임에 필요한 시점에 로드하는 방식입니다. 빌드 도구는 코드에서 `import('./SomeComponent')`처럼 dynamic import를 만나면 그 모듈과 의존성을 별도 청크 파일로 분리합니다. 빌드 결과물로는 최초 페이지 로드에 반드시 필요한 Initial Chunk와, 나중에 필요할 때 받는 Lazy Chunk들이 생깁니다. 브라우저에서 해당 라우트에 진입하거나 특정 기능을 사용하는 시점이 되면, JavaScript 런타임이 그 청크의 URL로 네트워크 요청을 보내고 받아서 실행합니다. 이미 받은 청크는 브라우저 캐시에 남기 때문에 다음 방문에서는 다시 내려받지 않습니다. React에서는 `React.lazy()`와 `Suspense`를 조합하면 컴포넌트 단위로 이 패턴을 선언적으로 쓸 수 있습니다. 로딩 중에 보여줄 fallback UI를 Suspense가 처리하므로 빈 화면을 피할 수 있습니다.

경계와 구분

Code Splitting과 Tree Shaking은 둘 다 번들 크기를 줄이는 기법이지만 접근이 다릅니다. Tree Shaking은 빌드 시점에 실제로 사용되지 않는 코드를 정적 분석으로 제거하는 방식이라, 결과 번들은 하나지만 쓰지 않는 코드가 빠집니다. Code Splitting은 코드 제거가 아니라 분할입니다. 앱이 실제로 필요로 하는 코드지만 지금 당장은 아닌 코드를 나중에 받도록 미루는 것입니다. 두 기법은 병행해서 쓰는 것이 보통입니다. Service Worker와 함께 쓸 때는 전략을 맞춰야 합니다. Service Worker로 청크를 사전에 캐싱하면 오프라인에서도 Lazy Chunk를 즉시 제공할 수 있지만, 어떤 청크를 미리 캐싱할지 범위를 잘 정하지 않으면 캐시 크기가 불필요하게 커질 수 있습니다. 오프라인 지원이 목표라면 Code Splitting과 Service Worker의 캐싱 전략을 함께 설계해야 합니다. Code Splitting이 적합하지 않은 상황도 있습니다. 앱 자체가 작거나 대부분의 코드가 첫 페이지에서 필요하다면 청크를 나눠도 네트워크 왕복 횟수만 늘어나 오히려 느려질 수 있습니다.

언제 쓰나요?

페이지 수가 늘어날수록 라우트 기반 분리 효과가 커집니다. 메인 페이지, 로그인, 상품 상세 같은 가벼운 페이지는 Initial Chunk만으로 빠르게 뜨고, 통계 대시보드나 텍스트 에디터처럼 무거운 기능은 해당 페이지에 진입하는 사용자만 그 비용을 지불하는 구조가 됩니다. 실무에서 Code Splitting 도입을 고려하는 신호는 Lighthouse나 번들 분석 도구에서 번들 사이즈가 일정 수준을 넘거나, First Contentful Paint나 Time to Interactive가 목표치를 벗어날 때입니다. 번들 분석기로 어떤 모듈이 가장 큰지 파악한 뒤, 그 모듈이 첫 화면에 반드시 필요한지 확인하는 것이 도입의 출발점입니다. 다만 너무 세분화하면 청크 개수가 늘어 네트워크 요청이 많아지고 오히려 역효과가 날 수 있습니다. 청크 단위는 라우트나 의미 있는 기능 묶음 정도가 적당합니다.

SPA 초기 로딩라우트 기반 분리무거운 서드파티 라이브러리조건부 기능