본문 바로가기

프로젝트/You-Together

next.js에서 Open Graph 적용하기

Open Graph란?

- Open Graph (OG)는 Facebook에서 만든 메타데이터 프로토콜로, 웹페이지가 소셜 미디어 플랫폼에서 공유될 때 어떤 정보를 표시할지 제어할 수 있게 해준다.

- 쉽게 말해서 위 이미지와 같이 소셜 미디어 플랫폼에 공유할 때 표시될 제목, 설명, 이미지 등을 오픈그래프를 통해 정의할 수 있다.

문제정의

- you-together는 친구와 youtube 영상을 함께 볼 수 있는 서비스로 별도 로그인 절차 없이 언제든지 간편하게 사용 가능하도록 만들었다.

- 따라서, 링크를 통해 방에 접근하는 경우가 많을 수 밖에 없는데, 기존 SEO(Search Engine Optimizaion, 검색 엔진 최적화)를 위해 metadata를 추가 및 객관적 지표인 크롬 lighthouse에서 SEO 점수를 개선한 것과 별개로 소셜 미디어 플랫폼에 표시되는 제목, 설명, 이미지 등을 정의할 필요가 있었다.

페이스북에서 제공하는 디버그 툴에서 확인한 링크 미리보기
카카오톡으로 링크를 공유했을 때 링크 미리보기

- 위 이미지들은 미리보기를 위한 Open Graph(OG)를 설정하기 전의 링크 미리보기의 모습인데, 링크가 어떤 서비스인지 전혀 가늠할 수가 없다.

- 따라서, Open Graph(OG)를 설정하여 이를 수정해보도록 하겠다.

Open Graph 설정

- Open Graph를 설정하기 전에, 기존에 layout.tsx에 metadata를 설정한 부분은 다음과 같다.

import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import './globals.css';
import { NextUIProviders, ReactQueryProviders } from './providers';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

const inter = Inter({ subsets: ['latin'] });

export const metadata: Metadata = {
  title: 'You Together - 친구와 함께 동영상 시청',
  description:
    'You Together는 친구와 함께 YouTube 동영상을 실시간으로 시청하며 채팅할 수 있는 서비스입니다.',
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en" className="dark bg-application">
      <body className={inter.className}>
        <ReactQueryProviders>
          <NextUIProviders>
            <div className="flex flex-col gap-12">{children}</div>
            <ToastContainer />
          </NextUIProviders>
        </ReactQueryProviders>
      </body>
    </html>
  );
}

 

- 이제 metadata에 Open Graph를 추가 설정해보자.

export const metadata: Metadata = {
  title: 'You Together - 친구와 함께 동영상 시청',
  description:
    'You Together는 친구와 함께 YouTube 동영상을 실시간으로 시청하며 채팅할 수 있는 서비스입니다.',
  openGraph: {
    title: 'You Together - 친구와 함께 동영상 시청',
    description:
      'You Together는 친구와 함께 YouTube 동영상을 실시간으로 시청하며 채팅할 수 있는 서비스입니다.',
    siteName: 'You Together - 친구와 함께 동영상 시청',
    locale: 'ko_KR',
  },
};

- 내가 정의한 Open Graph의 속성은 다음과 같다.

- title : 공유되는 페이지의 제목

- description : 공유되는 페이지의 설명

- siteName : 페이지가 속한 전체 사이트 이름 정의

- locale : 페이지의 언어 및 지역을 지정

- type : 콘텐츠의 유형을 지정

ImageResponse

- 위에 정의한 Open Graph 속성외에 링크를 공유했을 때, image를 표시하고 싶었다.

-하지만, You-Together를 대표하는 디자인된 이미지가 없는 상황이었기 때문에, Next.js에서 제공하는 ImageResponse를 사용했다.

- ImageResponse는 Next.js에서 제공하는 API로 서버에서 HTML과 이미지를 생성해 클라이언트로 전달하는데, JSX와 CSS를 사용하여 동적 이미지를 생성할 수 있다. 즉, 별도의 이미지 파일이 없을 때, JSX와 CSS를 사용하여 동적으로 이미지를 생성할 수 있다.

import { ImageResponse } from 'next/og';

export const size = {
  width: 1200,
  height: 630,
};

const getOpenGraphImage = async () => {
  return new ImageResponse(
    (
      <div
        style={{
          fontSize: 48,
          background: 'white',
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        You-Together 친구와 함께 youtube 시청
      </div>
    ),
    {
      ...size,
    }
  );
};

export default getOpenGraphImage;

- ImageResponse 생성자는 동적 이미지를 생성하기 위한 도구이다. size는 대부분의 소셜 미디어 플랫폼에서 권장하는 OG 이미지 크기로 설정하였다.

ImageResponse는 Next.js에서 제공하는 API로 서버에서 HTML과 이미지를 생성해 클라이언트로 전달하기 때문에

적용 결과

- 아쉬운 점은, 개별적인 방 정보와 재생중인 영상 정보를 기반으로 개별적인 Open Graph 속성을 추가하고 싶었지만, 개별적인 방애서는 채팅 및 실시간 영상 정보 공유를 위한 웹 소켓 연결이 필요해 CSR를 사용하고 있기 때문에 SSR 환경에서 사용하는 ImageResponse를 사용할 수 없어 이를 적용하지 못했다.

 


학습 단계로 잘못된 정보가 있을 수 있습니다. 잘못된 부분에 대해 알려주시면 정정하도록 하겠습니다

참고 : https://velog.io/@sweetpumpkin/Open-Graph-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0

https://velog.io/@doeunnkimm_/%EB%8F%99%EC%A0%81%EC%9C%BC%EB%A1%9C-mete%EC%99%80-og%ED%83%9C%EA%B7%B8-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0-opengraph-image%EA%B9%8C%EC%A7%80

https://miriya.net/blog/MKkWLVdLpZo0tARvG8za

https://nextjs-ko.org/docs/app/building-your-application/optimizing/images