12.1
Image Optimization
이미지는 일반적으로 웹사이트에서 가장 용량을 많이 차지하는 리소스 중 하나입니다. 그래서 웹사이트의 사용자 경험 및 성능과 관계가 깊다고 할 수 있습니다. 즉, 이미지 최적화만 신경써도 FCP 등 웹사이트의 핵심 성능 지표를 크게 개선할 수 있습니다.
NOTE. First Contentful Paint(FCP)란?
First Contentful Paint (FCP)는 웹페이지에서 텍스트, 이미지, 캔버스 등의 콘텐츠가 처음으로 렌더링되는 순간을 측정하는 성능 지표입니다.
Image 컴포넌트Next.js에는 이미지 최적화를 위한 Image 컴포넌트가 내장되어 있습니다. 이 Image 컴포넌트는 HTML <img> element를 확장하여 아래와 같은 자동 이미지 최적화 기능을 제공합니다.
Image 컴포넌트를 사용하기 위해서는 먼저 아래와 같이 import를 해야 합니다.
import Image from 'next/image';
이후 아래 각각의 경우에 따라 해당되는 방법을 사용하면 됩니다.
로컬에 있는 이미지를 사용하기 위해서는 아래 예시 코드와 같이 이미지 파일(.jpg, .png, .webp)을 import해서 Image 컴포넌트의 src 속성에 넣어주면 됩니다.
import Image from 'next/image';
import avatarPhoto from './avatar.png';
export default function Page() {
return (
<Image
src={avatarPhoto}
alt='avatar'
// width={500} // 자동으로 제공
// height={500} // 자동으로 제공
// blurDataURL="data:..." // 자동으로 제공
// placeholder="blur" // 로딩 시 선택적으로 blur-up
/>
);
}
로컬에 있는 이미지들은 Next.js가 직접 접근하여 이미지의 가로세로 크기를 알 수 있기 때문에, Next.js가 자동으로 이미지의 width, height를 결정하게 됩니다. 그리고 이 값들은 이미지가 로딩되는 동안 Cumulative Layout Shift(CLS)를 막기 위해서 사용됩니다.
NOTE. Cumulative Layout Shift(CLS)란?
Cumulative Layout Shift (CLS)는 웹페이지가 로드될 때 레이아웃 요소들이 예상치 못하게 이동하는 정도를 나타내는 사용자 경험 지표. 사용자가 페이지를 읽거나 사용하는 동안 발생하는 이동의 누적 합으로, CLS가 낮을수록 사용자 경험이 더 나아짐.
로컬이 아닌 원격 서버에 있는 이미지를 사용하기 위해서는 해당 이미지의 주소(URL)를 Image 컴포넌트의 src 속성에 넣어주면 됩니다. 또한 Next.js는 빌드 과정에서 원격 파일에 접근할 수 없기 때문에, width, height 및 blurDataURL(선택) 속성을 수동으로 제공해주어야 합니다. 이렇게 제공된 width와 height 값은 이미지의 올바른 가로세로 비율을 추론하고, 이미지 로딩 시 발생할 수 있는 layout shift를 방지하는 데 사용됩니다. 참고로 width와 height 속성은 이미지 파일의 렌더링 크기를 결정하지는 않습니다.
아래 코드는 Remote Images를 사용하는 예시 코드입니다. width와 height 값을 수동으로 넣어준 것을 볼 수 있습니다.
import Image from 'next/image';
export default function Page() {
return (
<Image
src='https://s3.amazonaws.com/my-bucket/avatar.png'
alt='avatar'
width={240}
height={240}
/>
);
}
원격에 존재하는 이미지에 대해 안전하게 최적화를 적용하려면, 아래와 같이 지원되는 URL 패턴 목록을 next.config.js 파일에 정의해야 합니다. 이 때 악의적인 사용을 방지하기 위해 지원되는 URL 패턴 목록을 가능한 한 구체적으로 작성하는 것이 좋습니다. 참고로 아래와 같이 작성하면 특정 AWS S3 버킷에서만 이미지를 가져오도록 허용하게 됩니다.
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 's3.amazonaws.com',
port: '',
pathname: '/my-bucket/**',
},
],
},
};
이 설정을 통해 Next.js는 지정된 도메인에서만 이미지를 로드하고 최적화할 수 있으며, 외부에서 악의적인 이미지가 로드되는 것을 방지할 수 있습니다.
Largest Contentful Paint(LCP) 는 페이지 로딩 시점부터 가장 큰 콘텐츠가 화면에 표시될 때까지의 시간을 나타내는 웹사이트의 성능 지표입니다. LCP를 향상 시키기 위해서는 각 페이지의 가장 큰 콘텐츠 페인트(LCP) 요소가 될 이미지에 priority 속성을 추가하여 더 우선적으로 로드되도록 해야합니다.
아래 코드는 LCP 이미지 요소에 priority 속성을 사용한 예시 코드입니다. 이렇게 priority 속성을 추가함으로써 Next.js가 해당 이미지를 로드할 때 특별히 우선 순위를 부여하게 되고 결과적으로 LCP를 크게 향상시킬 수 있습니다. 참고로 개발 모드에서 LCP 요소가 priority 속성이 없는 <Image>일 경우에는 콘솔에 경고가 표시됩니다.
import Image from 'next/image';
import profilePic from '../public/avatar.png';
export default function Page() {
return (
<Image
src={profilePic}
alt='avatar'
priority
/>
);
}
일반적으로 이미지는 화면에서 차지하는 크기가 크기 때문에, Layout Shift 관점에서도 영향을 많이 미치게 됩니다. Layout Shift는 이미지가 로드되면서 페이지의 다른 요소를 밀어내는 현상을 의미합니다. 즉, 화면에 먼저 나타난 요소들이 이후 이미지가 로드 되면서 밀려나게 되고, 이로인해 사용자에게 시각적으로 불안정함을 겪게 만듭니다. Core Web Vitals에서 Layout Shift와 관련된 지표가 바로 Cumulative Layout Shift(CLS) 입니다.
이러한 Layout Shift를 줄이기 위해서는 화면에서 이미지가 로드될 공간의 크기를 미리 잡아두어야 합니다. 그리고 Next.js의 <Image> 컴포넌트는 아래와 같이 다양한 방법을 통해 이미지가 로드될 공간을 정확하게 잡아두게 됩니다.
width, height를 결정width 및 height 속성을 명시적으로 선언fill 속성을 사용하여 이미지를 부모 요소에 맞게 확장fill 속성을 사용함으로써 <Image> 컴포넌트가 부모 요소에 맞게 확장되도록 만듦그리고 만약 이미지 크기를 조정하는데 위 방법들을 모두 사용할 수 없는 경우에는, Next.js의 <Image> 컴포넌트는 일반적인 <img> 요소와 동일하게 작동한다고 이해하면 됩니다.
Next.js의 <Image> 컴포넌트를 스타일링하는 것은 일반적인 <img> 요소를 스타일링하는 것과 비슷하지만, 아래와 같은 몇 가지 규칙을 지켜야합니다.
className 또는 style 사용className 속성을 사용하는 것을 권장style 속성을 사용하여 인라인 스타일을 할당할 수도 있음styled-jsx 사용 금지styled-jsx는 전역으로 스타일을 지정하지 않는 한, 스타일의 scope가 현재 컴포넌트로 제한되기 때문에 사용할 수 없음fill 속성을 사용할 경우 부모 요소의 속성position: relative여야 함display: block이어야 함display: block은 <div> 요소의 기본값<div>가 아닌 다른 요소의 경우 기본값이 다를 수 있으므로 명시해야 함조금 까다로워 보이긴 하지만 Next.js의 <Image> 컴포넌트를 잘 사용하면 여러가지 이점들을 얻을 수 있기 때문에 규칙을 잘 지키면서 사용해보기 바랍니다.
마지막 업데이트: 2025년 10월 24일 02시 47분
이 문서의 저작권은 이인제(소플)에 있습니다. 무단 전재와 무단 복제를 금합니다.