다독다독 프로젝트가 굉장히 오랫동안 진행하고 있는 와중에 인상깊게 배웠던것들을 블로그에 기록해보려한다.
좋은 기회들을 계속해서 만들어갈 수 있도록 힘 써 주고 있는 팀원들에게 압도적 감사...!
페이지 성능 개선을 위해 손 볼 수 있는 요소는 참 많습니다
당장 떠오르는 것만해도 이미지, 폰트, 캐싱 전략, CDN 활용, JS 번들 사이즈 줄이기 등등...
이외에도 정말 많을 것입니다
그 중 오늘 이야기할 내용은 바로, Next/Image 컴포넌트를 활용한 이미지 최적화!
Next/Image 컴포넌트를 사용했을 때 얻을 수 있는 이점 3가지
이미지 최적화, lazyloading, placeholder에 대해 알아봅시다
이미지 최적화
Next/Image 컴포넌트를 가져다 쓰면 자동으로 최적화가 된다?
왜 그럴까요?
결론부터 말하자면 Next/Image 컴포넌트를 사용했을 때 기본 이미지 포맷을
Next.js가 자동으로 WebP으로 바꿔주기 때문입니다
"WebP이 뭔데 씹덕아"
이를 좀 더 알아보기 위해 일반적으로 브라우저에서 지원하는 이미지 포맷 3가지
JPEG, WebP, AVIF의 차이를 비교해봅시다
이미지 포맷 종류 | fetching 상세 내용 | 로딩 이미지 크기 (이미지 11개) |
JPEG | 총 98.5KB | |
WebP | 총 46.1KB (JPEG 대비 약 53.2% 압축) |
|
AVIF | 총 30.7KB (JPEG 대비 약 68.8% 압축) (WebP 대비 약 33.4% 압축) |
"그럼 압축률이 제일 좋은 AVIF만 쓰면 되는거 아닌가요?"
꼭 그렇지만은 않습니다
브라우저 이미지 호환성에 대해 알아보면서 더 이야기해보죠
'브라우저 별 AVIF 이미지 호환성 표'
표를 보면 지원되는 브라우저 중 Safari는 일부 버전에서 Edge 브라우저는 지원자체가 안되는것을 볼 수 있습니다
그러면 브라우저 호환성에 따라 적절한 이미지 포맷을 제공할 순 없을까요?
서비스에서 제공할 이미지 포맷들을 next.config.js에 아래와 같이 적어주면 됩니다!
그러면 NextJS가 호환성에따라 배열 인덱스 순서대로 이미지 포맷을 적용해줄것입니다
const nextConfig = {
images: {
formats: ['image/avif', 'image/webp'],
},
};
module.exports = nextConfig;
해당 코드처럼 적용한다면 기본으로 AVIF
AVIF가 지원되지 않는 브라우저에서는 WebP
AVIF, WebP 둘다 지원하지 않는다면 JPEG로 적용됩니다
"그럼 무조건 AVIF를 default 포맷으로, WebP를 fallback 포맷으로 하면 될까요?"
저는 이부분에 대해서 이렇게 말하고 싶습니다
"여러분이 무슨 프로젝트를 진행중인지? 어떤 크기의 이미지를 얼마나 호출하는지? 프로젝트 내부에서 정해진 캐싱 전략은?
근거있는 여러 고민 이후 알맞게 적용해보세요. 이외에도 고려할 사항은 얼마든지 있을 수 있습니다."
LazyLoading (지연 로딩)
Next/Image 컴포넌트는 기본으로 LazyLoading (지연 로딩)을 지원합니다
아래 영상에서 페이지를 스크롤함에 따라 변화하는 네트워크 탭 항목을 주목해주세요
신기하게도 스크롤을 내리기 시작하니 네트워크 요청과 응답이 이루어 집니다
이러한 현상이 일어나는 이유는
초기 렌더링에 사용자 viewport에 들어오지 않은 image요소를 불러오지 않고 있다가
스크롤을 내리고 컨탠츠가 viewport에 들어오고 나서야 로드하기 때문입니다
이것이 바로 LazyLoading 입니다
LazyLoading을 사용해서 얻을 수 있는 이점은
초기 렌더링시 실제로 보이는 컨탠츠만 로딩시켜
초기 렌더링 속도를 향상시킬 수 있다는 것 입니다.
하지만, 주의할 점 또한 있습니다!
1. viewport내에 로드되지 못한 요소는 검색 엔진으로부터 제외되어 검색 순위에 영향을 줄 수 있다.
2. LazyLoading 되는 요소 중 비교적 사이즈가 크고 이미지가 있다면 UX를 해칠 수 있다.
주의사항을 참고하여 여러분은 Next/Image 컴포넌트 props로
loading="lazy" 혹은 loading="eager" 을 부여하여
지연 로드가 필요한곳과 필요하지 않은 곳 알맞게 사용하시길 바랍니다!
placeholder
placeholder를 번역하면 뭘까요?
Papago는 '자리지킴이' 라고 알려주는군요
지금 설명하려는 placeholder 역시 자리지킴이라고 생각하시면 이해하기 쉽습니다
이미지가 로드되기전 이미지가 있어야할 자리를 placeholder 기능을 통해 확보해 놓는것입니다
그러면 만약 placeholder가 없다면 어떤 현상을 겪을 수 있을까요?
위 GIF는 광고 배너가 늦게 로드 되면서
레이아웃이 밀리는 현상이 발생하였고
실수로 테스트 경보가 아닌!
실제 공습 경보 버튼을 눌러버리는 끔찍한 상황입니다
GIF로 보여드린게 극단적인 예시이긴 하지만
이게 실제 상황이라면 진짜 난리가나겠죠?
이러한 레이아웃 밀림 현상을 CLS(Cumulative Layout Shift)라고도 합니다
아마 placeholder 기능이 있었다면 광고 배너 자리를 미리 확보해두어 레이아웃이 밀리는 현상이 없었을 것입니다
그렇다면 시각적인 안정감 또한 유저에게 제공해줄 수 있겠죠?
여담: 올해 5~6월 즈음? 카카오톡이 업데이트가 되면서 없었던 광고 배너가 친구창과 채팅창에 생긴것으로 기억합니다
지금은 확인해본 결과 CLS 현상은 없지만 배너가 처음 생기고 오랜 기간동안 CLS를 개선해주지 않아 불편함을 느꼈었는데요
의도적으로 광고 클릭 횟수를 늘리려는 카카오의 개수작이 아니였을까? 라고 할 뻔~
정리
Next/Image를 활용해서 성능 개선이 어떻게 이루어 질까?
1. 이미지 최적화를 통한 렌더링 속도 향상
2. LazyLoading을 통한 초기 렌더링 속도 향상
3. placeholder를 통한 유저에게 시각적인 안정성 부여
이를 더 활용하여 더 많은 성능 개선 혹은 질 높은 UI/UX를 제공할 수 도 있습니다.
다만 글이 길어질 수 있어 이후에 다루어 보려고 합니다!
긴 글 읽어주셔서 감사합니다.
'개발이야기 > 페이지 성능 개선' 카테고리의 다른 글
[리렌더링] 01. reflow & repaint (0) | 2024.11.25 |
---|---|
[이미지 최적화] 02. Next/Image의 한계점, 그에 대한 대책 (0) | 2024.07.02 |