icon안동민 개발노트

Open Graph 태그 활용


 Open Graph 프로토콜은 웹페이지가 소셜 미디어 플랫폼에서 어떻게 표시될지를 제어하는 메타데이터 세트입니다.

 Next.js에서 Open Graph 태그를 효과적으로 활용하면 소셜 미디어 최적화(SMO)를 통해 콘텐츠의 가시성과 공유 가능성을 크게 향상시킬 수 있습니다.

기본 Open Graph 태그 설정

 Next.js의 메타데이터 API를 사용하여 기본 Open Graph 태그를 설정할 수 있습니다.

app/layout.js
export const metadata = {
  openGraph: {
    title: 'My Website',
    description: 'Welcome to my website',
    url: 'https://www.mywebsite.com',
    siteName: 'My Website',
    images: [
      {
        url: 'https://www.mywebsite.com/og-image.jpg',
        width: 1200,
        height: 630,
      },
    ],
    locale: 'en_US',
    type: 'website',
  },
}

동적 콘텐츠 Open Graph 태그 생성

 동적 라우트나 데이터에 기반한 페이지의 경우, generateMetadata 함수를 사용하여 동적으로 Open Graph 태그를 생성할 수 있습니다.

app/blog/[slug]/page.js
export async function generateMetadata({ params }) {
  const post = await getPost(params.slug)
  
  return {
    openGraph: {
      title: post.title,
      description: post.excerpt,
      url: `https://www.mywebsite.com/blog/${post.slug}`,
      images: [
        {
          url: post.ogImage || '/default-og-image.jpg',
          width: 1200,
          height: 630,
        },
      ],
      type: 'article',
      article: {
        publishedTime: post.publishDate,
        authors: [post.author],
      },
    },
  }
}

플랫폼별 메타 태그 차이점

 각 소셜 미디어 플랫폼은 약간 다른 메타 태그를 사용할 수 있습니다.

 예를 들어, Twitter는 twitter:card 태그를 사용합니다.

export const metadata = {
  openGraph: {
    // Open Graph 태그
  },
  twitter: {
    card: 'summary_large_image',
    title: 'My Website',
    description: 'Welcome to my website',
    images: ['https://www.mywebsite.com/twitter-image.jpg'],
  },
}

동적 Open Graph 이미지 생성 및 최적화

 동적 Open Graph 이미지 생성은 콘텐츠의 시각적 표현을 개선하는 강력한 방법입니다.

 Next.js의 API 라우트를 사용하여 동적 이미지를 생성할 수 있습니다.

app/api/og/route.js
import { ImageResponse } from 'next/server'
 
export async function GET(request) {
  const { searchParams } = new URL(request.url)
  const title = searchParams.get('title')
 
  return new ImageResponse(
    (
      <div
        style={{
          fontSize: 48,
          background: 'white',
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        {title}
      </div>
    ),
    {
      width: 1200,
      height: 630,
    }
  )
}

 이 API 라우트를 Open Graph 이미지로 사용할 수 있습니다.

export async function generateMetadata({ params }) {
  const post = await getPost(params.slug)
  
  return {
    openGraph: {
      images: [
        {
          url: `https://www.mywebsite.com/api/og?title=${encodeURIComponent(post.title)}`,
          width: 1200,
          height: 630,
        },
      ],
    },
  }
}

12장 이미지 최적화와의 연결

 13장의 Open Graph 이미지 생성은 12장에서 다룬 이미지 최적화와 밀접하게 연관됩니다.

 동적으로 생성된 Open Graph 이미지에도 Next.js의 이미지 최적화 기능을 적용할 수 있습니다.

 예를 들어, next/image 컴포넌트를 사용하여 Open Graph 이미지를 최적화할 수 있습니다.

import Image from 'next/image'
 
export default function BlogPost({ post }) {
  return (
    <article>
      <Image
        src={`/api/og?title=${encodeURIComponent(post.title)}`}
        alt={post.title}
        width={1200}
        height={630}
        priority
      />
      {/* 게시물 내용 */}
    </article>
  )
}

 이렇게 하면 Open Graph 이미지도 Next.js의 자동 이미지 최적화 기능의 이점을 누릴 수 있습니다.

실습 : 동적 데이터 기반의 Open Graph

 블로그 포스트의 제목과 작성자 정보를 포함하는 동적 Open Graph 이미지를 생성하고 적용하는 실습을 해보겠습니다.

  1. 동적 이미지 생성 API 라우트 생성
app/api/og/route.js
import { ImageResponse } from 'next/server'
import { loadGoogleFont } from '@/lib/fonts'
 
export async function GET(request) {
  const { searchParams } = new URL(request.url)
  const title = searchParams.get('title')
  const author = searchParams.get('author')
 
  const inter = await loadGoogleFont({ family: 'Inter', weight: 400 })
  const interBold = await loadGoogleFont({ family: 'Inter', weight: 700 })
 
  return new ImageResponse(
    (
      <div
        style={{
          width: '100%',
          height: '100%',
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'flex-start',
          justifyContent: 'center',
          backgroundColor: '#fff',
          padding: 80,
        }}
      >
        <div style={{
          fontSize: 60,
          fontWeight: 700,
          fontFamily: 'Inter',
          marginBottom: 40,
        }}>
          {title}
        </div>
        <div style={{
          fontSize: 40,
          fontFamily: 'Inter',
          color: '#666',
        }}>
          By {author}
        </div>
      </div>
    ),
    {
      width: 1200,
      height: 630,
      fonts: [
        { name: 'Inter', data: inter, weight: 400 },
        { name: 'Inter', data: interBold, weight: 700 },
      ],
    }
  )
}
  1. 블로그 포스트 페이지에 동적 Open Graph 이미지 적용
app/blog/[slug]/page.js
export async function generateMetadata({ params }) {
  const post = await getPost(params.slug)
  
  const ogImageUrl = new URL('/api/og', 'https://www.mywebsite.com')
  ogImageUrl.searchParams.append('title', post.title)
  ogImageUrl.searchParams.append('author', post.author)
 
  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      url: `https://www.mywebsite.com/blog/${post.slug}`,
      images: [
        {
          url: ogImageUrl.toString(),
          width: 1200,
          height: 630,
        },
      ],
      type: 'article',
      article: {
        publishedTime: post.publishDate,
        authors: [post.author],
      },
    },
    twitter: {
      card: 'summary_large_image',
      title: post.title,
      description: post.excerpt,
      images: [ogImageUrl.toString()],
    },
  }
}
 
export default async function BlogPost({ params }) {
  const post = await getPost(params.slug)
  
  return (
    <article>
      <h1>{post.title}</h1>
      <p>By {post.author}</p>
      {/* 게시물 내용 */}
    </article>
  )
}

 이 실습을 통해 동적 데이터를 기반으로 Open Graph 이미지를 생성하고 적용하는 방법을 익힐 수 있습니다.

 이 접근 방식은 각 블로그 포스트에 대해 고유하고 시각적으로 매력적인 Open Graph 이미지를 제공하여 소셜 미디어에서의 공유 효과를 극대화합니다.

 Next.js의 Open Graph 태그 활용은 웹사이트의 소셜 미디어 최적화에 중요한 역할을 합니다.

 동적 콘텐츠에 대한 맞춤형 Open Graph 태그와 이미지를 생성함으로써, 각 페이지의 공유 가능성과 시각적 매력을 높일 수 있습니다.

 이는 궁극적으로 웹사이트의 가시성과 트래픽 증가로 이어질 수 있습니다.