Tech| 읽는 데 5분

Next.js에서 섬네일 이미지 쉽게 생성하기

Vercel/og를 사용해서 섬네일과 OG(Open Graph) image를 자동으로 생성하는 방법

#Nextjs#thumbnail#OgImage#Vercel
목차

섬네일, 매번 만들어야 하는가..?

블로그에 글을 작성할 때, 섬네일(thumbnail)을 매번 직접 만드는 것은 번거로운 작업이다.

미니픽이라는 프로젝트를 통해, 섬네일을 직접 만들었지만, 제목 등을 직접 입력해야 하므로, 추가적인 작업 시간이 소요된다는 점을 개선할 필요가 있었다.

@vercel/og 라이브러리를 도입해서, 포스트 제목에 대해 자동으로 이미지를 생성하도록 해서 이를 해결할 수 있었다.

어떻게 만들었는가?

Next.js 13의 app router를 사용하는 프로젝트에서, @vercel/og로 이미지를 생성하는 방법은 아래와 같다.

먼저, app 디렉토리에 og 폴더를 만들고, route.tsx 파일을 생성하고, 아래와 같이 구현했다.

import { ImageResponse } from 'next/server';
 
export const runtime = 'edge';
 
export async function GET(request: Request) {
  try {
    const { searchParams } = new URL(request.url);
 
    const hasTitle = searchParams.has('title');
    const title = hasTitle
      ? searchParams.get('title')?.slice(0, 100)
      : 'Woongsnote';
 
    const size = { width: 1200, height: 630 };
 
    return new ImageResponse(
      (
        <div
          style={{
            height: '100%',
            width: '100%',
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center',
            justifyContent: 'center',
            backgroundImage:
              'linear-gradient(to bottom right, #00C0FF, #4218B8)',
            fontSize: 64,
            fontWeight: 600,
          }}
        >
          <div style={{ color: 'white' }}>{title}</div>
        </div>
      ),
      {
        ...size,
      }
    );
  } catch (error) {
    return new Response(`Failed to generate the Image`, { status: 500 });
  }
}

그리고, Metadata 설정하는 부분에서 아래와 같이 호출하면 된다.

 
...
    openGraph: {
      images: [
        {
          url: `/og?title=${post.title}`,
          width: 1200,
          height: 630,
          alt: post.title,
        },
      ],
    },
...
 

이 이미지를 섬네일로 사용하는 방법은?

Next.js에서 제공하는 <Image /> 컴포넌트에 og image로 생성한 url을 입력하면 섬네일로 사용할 수 있다.

배포 후에 만난 오류

Local 상태에서 yarn build && yarn start로 build해서 test했을 때는, 섬네일이 정상적으로 나왔었다. 하지만, 배포하고 나서 접속했을 때는, 400 Error를 마주하게 되었다.

해당 에러에 대해 검색해 본 결과, 이미지 주소의 Remote Patttern이 빠져서 생긴 오류임을 확인했다.

next.config.js 파일에 아래와 같이 image 주소의 Remote pattern을 추가하고,

      {
        protocol: 'https',
        hostname: '배포한 url 주소',
        port: '',
        pathname: '/og/**',
      },

섬네일 이미지의 src의 경로를 /og?title=${title}에서 ${"배포한 url 주소"}/og?title=${title} 로 수정 후 다시 배포해서 정상적으로 동작하는 것을 확인했다.

최신 버전 내용 추가(2024.05)

공식 문서에 추가된 내용이 있어 이를 기록한다.

og-image를 생성하려는 폴더에 opengraph-image.tsx 파일을 아래와 같이 생성한다.

opengraph-image.tsx - static image
import { ImageResponse } from 'next/og';
 
//Image metadata
export const alt = 'Alt text';
export const size = {
  width: 1200,
  height: 630,
};
 
export const contentType = 'image/png';
 
// Image generation
export default async function Image() {
  return new ImageResponse(
    (
      <div
        style={{
          width: '100%',
          height: '100%',
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          justifyContent: 'center',
          textAlign: 'center',
          color: 'white',
          textShadow: `rgba(0, 0, 0, 0.4) 2px 2px 4px`,
          border: 'none',
        }}
      >
        <h2 style={{ fontSize: 56 }}>How to make thumbnail Easy</h2>
      </div>
    ),
    {
      ...size,
    }
  );
}

※ slug 등을 사용해서 동적으로 생성하고자 한다면 아래와 같이 params를 추가해서 사용할 수 있다.

opengraph-image.tsx - dynamic params
export default function Image({ params }: { params: { slug: string } }) {
  // ...
}