Angular 18 워크스페이스에서 public 폴더의 이미지 에셋 참조 에러 해결 방법
Problem
Angular 18로 워크스페이스를 생성하고 애플리케이션을 추가하면, 이전 버전(v17 이하)과 달리 src/assets 대신 public 폴더가 생성됩니다. 이때 개발자들이 public 폴더 안에 있는 이미지 등 에셋 파일의 경로를 템플릿에서 어떻게 지정해야 할지 몰라 404 Not Found 에러를 겪는 경우가 많습니다. 특히 기존 방식대로 경로를 입력하거나 public/ 접두사를 붙여도 이미지가 렌더링되지 않으며, 빌드 시 파일이 제대로 복사되지 않는 것처럼 보이는 현상이 발생합니다.
Background
이 문제는 Angular 18에서 도입된 새로운 프로젝트 구조와 빌더 설정의 변화 때문에 발생합니다. Angular 18의 angular.json 파일을 살펴보면 에셋 설정이 {"glob": "**/*", "input": "public"}으로 기본 지정되어 있습니다. 이는 빌드 과정에서 public 폴더 자체를 복사하는 것이 아니라, public 폴더 ‘내부의 내용물’을 빌드 결과물(dist)의 최상위 루트 경로로 매핑한다는 것을 의미합니다. 따라서 소스 코드 상의 실제 폴더 구조와 빌드 후 브라우저가 인식하는 라우팅 경로 간에 차이가 생기게 되며, 이 매핑 규칙을 이해하지 못하면 잘못된 경로를 참조하게 됩니다.
Solution
이 문제를 해결하는 방법은 크게 두 가지가 있습니다. Angular 18의 새로운 구조에 맞추는 방법과 기존 버전의 관행을 유지하는 방법입니다.
방법 1: URL 경로에서 public 접두사 생략하기 (권장)
Angular 18의 기본 빌드 설정은 public 폴더 안의 파일들을 웹 서버의 루트(/)로 바로 복사합니다. 따라서 템플릿에서 에셋을 참조할 때 public/ 경로를 빼고 작성해야 합니다.
<!-- 잘못된 방법: public 폴더를 명시하면 404 에러가 발생합니다. -->
<!-- 실제 파일 위치: workspace/projects/app-name/public/img/logo.png -->
<img src="public/img/logo.png" alt="Logo">
<!-- 올바른 방법: public 폴더를 생략하고 내부 경로만 작성합니다. -->
<img src="img/logo.png" alt="Logo">
- 장점: Angular 18의 새로운 아키텍처 의도에 완벽히 부합하며, 추가적인 설정이나 폴더 구조 변경이 필요 없습니다.
- 단점: 이전 버전의 Angular에 익숙한 개발자에게는 초기에 직관적이지 않을 수 있습니다.
방법 2: public 폴더 내부에 assets 하위 폴더 생성하기 (하위 호환성)
기존 Angular 17 이하 버전에서 사용하던 <img src="assets/..."> 방식을 그대로 유지하고 싶다면, public 폴더 안에 수동으로 assets 폴더를 만들면 됩니다.
public폴더 아래에assets폴더를 생성합니다. (경로:/public/assets/)- 이미지 파일을 해당 폴더에 넣습니다. (예:
/public/assets/image.png) - 템플릿에서 다음과 같이 참조합니다.
<!-- 기존 Angular 버전과 동일한 방식으로 참조가 가능해집니다. -->
<!-- 실제 파일 위치: workspace/projects/app-name/public/assets/image.png -->
<img src="assets/image.png" alt="My Image">
- 장점: 기존 프로젝트를 Angular 18로 마이그레이션할 때 템플릿 코드를 대량으로 수정할 필요가 없습니다.
- 단점:
public이라는 정적 폴더 안에 또assets라는 폴더가 중첩되어 구조가 약간 중복되는 느낌을 줄 수 있습니다.
Deep Dive
angular.json의 assets 배열 설정을 수정하면 여러 폴더의 에셋을 원하는 출력 경로로 세밀하게 제어할 수 있습니다. 예를 들어 외부 라이브러리의 정적 파일이나 특정 모듈 전용 에셋을 빌드 결과물의 특정 경로로 복사하도록 output 속성을 추가하는 객체 형태로 설정을 확장할 수 있습니다. 프로덕션 환경에서 주의할 점은, public 폴더에 직접 넣은 파일들은 일반적으로 Angular 빌더의 파일명 해싱(Cache Busting) 프로세스를 거치지 않는다는 것입니다. 따라서 자주 변경되는 이미지 리소스보다는 파비콘(favicon.ico), robots.txt, manifest.webmanifest 같은 고정적인 정적 파일 위주로 public 폴더를 활용하는 것이 베스트 프랙티스입니다.
Conclusion
Angular 18의 새로운 public 폴더 구조에서는 에셋을 참조할 때 URL 경로에서 public/을 제외해야 한다는 점이 핵심입니다. 새 프로젝트라면 Angular의 기본 의도대로 public 접두사를 생략하는 방식을 사용하고, 기존 프로젝트를 마이그레이션하는 상황이라면 public/assets 폴더를 만들어 기존 템플릿의 경로 구조를 유지하는 방식을 선택하는 것이 효율적입니다.