오늘은 Next.js에서 이미지를 사용하는 방법에 대해서 알아보겠다.
이 글은 Next.js 14를 기준으로 작성되었다.
이미지 최적화 전략
이미지를 최적화하기 위한 전략에는 아래와 같이 다양한 방법이 있다.
- png, jpeg 형식보다는 webp, avif 형식의 이미지 파일 사용하기
- 이미지 Lazy Loading 처리하기
- 디바이스 크기에 알맞은 이미지 크기로 리사이징
- 이미지 캐싱하기
이러한 작업을 Next.js에서 해주고 있는데 어떻게 적용할 수 있는지 알아보겠다!
1. webp로 변환
next/image는 png, jpeg 등 형식을 webp로 변환해 이미지 용량을 줄여준다.
webp보다 2019년에 만들어진 avif가 여러 형식(jpeg, webp) 보다 훨씬 더 좋은 무손실 압축과 고품질을 자랑한다.(webp보다 인코딩하는데 20%는 더 오래 걸리지만 20% 더 작게 압축된다고 한다) 하지만 avif는 지원하지 않는 브라우저가 있을 수 있다.
얼마나 효과가 있는지 하나씩 적용을 해봤는데 webp와 avif가 확실히 기존 형식에 비해 size가 줄어든 것을 확인할 수 있었다. 나의 경우 avif는 큰 효과를 모르겠어서 webp로 사용했다.
일반 img 태그 사용 시
next/image 적용해 webp 사용 시
avif 사용 시
2. 이미지 Lazy Loading 처리
Lazy Loading이란 웹 페이지 성능을 향상시키기 위한 기술 중 하나로, 페이지가 로드될 때 이미지를 한 번에 다운로드하는 대신 페이지가 스크롤될 때 필요한 이미지만 로드하는 방식을 의미한다.
과거에는 Intersection observer 또는 scroll 이벤트를 활용하여 이미지를 동적으로 로드했다. 최근에는 img 태그에 loading 속성을 사용해 Lazy Loading을 적용할 수 있다고 한다.
이런 기능도 Next.js에서 지원해주고 있다. 기본적으로 next/image를 사용하면 Lazy loading이 적용되고 이를 끄고 싶다면 priorty 속성을 true로 설정해 주면 된다. 또는 loading="eager"로 설정할 경우에도 이미지를 즉시 로딩하지만 성능을 저하시킬 수 있다고 한다.
나의 경우 우선순위가 높은 이미지(페이지를 로드했을 때 화면에 바로 보이는 이미지)는 priority를 true로 적용해 줬고 스크롤되면서 필요한 이미지들은 기본값으로 두었다.
priority
기본값은 false이고, priority를 true로 설정하면 높은 우선순위로 간주되어 preload된다. LCP(Largest Contentful Paint, 웹 페이지가 로드되는 동안 사용자에게 가장 먼저 보이는 콘텐츠 요소로 웹 페이지 성능 및 사용자 경험을 평가하는데 중요한 지표 중 하나) 요소는 priority를 true로 적용하는 것이 좋다.
3. 디바이스 크기에 알맞는 이미지로 리사이징
모바일 화면에서 pc에서 사용되는 큰 이미지를 사용하는 것은 낭비이다. 따라서 각 화면에 알맞은 이미지 크기를 보여주는 것이 성능을 최적화하는데 도움이 된다.
Image 태그에서 width와 height를 명시할 경우 그에 맞게 생성된다. fill을 사용할 경우 아래처럼 자동으로 srcset이 지정되어 디바이스 별 이미지 사이즈를 설정해 준다.
(좀 과하게...? 디바이스별 이미지 사이즈를 만들어주는 게 아닌가 하는 생각이 들어 이 부분에 대해서는 좀 더 찾아봐야 할 거 같다..! next.config.js에서 설정해 주는 값도 무엇을 기준으로 deviceSizes와 imageSizes를 설정해줘야 하는지 등도 의문이다 )
이걸 next.config.js에서 원하는 값으로 설정할 수 있는데
만약 원하는 디바이스 중단점과 그에 따른 이미지 넓이가 있다면 next.config.js 파일에 아래처럼 작성해 주면 된다. 이런 값을 별도 설정하지 않는다면 아래의 기본값이 사용된다.
module.exports = {
images: {
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
},
}
4. 이미지 캐싱
.next/cache/images안에 이미지를 자동으로 캐싱하도록 지원한다. vercel에 배포할 경우 최대 31일까지 저장해둔다고 한다.
X-Nextjs-Cache를 보면 캐싱 상태를 확인할 수 있다.
MISS : 경로에 캐시가 없음
STALE: 경로가 캐시에 있지만 재확인 시간을 초과했으므로 백그라운드에서 업데이트됨
HIT: 경로가 캐시에 있고 재확인시간을 초과하지 않음
나의 경우 이미지를 이전에 한번 불러온 상태라서 캐시 되어있는 이미지가 사용되었음을 알 수 있다.
이외에도 Next.js에서 Image는 다양한 기능을 가지고 있고 오늘은 내가 사용한 기능들을 위주로 작성해 봤다.
최적화된 이미지 사용은 웹 페이지 성능 향상과 함께 사용자에게 더 좋은 경험을 줄 수 있으므로 중요하다. 앞으로도 추가적인 기능을 사용하게 되면 추가적으로 더 작성해 보겠다! 👋
참고자료
+ Lighthouse의 Performance가 개선되었다!!
이전 Next.js의 next/image를 적용하기 전이고
적용한 후 !!
적용하기 전에 정확히 분석을 안 해봐서 상관관계가 있는지 100% 확신은 안드지만 눈에 보이는 속도부터 빨라졌담!! ✨ ✨
신기하네... 🤔
'Project > foliohub' 카테고리의 다른 글
[react-query] 서버에서 prefetch한 데이터 사용하기 (prefetchInfiniteQuery) (0) | 2024.05.10 |
---|---|
[Next.js] fill을 사용한 이미지에 sizes 추가 (Image with src "~~" has "fill" but is missing "sizes" prop. Please add it to improve page performance.) (0) | 2024.04.14 |
[Express] Custom Error Handling (0) | 2024.04.06 |
[Next.js] NotFound / Error 페이지 Custom하기 (0) | 2024.04.06 |
프로젝트 1차 완성 🎉(+검색엔진에 내 사이트가 뜬다!) (0) | 2024.04.04 |