next.js에서는 next/image
로 자체적인 이미지 컴포넌트를 제공한다. 일반적인 img
태그와는 달리 여러 성능 최적화기법이 내장되어있다. 기본적으로 다음과 같은 기능을 제공한다.
- 성능 향상 : 각 디바이스에 정확히 맞는 이미지를 모던 웹 포맷에 맞게 제공한다.
- Visual Stability : Cumulative Layout Shift를 자동으로 예방한다.
- Cumulative Layout Shift : 웹 화면의 레이아웃이 갑자기 바뀌는 것. 사용자가 의도치않은 동작을 실행할 수 있다.
- Faster Page Loads : 뷰포트 안에 들어와야만 이미지가 로드되게 한다. 선택적으로 블러처리된 placeholder를 둘 수 있다.
- Asset Flexibility : 이미지가 리모트 서버에 저장되어있어도, on-demand image resizing을 지원한다.
nexy/Image 컴포넌트 사용법
컴포넌트 import
1
import Image from "next/image"
image 불러오기
Local Image
1 2 3 4 5 6 7 8 9 10 11 12 13 14
import profilePic from '../public/me.png' function Home() { return ( <Image src={profilePic} alt="Picture of the author" // width={500} automatically provided // height={500} automatically provided // blurDataURL="data:..." automatically provided // placeholder="blur" // Optional blur-up while loading /> ) }
import
문이 빌드시 분석되어야하기 때문에 Dynamicawait import()
또는require()
는 지원되지 않는다.
width
,height
는 next.js에서 자동으로 계산한다. 이는 Cumulative Layout Shift를 방지하기 위해 쓰인다.blurDataURL
도 자동으로 지원된다.
Remote image
1 2 3 4 5 6 7 8 9 10 11 12
import Image from 'next/image' export default function Home() { return ( <Image src="/me.png" alt="Picture of the author" width={500} height={500} /> ) }
- 절대주소 또는 상대주소로 이미지의 위치를 명시한다. 이때 상대주소는
public
폴더 이하의 경로이다. - 빌드시 remote image에 접근하지 않기에,
width
,height
를 명시해주어야한다. blurDataURL
또한 직접 입력해야한다.
- 절대주소 또는 상대주소로 이미지의 위치를 명시한다. 이때 상대주소는
Loaders
Remote image를 불러오는 예제에서 src
값을 /me.png
와 같은 상대경로로 입력하였는데, 이것이 가능한 이유는 Loader
가 있기 때문이다.
loader는 이미지의 URL을 생성하는 함수이다. src
를 변경하여 다양한 사이즈의 이미지를 요청하는 여러 URL을 생성한다. 이러한 여러 URL은 자동으로 srcset
을 생성하고, 사이트에 방문한 유저가 적절한 사이즈의 이미지를 다운 받도록한다.
default loader는 이미지를 가져와 최적화한 다음에 next.js 웹 서버에서 제공한다. 만약 CDN이나 image server에서 직접 이미지를 가져가도록 하고 싶다면, 직접 loader 함수를 작성할 수 있다. next/image
컴포넌트마다 loader
속성을 지정할 수 있으며, 아니면 어플리케이션 레벨로 next.config.js
에서 loader를 지정할 수 있다.
Domains
remote image를 최적화하고 싶을 때, loader
는 디폴트 설정으로 두고, next/image
컴포넌트의 src
에는 절대경로를 입력한다. 악의적인 공격을 막기 위해 remote hostname을 반드시 정의해야한다. 다음과 같이 next.config.js
에서 정의할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
port: '',
pathname: '/account123/**',
},
{
protocol: 'https',
hostname: '**.example.com',
},
],
},
}
- 와일드카드
*
는hostname
과pathname
에 모두 쓰일 수 있다.*
: 하나의 path segment 또는 subdomain과 매칭된다.**
; 여러 path segment 또는 subdomain과 매칭된다.www.**.com
과 같이 중간 부분에서 적용되진 않는다.
좀 더 간단하게 domain
만 명시할 수도 있다. 하지만 domain
은 와일드카드를 지원하지 알고, protocol
을 지정할 수 없기에 remotePatterns
가 권장된다.
1
2
3
4
5
module.exports = {
images: {
domains: ['assets.acme.com'],
},
}
Priority
priority
속성을 사용하여 이미지 로딩에 우선순위를 둘 수 있다. LCP 엘리먼트에 쓰일 수 있으며, 이미지가 페이지에 접속하자마자 보여야할 때만 사용하는 것이 좋다,
Image Sizing
이미지가 퍼포먼스에 악영향을 미치는 가장 큰 요인은 cumulative layout shift이다 . 이미지가 늦게 로딩되어 다른 엘리먼트를 멀어내는 것을 말한다. 유저의 입장에선 매우 짜증나는 이슈이다.
이 이슈를 막기 위해서는 이미지의 사이즈를 기입해야한다. 이미지의 사이즈를 기업하면, 브라우저는 이미지가 로드되기 전에 이미지를 위한 공간을 미리 잡아둔다.
next/image
에서는 다음 세가지 방법중 하나를 사용한다.
static import
를 통해 이미지를 가져오면 자동으로 계산한다.명시적으로
width
,height
속성을 기입한다.fill
속성은 부모 요소를 채울 때 사용하며, 이 속성을 사용하면,width
,height
를 기입하지 않아도 자동으로 계산된다. 다만 부모 요소의 position이relative
,absolute
,fixed
중 하나여야한다.
Styling
기본적으로는 <img>
태그를 사용할 때와 같지만 아래 주의사항이 있다.
글로벌이 아닌 styled-jsx
대신에 className
또는 style
을 사용한다.
styled-jsx
는 글로벌로 사용하지 않는한 현재 컴포넌트에서만 적용되기에 사용할 수 없다.
fill
속성 사용시, 부모 요소는 position:relative
여야한다.
적절한 사이즈를 계산하기 위해 필요하다.
fill
속성 사용시, 부모요소는 deplay: block
여야한다.
<div>
엘리먼트일 경우엔 이미 적용되어있지만, 다른 엘리먼트라면 명시적으로 설정해야한다.
출처
next/image 가이드 : https://nextjs.org/docs/basic-features/image-optimization
next/image 레퍼런스 : https://nextjs.org/docs/api-reference/next/image