[Next.js] 렌더링 이미지 최적화: 기본편
Frontend/Next.js
· 2025-01-10
![[Next.js] 렌더링 이미지 최적화: 기본편](/assets/posts/image-rendering/thumbnail-optimized.webp)
이미지 최적화
이미지는 컨텐츠에서 중요한 요소이기 때문에 성능이 향상된다면 HTML이 로드되는 과정에서 초기 페인트 성능을 향상시키기 때문에 페이지 로딩 속도 측면에서 가장 유리해보인다. 사용자 경험 개선 뿐만 아니라 데이터 절감 효과까지 있어 모바일 사용자나 제한된 데이터 플랜을 사용하는 사람들에게 더욱 중요할 수 있는 개념이라 생각한다.
- Lazy Loading
- Placeholder 제공
- Image Size 최적화
- Layout 최적화
Next.js
에서 제공해주는 이미지를 최적화시키는 방법은 크게 위와 같은 네 가지 방식이 있다. 하나씩 살펴보자.
Lazy Loading
Lazy Loading은 말그대로 이미지가 바로 로드되지 않고, 사용자에게 꼭 필요할 때만 로드되도록 하는 방식이다. 기본적으로, 페이지가 로드될 때 모든 이미지가 한꺼번에 다운로드되지 않고, 사용자가 이미지가 위치한 영역에 스크롤할 때 이미지를 불러오게 할 수 있다. 즉, 렌더링 시점에 필요한 이미지를 로드하는 것인데, 예를 들어 사용자가 스크롤하지 않는 이미지는 아직 보여주지 않는 방식이다.
이 방식은 대부분의 브라우저에서 지원하는Intersection Observer API와 scroll event를 통해 스크롤 상태를 감지하여 화면에 노출되는 시점에 로드를 시작시킨다. next.js를 크롬에서 사용할 시 브라우저에서 제공하는 loading="lazy"
기능을 자동으로 사용하기 때문에 추가 설정 없이 Lazy Loading이 가능하다.
🙋🏻 어떻게 사용할까
앞서 언급했듯 Next.js에서는 next/image
를 사용하면 자동으로 lazy loading이 적용된다. 만일 특정 이미지를 lazy loading하지 않도록 하고 싶다면 priority
속성을 true
로 주거나 loading
속성에 "eager"
값을 넣어주면 된다.
1import Image from 'next/image'; 2export default function ExampleImage() { 3 return ( 4 <Image 5 src="/example.jpg" 6 alt="Example Image" 7 width={500} 8 height={500} 9 priority // 중요 이미지에 lazy loading 적용 안함 10 /> 11 ); 12}
디폴트로 Lazy Loading을 지원하기 때문에 위 ExampleImage 컴포넌트는 priority 속성으로 인하여 적용되지 않은 것.
Placeholder 제공
이미지가 로드되기 전 시점에는 이미지가 있어야할 자리가 비어있기 때문에 페이지의 레이아웃이 흔들리게 된다. 이 때 Placeholder는 로딩 중에도 미리보기 이미지를 보여주거나 빈 영역을 확보해 레이아웃이 변경되지 않도록 해주는 역할을 한다.
🙋🏻 어떻게 사용할까
Next.js에서는 로컬 이미지를 쓸 때 자동으로 blur
효과를 준다. blur
효과란 흐릿한 버전을 보여줌으로 빈 영역을 채워주는 것이다. 외부에서 끌어오는 소스일 경우에는 Base64로 인코딩된 데이터를 placeholder로 사용해야한다.
1import Image from 'next/image'; 2import profilePic from '../public/example.jpg'; 3 4export default function LocalImage() { 5 return ( 6 <Image 7 src={profilePic} 8 alt="Example Image" 9 placeholder="blur" // 블러된 Placeholder 제공 10 /> 11 ); 12} 13 14export default function ExternalImage() { 15 return ( 16 <Image 17 src="https://example.com/image.jpg" 18 alt="Example Image" 19 width={500} 20 height={500} 21 placeholder="blur" 22 blurDataURL="data:image/jpeg;base64,.." // Base64 인코딩된 데이터 사용 23 /> 24 ); 25}
추가적으로, 위와 같이 외부에서 이미지를 가져올 경우 해당 서버에 직접 요청을 보내는 것이다. 모든 접근을 허용하면 위험하기 때문에 해당 서버에서는 모든 접근을 허용하지 않고, 우리는 이미지를 요청하려는 서버가 안전한 서버라는 것을 Next.js에 아렬주기 위해 next.config.js 파일에 CDN에 대한 host를 아래와 같이 알려주어야한다.
1const nextConfig = { 2 .. 3 images: { 4 domains: ['sample-cdn.com'], 5 }, 6}; 7 8export default nextConfig;
Image Size 최적화
이미지 사이즈 최적화는 디바이스별 적절한 크기의 이미지를 제공하기 위함이다. 사용자가 필요로 하는 이미지보다 큰 사이즈의 이미지가 들어온다면 비교적 큰 네트워크 대역폭을 사용하게 될 것이기 때문에, 최적화로 인한 네트워크 트래픽과 로드 시간까지 최적화를 확보할 수 있다. Next.js는 다양한 화면 크기에 맞춘 여러 크기의 이미지를 자동으로 생성(scrSet)한다. 먼저 srcSet가 뭔지 간단히 알고 가자.
srcSet이란
srcSet은 HTML의 <img>
태그와 Next.js Image
컴포넌트에서 사용되는 속성이자, 이미지의 다양한 해상도와 크기를 제공해주는 일종의 기능이다. 브라우저가 사용자의 화면 크기와 해상도에 맞는 최적의 이미지를 선택할 수 있도록 돕는다. 동작방식은 크기와 해상도별 이미지를 지정할 수 있는 목록을 제공해주는 방식으로 이루어진다. 그러면 브라우저는 목록을 훑고 사용자 디바이스 크기나 해상도에 맞는 적절한 이미지를 골라서 로드한다.
1import Image from 'next/image'; 2 3<img 4 src="image-300w.jpg" 5 srcset="image-300w.jpg 300w, image-600w.jpg 600w, image-1200w.jpg 1200w" 6 sizes="(max-width: 600px) 300px, (max-width: 1200px) 600px, 1200px" 7 alt="Example image" 8> 9 10<Image 11 src="/example.jpg" 12 alt="Example" 13 width={500} 14 height={500} 15 sizes="(max-width: 600px) 300px, (max-width: 1200px) 500px, 100vw" 16/>
위 코드는 각각 기본적인 scrSet 예시와 Next.js에서의 srcSet 사용 예시다. 예를 들어, 각 너비별 이미지가 지정되어있고 브라우저 너비가 500px이라면, 브라우저는 image-300w.jpg를 가져다 쓸 것이다.
🙋🏻 어떻게 사용할까
이미지 사이즈 최적화를 위해 Next.js는 다양한 화면 크기와 해상도를 고려한 srcSet를 생성하고, sizes
이라는 속성을 통해 브라우저에게 화면 크기에 따라 적절한 이미지 크기를 결정하도록 지시한다. 이런 방식으로 디바이스별 최적의 크기의 이미지가 전송되는 것! 추가로, Next.js는 이미지의 파일 형식을 WebP와 같은 최신 이미지 포맷으로 자동 변환하여 용량을 줄인다.
1import Image from 'next/image'; 2 3export default function ExampleImage() { 4 return ( 5 <Image 6 src="/example.jpg" 7 alt="Example Image" 8 width={500} 9 height={500} 10 sizes="(max-width: 600px) 300px, (max-width: 1200px) 500px, 100vw" 11 /> 12 ); 13}
예를 들어, 위 sizes 속성이 선언된 것처럼, 600px 이하의 화면에서는 300px 이미지를, 1200px 이하에서는 500px 이미지를 전송한다.
Layout 최적화
레이아웃 최적화는 이미지가 페이지 내 배치와 크기를 조정하는지에 대해 결정하는 방법이다. 즉, 페이지의 다른 요소들과의 상호작용을 고려하여 이미지의 배치와 크기를 자동으로 조정하는 것인데, 이는 적절한 크기가 아닌 이미지의 레이아웃이 깨지는 등 반응형 웹 사이트에서 유연하게 변경시키기 위해 필수로 고려되어야하는 부분이다.
🙋🏻 어떻게 사용할까
next/image
의 layout
속성을 사용하여 레이아웃 방식을 명시한다. 이 속성은 이미지가 고정 크기도 표시될지, 반응형으로 될지 또는 부모 요소의 크기에 맞게 채워질지 등을 정의한다.
-
intrinsic
: 이미지 원래 비율을 유지하면서 부모 요소에 맞게 조정시킨다. -
fixed
: 이미지 크기 자체가 고정된다. 부모나 디바이스 크기랑 상관없이 지정된width
와height
가 유지된다. -
responsive
: 이미지가 화면 크기에 맞게 자동으로 변경된다. -
fill
: 부모 컨테이너의 크기에 채워지도록 조정된다. 주로 objectFit 속성과 함께 사용되어 이미지 비율을 유지하는 용도로 쓰인다.
1import Image from 'next/image'; 2 3export default function Example() { 4 return ( 5 <Image 6 src="/example.jpg" 7 alt="Example Image" 8 layout="fill" // 부모 컨테이너에 맞게 크기가 조정됨 9 objectFit="cover" // 부모 컨테이너에 이미지를 꽉 채우면서 비율 유지 10 /> 11 ); 12}
이렇게 Next.js에서 제공해주는 Image 컴포넌트를 통해 이미지 최적화를 어떻게 할 수 있을지에 대해 알아보았다. Next/Image를 통해 얻을 수 있는 이점은 크게 효율적인 페이지 로딩,시각적인 안정성 그리고 용량과 성능 향상이다. 또한, 네트워크 트래픽 절감과 SEO 점수 및 Lighthouse 성능 점수도 높이는 데 도움이 된다고 하는데 이 부분은 2편에서 실제 테스트를 통해 명확한 입증을 해볼 생각이다.