📢 어렵고 정석적인 개념 설명보다는 저같은 초보자도 이해하기 쉽게 정리하는 것을 원칙으로 포스팅하고 있습니다. 😄

[Next.js] 이미지 넣는 방법 : Image 컴포넌트 활용하여 최적화하기

Image를 쓰는 이유

Next.js에서는 이미지를 넣을 때 <img> 태그를 사용하기도 하지만, 최적화를 위해 Image 컴포넌트를 주로 사용한다.

그렇다면, 어떻게 이미지 최적화를 시켜주고 어떤 기능이 있는지 대표적인 3가지 기능을 살펴보자.

 

1. 이미지 사이즈 최적화

Image 컴포넌트를 통해 이미지를 넣고 개발자 도구로 확인해 보면 img 태그 속성에 'srcset'이 있는 걸 확인할 수 있다.

srcset 속성은 Image 컴포넌트가 디바이스 별로 미리 지정해 둔 크기에 맞춰 이미지를 다운로드할 수 있게 도와주는 속성이라고 생각하면 된다. 예를 들어, 우리가 아이폰 미니로 접속한다면 1920px 사이즈의 큰 이미지를 다운로드할 필요가 없다. 즉, 사용자의 디바이스 크기가 작다면 알아서 작은 크기에 맞는 이미지를 다운로드하게 된다.

 

사이즈가 작아지면 이미지의 크기 또한 작아질 것이고, 이미지 확장자 또한 용량이 작은 webp 포맷으로 변환되기 때문에 사용자들은 이미지 다운로드를 더 빠르게 할 수 있게 돼서 최종적으로는 페이지를 빠르게 이용할 수 있게 된다.

 

2. Lazy Loading

이름부터 생소한 Lazy Loading은 한 마디로 이미지 로드의 시점을 필요할 때까지 지연시키는 기술을 말한다. 예를 들어 한 페이지에 50개의 이미지가 있다고 하고, 뷰포트에는 10개의 이미지가 보인다고 하자. 생각해 보면 스크린 밖에 있는 이미지까지 모두 한 번에 로드할 필요는 없다. (현재 화면에 보이는 이미지만 우선적으로 다운로드하면 된다.) 50개의 이미지를 다운로드하는 시간보다 10개의 이미지를 다운로드하는 시간이 당연히 짧고 빠르다. 결국 이것 역시 빠른 페이지 로드를 도와준다.

 

3. placeholder

input 태그에만 있는 속성이 아니다. Image 컴포넌트의 placeholder 속성은 이미지가 로드되기 전 이미지의 크기만큼 빈 영역을 잡아주는 기능이다. 예를 들어, 이미지와 그 밑에 버튼이 하나 있다고 하자. 이미지의 크기가 너무 커서 이미지가 로드되는데 시간이 걸린다고 할 때, 버튼의 위치는 이미지의 높이만큼 원래 위치보다 위쪽으로 올라가 있을 것이다. 그리고 이미지가 로드되면 그제서야 버튼은 본래 자리로 돌아가게 된다. (전체적인 페이지 레이아웃이 순간 흔들릴 수 있다.)

즉, placeholder 기능을 사용하면 이미지가 로드되기 전 빈 영역의 자리를 잡아주기 때문에 페이지 레이아웃이 흔들리는 것을 방지할 수 있다.

 

사용 방법

// 로컬 이미지의 경우

import Image from "next/image";
import temp from "/public/temp.jpg";

function Home() {
    return (
        <div>
            <Image src={temp} alt={} placeholder="blur" />
        </div>
    )
}

public 폴더에 있는 이미지(로컬 이미지)를 사용하는 경우 width와 height 값은 필수로 넣어주지 않아도 된다.

대신, 이미지 경로를 src에 직접 넣는 게 아닌 반드시 import 해서 사용해야 한다. 위 예시 코드를 보면 temp라는 이름으로 로컬 이미지를 불러오고 있다. 

 

// 리모트(외부) 이미지의 경우

import Image from "next/image";

function Home() {
    return (
        <div>
            <Image src={https://abc.co.kr/img.jpg} alt={} width={500} height={300} />
        </div>
        
        // OR (반응형 이미지로 사용하고 싶다면)
        // CSS로 이미지의 position을 relative로 바꾸고 width를 부모 태그 CSS에서 컨트롤.
        
        <div>
            <Image src={https://abc.co.kr/img.jpg} alt={} fill />
        </div>
    )
}

// next.config.js
module.exports = {
    images: {
        domains: ['abc.co.kr']
    }
}

로컬 이미지가 아닌 외부에서 이미지를 가져오는 경우에는 사용 방법이 조금 달라진다. src에 이미지 주소를 넣고, 반드시 width와 height 값을 넣어줘야 한다. 따로 사이즈 없이 전체를 채우고 싶다면 fill 속성을 사용해도 된다.

그리고, src에 이미지 주소를 넣는다고 해서 끝이 아니다. next.config.js에 들어가서 images의 domains에 사용할 이미지의 호스트를 넣어줘야 한다. 이것은 이미지를 서빙하는 서버가 안전하다는 것을 Next.js에 알려줘야 하기 때문이다.

 

width와 height를 직접 지정하면 사이즈가 고정되므로 반응형 페이지에서는 사용하기가 조금 애매할 수 있다. Image 컴포넌트로 만들어진 이미지는 기본적으로 position의 값이 absolute로 되어 있다. (그렇기 때문에 Image 컴포넌트를 쓸 때는 부모 태그의 position을 relative로 맞춰줘야 한다.) 이것을 relative로 바꾸고 width와 height 대신 fill 속성을 넣어주면 높이가 너비에 맞춰 변하는 반응형 이미지를 만들 수도 있다.

 

1. 이미지 최적화 : 디바이스 크기에 맞춰서 이미지 크기를 로드함. 작은 디바이스가 굳이 큰 파일을 받을 필요 X
2. Lazy Loading : 내가 보는 페이지의 이미지만 우선적으로 로드함. 전체 페이지의 이미지를 한 번에 로드할 필요 X
3. placeholder : 이미지가 로드되기 전 빈 영역의 자리를 잡아줌. 페이지 레이아웃이 흔들리는 걸 방지.
4. 로컬 이미지로 사용할 경우 반드시 import 해서 사용하기. width, height 안 줘도 됨.
5. 외부 이미지를 가져다 쓸 경우 width, height는 필수! (width, height 대신 fill로 주고 CSS로 relative 줘도 됨)
5-1. next.config.js에 외부 도메인 호스트 입력해줘야 함. ☞ next.js에게 이 도메인은 안전해라는 것을 알려줌