프론트엔드 프로젝트를 하면서 asset 파일을 어디에 두어야 할지 고민하던 중 두 폴더의 용도 차이에 대한 고민이 생겼다. 일반적인 번들링 툴에서 public은 가공과정이 필요없는 정적 자산을, src는 가공과정이 필요한 동적 자산을 관리한다. 전자의 대표적인 케이스가 html, 로고 등의 정적 컨텐츠이고, 후자의 예시는 js, jsx, 스타일시트 파일이다. 그렇다면 일반적으로 사용되는 이미지, 폰트, svg는 어디에 두어야 할까?
src 폴더 내에 파일을 둘 때 장점
- 웹팩을 통한 최적화
- src 폴더의 파일은 웹팩으로 처리하여 번들에 포함된다. 이 과정에서 정적 파일은 최적화될 수 있다. 반면 public 폴더에 있는 파일은 번들링 과정에 포함되지 않고 그대로 배포된다.
- 정적 파일의 최적화는 원본 파일의 품질을 변경하거나 확장자를 바꾸는 것이 아니라 파일 용량과 불필요한 데이터를 줄이는 기법이다.
- 압축 (Compression)
이미지, 폰트 등의 파일을 압축해 파일 크기를 줄인다. 예를 들어 이미지 파일의 경우, 무손실 압축 (lossless compression) 방식으로 품질을 유지하면서 용량을 줄이는 경우가 많다(단, 경우에 따라 품질 손실이 있는 압축을 적용할 수도 있다) - 포맷 변환 (Format Transformation)
웹 성능 향상을 위해 더 효율적인 포맷으로 변환하기도 합니다. 예를 들어, 빌드 시점에 원본의 사본을 JPEG나 PNG 이미지보다 압축 효율이 좋은 WebP 포맷으로 변환하여 파일 크기를 줄일 수 있다. - 이미지 스프라이트 (Image Sprites) 및 SVG 최적화
작은 이미지를 하나의 스프라이트 이미지로 결합해 불필요한 요청 수를 줄이거나 SVG 파일의 경우, 불필요한 메타데이터나 빈 태그를 제거해 용량을 줄이는 최적화를 할 수 있다. - 캐시 최적화 (Cache Optimization)
정적 파일의 해시를 추가해 파일이 변경될 때만 새로운 파일로 인식되게 한다. 예를 들어, 파일 이름에 hash 값을 추가하여 브라우저가 파일 변경 여부를 쉽게 감지하게 한다. 이 방식은 파일이 수정되지 않는 한 브라우저가 캐시에서 파일을 불러와 로딩 속도를 높인다. - 중복 제거 (Deduplication)
동일한 리소스를 중복해서 포함하지 않도록 한다. 웹팩은 동일한 이미지나 폰트를 여러 컴포넌트에서 참조할 경우, 중복을 제거하고 한 번만 포함하여 용량을 줄입니다.
- 압축 (Compression)
- 트리 쉐이킹 및 코드 스플리팅
src 폴더에 있는 정적 파일들은 특정 컴포넌트에서만 사용되는 경우 해당 컴포넌트와 함께 로드될 수 있다. 즉, 웹팩이 불필요한 파일을 제외하고 필요한 파일만 번들에 포함하게 되어 로딩 속도가 개선된다. 반면 public 폴더에 넣은 파일은 애플리케이션 전체에서 접근할 수 있지만, 트리 쉐이킹이나 코드 스플리팅의 영향을 받지 않습니다. - 타입 체크 및 오류 탐지 가능
src 폴더의 파일은 TypeScript와 ESLint 같은 도구들이 정적 파일의 경로나 사용 여부를 검사할 수 있어, 빌드 단계에서 잘못된 경로나 누락된 파일을 더 쉽게 감지할 수 있다. 반면 public의 파일은 404에러를 보낸다.
public 폴더 내에 파일을 두는 경우
만약 이런 빌드 이점이 필요없는 public 파일이라면 빌드 단계에 빌드 결과물에 그대로 복사할 수도 있다.
- 이름이 변경되면 안되는 파일
manifest.webmanifest처럼 정적 파일의 이름이 빌드 과정에서 바뀌면 안될 때 - 다량의 이미지를 동적으로 직접 url참조하는 경우
수천 개의 이미지를 동적으로 참조해야 하는 경우, public 폴더에 이미지를 저장하고 경로를 직접 참조할 수 있다. 이 경우, 번들링된 src 내 정적파일은 동적인 url 참조가 어려우므로 public 폴더를 이용해야 한다. - 번들 외부의 스크립트 추가
pace.js 같은 작은 스크립트를 번들 외부에서 별도로 포함하고 싶을 때 public 폴더에 넣어 <script> 태그로 추가할 수 있다. - 웹팩과 호환되지 않는 라이브러리
일부 라이브러리가 웹팩과 호환되지 않을 수 있는데, 이 경우 <script> 태그를 사용해 직접 포함합니다.
이런 경우, public 경로를 아래처럼 환경변수로 관리하면 편리하다.
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
파일 위치는 도메인 내에 어느 곳에서든 사용될만한 몇 안되는 파일(로고 이미지, 메타 데이터) 혹은 빌드 타임에 경로가 정적으로 고정된 파일은 프론트엔드 소스코드 내에 /public 폴더에 놓고 빌드 시 복사하는 방식으로 하면 된다(webpack의 경우, CopyWebpackPlugin을 사용하면 된다) 반면, 런타임에 동적으로 참조하는 대량의 이미지는 빌드 시 성능을 고려하여, 이미지를 가져오는 별도의 서버를 배치하는 것이 좋다. 이 때, CDN에 파일을 배치하여 최적화할 수도 있다.
'프로그래밍 일반 > 프론트엔드' 카테고리의 다른 글
웹 폰트의 동작 방식 (2) | 2024.11.13 |
---|---|
빌드한 파일을 실제 배포 환경처럼 실행해보기(serve) (0) | 2024.11.07 |
[모노레포, 마이크로 프론트엔드(MF)] 호스트 앱과 리모트 앱 동시 실행하기 (1) | 2024.11.04 |
[react] cra, vite 없이 직접 리엑트 프로젝트 세팅하기1(webpack) - 바벨, 타입스크립트, css 전처리, 환경변수, 정적 파일 (0) | 2024.08.18 |
마이크로 프론트엔드(MF) 1. 배경 지식 및 개념 정리 (0) | 2024.07.18 |