next/future/image 소개
next.js를 사용하시는 분들은 이미 아시겠지만 next/image라는 이미지 컴포넌트가 존재합니다. img태그를 직접 사용하지 않고 next/image 컴포넌트를 사용하는 것을 권장하고 있는데요. 문서에 소개된 장점을 살펴보면 다음과 같습니다.
✔ 향상된 성능(Improved Performance): 각 기기에 맞는 올바른 사이즈로 모던 이미지 포맷을 사용할 수 있게 제공한다.
✔ 시각적 안정성(Visual Stability): CLS를 자동으로 예방해줍니다.
✔ 빠른 페이지 로드(Faster Page Loads): 레이지 로딩을 통해 페이지를 로드하고 blur-up placeholder를 옵션으로 제공한다.
✔ 애셋 유연성(Asset Flexibility): 온디맨드로 이미지를 리사이징 합니다.
이미지를 최적화하는 기법들을 직접 이미지태그에 적용해가면서 일일히 사용할 수 있지만 해당 컴포넌트를 사용할 경우 번거로운 작업들을 처리해주기 때문에 편리하게 사용할 수 있습니다.
하지만 이미 이렇게 자랑하고 있는 기능을 제공하는 next/image를 두고 next.js는 12.2에서 실험기능으로, 12.3에서 stable 모드로 next/future/image를 등장시켰습니다. 왜 next/future/image를 만들었을까요? 사실 이 문제는 이 토론을 보면 꽤 묵은지였습니다.
추가로 이 글에서는 next/future/image의 사용법을 다루진 않습니다. 사용법이나 마이그레이션 가이드가 궁금하다면 이 링크를 참고해주세요.
next/future/image와 next/image의 차이점
next/future/image는 더 나은 성능과 next/image
의 DX를 통해 <img>
의 더 나은 기본 사용성을 제공합니다. 이 설명에서 알 수 있듯이 기존 next/image 컴포넌트는 기존 img태그를 그대로 사용하는 것과는 조금 거리가 있었는데요. 대표적으로 span 태그가 래핑되고 원하는 스타일이 지정이 안된다는 점이였는데요.
이 이슈의 코드를 그대로 가져와보면,
의 코드는
로 img 태그가 아주 꽁꽁 감싸져 있는 것을 볼 수 있습니다. 또한 next/image에서는 layout 같은 프로퍼티들로 인해 강제되는 기본 스타일들의 우선순위가 높아 이 중첩을 뚫어 스타일을 지정하기 위해서는 !important
를 사용해야 하는 문제들도 있었습니다.
그럼 변경점을 하나 하나 살펴보겠습니다.
감싸져있는 <span>
wrapper를 제거합니다.
- 기존
<img>
태그의 aspect ratio 계산 기능을 그대로 사용하기 위한 처리라고 합니다. - 일례로 img태그에 width, height를 작성하고 css에서 이미지 너비 계산 후 적용되는 프로퍼티를 사용한 경우(
auto
같은..) Layout Shift가 발생하는데 이를 width와 height 값을 사용해 방지해줍니다. - aspect ratio 계산 기능에 대해 궁금하다면 이 영상을 참고해보세요!
정식 style
프로퍼티가 추가되었습니다.
style
과className
사용을 위해 기존layout
,objectFit
,objectPosition
프로퍼티가 사라졌습니다.layout
프로퍼티가 사라졌기 때문에 기존에 적용되던 스타일 또한 사라졌는데요. 마이그레이션 가이드를 참고해 스타일을 지정해 줘야 동일한 동작이 이뤄집니다.
레이지 로딩을 위한 IntersectionObserver
구현이 사라집니다.
- 대신 native 레이지 로딩이 사용됩니다.
- 따라서
lazyBoundary
,lazyRoot
prop이 사라집니다. - 브라우저 레벨에서 제공하는 네이티브 레이지 로딩은 이 글에서 확인할 수 있습니다.
loader
설정이 사라지고 loader
프로퍼티로 사용됩니다
- loader는 Next.js 대신 외부 클라우드 공급자를 사용해 이미지를 최적화하려는 경우 사용되는 옵션입니다.
- 기존 이미지 컴포넌트에서는
next.config.js
설정 파일에 로더를 설정하고 사용하거나 프로퍼티로 내려주는 방식이 존재했는데 두 번째 방식만 남겨졌습니다.
alt
프로퍼티가 필수로 변경되었습니다.
- 접근성을 위한 조치입니다.
이미지 로딩이 완료되고 플레이스홀더가 사라지는 시점을 나타내는 onLoadingComplete
콜백이 <img>
요소 자체를 인자로 갖습니다
- 기존 핸들러와 사용성이 크게 달라지지 않지만 next/image에서
naturalHeight
,naturalWidth
만 사용 가능했던 부분에서 좀 더 범용적으로 사용할 수 있게 변경되었습니다. 예시를 보면 더 쉽게 이해되실 것 같습니다.
개인적으로는 next/image는 많은 것을 해주지만 처음에는 꽤 혼란스러웠던 기억이 있습니다. 훨씬 더 직관적인 컴포넌트가 된 것 같아 좋은 변화처럼 느껴졌고 서비스의 지원 범위에서 네이티브 기능이 전부 지원된다면 바로 변경을 해도 괜찮을 것 같습니다.