요약
PNG 형식의 퍼블릭 이미지를 WebP 확장자로 변경하여 용량 95% 절감 (평균 2.46MB → 128KB, 총 29.53MB → 1.54MB)
문제 1 : public 이미지의 용량 비대
기존의 public 디렉터리에 있던 이미지들은 모두 PNG 확장자였고 기본적으로 MB 단위라서 불러오는데 체감 시간이 오래 걸렸다. 특히 가장 큰 이미지의 경우 11MB나 됐는데, 504 Gateway Timeout 에러가 발생했다. 이미지 로딩이 너무 오래 걸려서 타임아웃이 난거다.

물론 Next.js의 Image 컴포넌트가 브라우저 호환여부에 따라 webp로 변환해주기는 하나, 원본의 용량 자체가 커서 다소 불러오는데 시간이 걸렸다.
해결 1 : WebP 변환하여 용량 절감
WebP 란?
WebP는 구글이 2010년에 개발한 이미지 포맷으로, 손실 및 비손실 압축, 움짤, 알파를 모두 지원하여 JPG 대비 25~34%, PNG 대비 26% 정도 줄어듦(구글 발표 기준)
기존의 12장의 PNG 이미지를 모두 WebP 확장자로 변경하여 평균 2.46MB에서 128KB로, 총 29.53MB에서 1.54MB로 95% 용량 절감하였다.
문제 2 : 원본 이미지보다 응답 이미지의 용량이 더 커짐
개발자 도구의 네트워크 탭을 확인해 보니 응답 이미지의 용량이 public 내의 원본 이미지 용량보다 더 컸다.
해결 2 : quality 속성을 100에서 75로 축소
코드 상에서는 next/image의 Image 컴포넌트를 사용하고 있었다. 이 컴포넌트는 요청된 사이즈에 맞게 리사이징 후 WebP로 재인코딩한다. 이 과정에서 원본보다 용량이 커질 수 있는데, quality 속성을 100으로 하면 압축을 거의 하지 않아서 결과적으로 원본보다 용량이 더 커지게 된다. 이를 기본값인 75로 지정해 주었다.
<Image
src={images.image1}
alt="image1"
fill
className="object-cover"
quality={75} // 여기 !! (또는 생략)
/>
문제 3 : 이미지 경고 로그
mage with src "/_next/static/media/image1.png" has legacy prop "layout". Did you forget to run the codemod?
Read more: https://nextjs.org/docs/messages/next-image-upgrade-to-13
Image with src "/_next/static/media/image1.png" has legacy prop "objectFit". Did you forget to run the codemod?
Read more: https://nextjs.org/docs/messages/next-image-upgrade-to-13
해당 링크를 참고하라고 한다.
해결 3 : 문서 대로 수정
<Image
src={images.image1}
alt="image1"
layout="fill" // 여기 1
objectFit="cover" // 여기 2
quality={75}
/>
기존의 코드는 위와 같다.
<Image
src={images.image1}
alt="image1"
fill // 여기 1
className="object-cover" // 여기 2
quality={75}
/>
변경한 코드는 위와 같다.
추가 개선 사항
이미지를 WebP 확장자로 변경하려고 하니, 일일이 페이지를 찾아가서 코드를 수정해야하는 문제가 있어서, 이미지 매핑 레이어를 추가해서 관리하였다.
import image1 from '@images/image1.webp'
import image2 from '@images/image2.webp'
import image3 from '@images/image3.webp'
// ...
export const images = {
image1,
image2,
image3,
// ...
}
결론
- png → webp 확장자 변경으로 이미지 총합 29.53MB 에서 1.54MB로 95% 절감
- 12개의 이미지를 이미지 매핑 레이어로 중앙집중화 하여 유지보수성 증대
- 레거시 속성의 개선으로 경고 메시지 제거
'TIL' 카테고리의 다른 글
| TIL #130 : 컨트롤러 테스트에서 커스텀 UserDetails 인증 객체 사용하기 (0) | 2025.04.10 |
|---|---|
| TIL #129 : 구글 번역 → next-intl 전환으로 렌더링 속도 70% 개선 (2.34s → 0.71s) (0) | 2025.04.08 |
| TIL #127 : Axios Interceptor 도입으로 인증 공통화 및 141줄 절감 (0) | 2025.04.07 |
| TIL #126 : SWR 도입으로 7개 페이지에서 93줄 코드 절감 (0) | 2025.04.07 |
| TIL #125 : 멀티스테이지 & .dockerignore로 Next.js Docker 이미지 용량 절반 줄이기 (1) | 2025.04.02 |