라떼군 이야기
Angular 18 빌드 시 생성되는 browser 폴더 제거 및 커스텀 Output Path 설정 방법
Problem
Angular 17에서 18로 업그레이드하면서 새로운 application 빌더를 적용할 때, 빌드 결과물 경로(Output Path) 구조가 변경되는 문제가 발생합니다. 기본적으로 dist/프로젝트명/browser와 같이 browser 폴더가 자동으로 생성되는데, 이를 방지하기 위해 angular.json을 수정했음에도 불구하고 CLI 명령어(ng build --output-path=...)로 경로를 덮어쓸 경우 다시 browser 폴더가 생성되는 현상이 나타납니다. 특히 백엔드 통합을 위해 특정 경로로 빌드 파일을 보내야 하는 경우 이 추가적인 폴더 구조가 배포 파이프라인을 깨뜨릴 수 있습니다.
Background
Angular 18의 새로운 빌드 시스템인 @angular-devkit/build-angular:application은 esbuild를 기반으로 하며, SSR(Server-Side Rendering)과 CSR(Client-Side Rendering) 빌드를 통합 관리합니다. 이로 인해 기본 출력 구조가 base/browser와 base/server로 나뉘게 되었습니다. 이전 버전처럼 단일 폴더에 결과물을 출력하려면 angular.json의 outputPath 옵션을 단순 문자열이 아닌 객체 형태로 설정하여 browser 서브 경로를 빈 문자열로 지정해야 합니다. 하지만 CLI 플래그로 경로를 오버라이드할 때 이 객체 설정이 무시되거나 기본값으로 초기화되는 동작 방식의 차이가 존재합니다.
Solution
이 문제를 해결하기 위해서는 CLI 명령어의 플래그로 경로를 직접 지정하는 대신, angular.json 내에 별도의 Configuration을 정의하여 사용하는 것이 가장 확실한 방법입니다.
1. 기본 설정 변경 (angular.json)
먼저, 기본 빌드에서 browser 폴더가 생기지 않도록 outputPath를 객체 형태로 설정합니다.
// angular.json
{
"projects": {
"my-project": {
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
// 기존 문자열 경로 대신 객체 사용
"outputPath": {
"base": "dist/my-project",
"browser": "" // 빈 문자열로 설정하여 하위 폴더 생성 방지
}
// ...
}
}
}
}
}
}
2. 커스텀 경로를 위한 Configuration 추가 (권장)
CLI에서 --output-path를 직접 사용하면 browser 속성 설정이 무시될 수 있습니다. 따라서 특정 환경(예: 백엔드 wwwroot 폴더)으로 빌드하기 위한 전용 설정을 configurations 섹션에 추가합니다.
// angular.json
{
"projects": {
"my-project": {
"architect": {
"build": {
// ...
"configurations": {
"development": {
// ... 개발 모드 설정
},
// 새로운 설정 추가 (예: dev-watch)
"dev-watch": {
// 필요한 경우 development 설정을 상속받거나 복사
"optimization": false,
"extractLicenses": false,
"sourceMap": true,
// 핵심: 여기서 outputPath를 재정의
"outputPath": {
"base": "/projects/backend/wwwroot", // 원하는 커스텀 경로
"browser": "" // browser 폴더 생성 방지 유지
}
}
}
}
}
}
}
}
3. 명령어 실행
이제 CLI에서 긴 경로 옵션을 주는 대신, 위에서 정의한 configuration을 호출합니다.
# 기존 방식 (작동하지 않음 - browser 폴더가 생성됨)
# ng build --output-path=/projects/backend/wwwroot --watch
# 해결된 방식 (browser 폴더 없이 생성됨)
ng build --configuration dev-watch --watch
Deep Dive
왜 CLI 오버라이드가 실패하는가?
Angular CLI에서 --output-path 플래그는 역사적으로 단순 문자열 경로를 받았습니다. Angular 18의 application 빌더는 outputPath를 객체({ base, browser, server })로 처리하지만, CLI 플래그로 단일 문자열이 전달될 경우 이를 base 경로로 인식하면서 browser 속성은 기본값(즉, "browser")으로 리셋되는 경향이 있습니다. 이로 인해 angular.json의 기본 옵션에 browser: ""를 설정했더라도 CLI 플래그가 우선순위를 가지며 의도치 않은 하위 폴더를 생성하게 됩니다.
Configuration 사용의 이점
단순히 버그를 피하는 것 외에도, angular.json에 명시적인 configuration을 두는 것은 DevOps 관점에서 유리합니다. 빌드 스크립트가 간결해지고(ng build -c dev-watch), 경로 정보가 코드(설정 파일)로 관리되므로 팀원 간의 환경 차이를 줄일 수 있습니다.
Conclusion
Angular 18의 application 빌더 도입으로 빌드 출력 구조가 변경되었습니다. browser 폴더 없이 빌드하려면 outputPath를 객체로 설정하고 browser 속성을 비워야 합니다. 특히 커스텀 경로로 빌드할 때는 CLI 플래그 대신 angular.json에 전용 configuration을 추가하여 사용하는 것이 가장 안정적인 해결책입니다.