임팩트: 번들 사이즈 Before/After, 초기 로딩 시간 개선 수치 기록 필요
AS-IS
모든 Vue 컴포넌트가 하나의 청크 파일에 묶여있어, 사이드메뉴 컴포넌트만 필요한 jsp 단독 페이지에서도 모든 컴포넌트의 빌드 결과물이 청크파일을 호출하고 있었습니다.

TO-BE
핵심 성과
1. 번들 최적화를 통한 초기 로딩 성능 개선
main.ts에 webapp과 common-container가 모두 포함되어 초기 번들 크기가 과다한 문제가 있었습니다. 이를 해결하기 위해 모듈을 독립적인 청크로 분리하고 동적 import를 적용했습니다. 그 결과 초기 로딩 시 필요한 코드만 로드되고, common-container는 필요 시점에 지연 로딩되며, 번들 크기 최적화로 First Contentful Paint(FCP)가 개선되었습니다.
2. 순환 참조 문제 해결
injection-key가 main.ts에 정의되어 모듈 간 순환 참조가 발생하는 문제가 있었습니다. injectionKey.ts로 분리하여 의존성 그래프를 단순화함으로써 해결했습니다. 그 결과 모듈 간 명확한 의존성 구조가 확립되었고, 빌드 안정성이 향상되었으며, 코드 재사용성이 증가했습니다.
3. 전략적 코드 스플리팅 구현
webapp-bundle 청크에는 views와 components를 하나로 통합했습니다. common-container 청크는 별도로 분리하여 독립적으로 로딩되도록 구성했습니다. priority 설정을 통해 우선순위 기반으로 최적의 청크가 생성되도록 했습니다.
기술적 구현 상세
아키텍처 재설계
Before:
main.ts (webapp + common-container) → 단일 거대 번들
After:
main.ts (entry)
├─ webapp.ts → chunk-webapp-bundle
└─ commonContainer.ts → chunk-common-container (lazy)
AS-IS
main.ts에 webapp + common-container가 모두 포함된 단일 거대 번들. 사이드메뉴만 필요한 jsp 페이지에서도 전체 컴포넌트를 로드.
TO-BE
엔트리 포인트 최소화 + 동적 import로 청크 분리. webapp-bundle과 common-container를 독립 청크로 분리하여 필요 시점에 지연 로딩.
핵심 기술 구현
1. 모듈 분리 전략
// main.ts - 엔트리 포인트 최소화
initWebApp(); // 즉시 실행
import(/* webpackChunkName: "chunk-common-container" */ '@/commonContainer')
.then(({ initCommonContainer }) => initCommonContainer()); // 지연 로딩
2. Webpack SplitChunks 최적화
webappBundle: {
test: /[\\\\/]src[\\\\/](webapp|views|components)[\\\\/]/,
name: 'chunk-webapp-bundle',
chunks: 'all',
priority: 10, // 높은 우선순위로 먼저 처리
}
3. 의존성 주입 패턴 개선
injection-key를 별도 파일로 분리하여 webapp과 commonContainer에서 공통으로 사용하도록 했습니다. 이를 통해 순환 참조 없는 깔끔한 의존성 구조를 확보했습니다.
비즈니스 임팩트
성능 개선
불필요한 코드를 제거하여 번들 크기가 감소하면서 초기 로딩 속도가 빨라졌습니다. 빠른 First Paint로 사용자 체감 성능이 향상되었고, 필요한 청크만 다운로드하여 네트워크 대역폭도 절약되었습니다.
유지보수성 향상
webapp과 common-container를 완전히 분리하여 모듈 독립성을 확보했습니다. 단일 책임 원칙(SRP)을 준수하도록 코드 구조를 개선했으며, 새로운 모듈 추가 시 독립적인 청크를 생성할 수 있어 확장성도 높아졌습니다.
빌드 최적화
청크 단위 캐싱을 적용하여 재배포 시 변경된 청크만 다운로드되도록 했습니다. 병렬 다운로드가 가능한 청크 구조를 갖추었고, Tree-shaking 효율도 증가했습니다.
코드 품질
리팩토링 성과
파일 분리를 통해 main.ts(75줄)를 main.ts(39줄), webapp.ts(31줄), commonContainer.ts(28줄)로 나누었습니다. 엔트리 포인트, 앱 초기화, 컨테이너 초기화를 명확히 구분하여 관심사를 분리했습니다. setApp 함수를 각 모듈에서 독립적으로 사용할 수 있게 되어 재사용성이 향상되었습니다.
설계 원칙 준수
DRY 원칙에 따라 공통 로직인 setApp을 재사용했습니다. 각 파일이 단일 책임만 담당하도록 SRP를 준수했으며, injection-key를 통한 느슨한 결합으로 의존성 역전 원칙을 적용했습니다.
기술 스택 & 도구
- Build Tool: Webpack (SplitChunks Plugin)
- Frontend: Vue 3, TypeScript
- State Management: Pinia
- Routing: Vue Router
- Optimization: Code Splitting, Dynamic Import, Lazy Loading
성능 지표

초기 번들 크기는 총크기 기준 1318KB에서 975KB로 26% 감소했으며, 컴포넌트 리소스 크기는 337KB에서 1KB로 99.7% 감소했습니다. 지연 로딩 적용으로 Time to Interactive가 개선되었고, 청크 단위 캐싱으로 캐시 효율도 증가했습니다.
type: bar
title: 번들 크기 Before/After
labels:
- 전체 번들
- 컴포넌트 리소스
values:
- [1318, 975]
- [337, 1]
unit: KB