개발 slecs

공유할 때 결과별 미리보기 카드 자동 생성

목차

이번엔 사용자들이 SNS에서 우리 서비스의 결과를 공유할 때 보여주는 미리보기 카드를 동적으로 생성하도록 개선했다. 링크를 카톡이나 X, 페이스북에 붙여넣으면 각 플랫폼이 자동으로 읽어가는 OG 메타데이터를 결과 타입(별자리/일간)별로 다르게 렌더링하는 작업이다.

배경: 왜 OG 카드 동적 생성이 필요했나

결과 공유 URL을 그냥 텍스트로만 공유하면 재미가 없다. SNS에서 링크를 미리보기로 표시할 때 "무언가 흥미로운 콘텐츠"라는 신호를 보내줘야 클릭율이 올라간다. 특히 우리처럼 개인화된 결과(별자리 리딩, 일간 운세 등)를 보여주는 서비스는 "내 결과를 남들한테 자랑하고 싶은" 욕구가 있다.

기존에는 정적인 OG 이미지를 썼겠지만, 이제는 결과별로 다르게 보여주고 싶었다. 사용자A의 별자리 결과와 사용자B의 일간 결과가 링크상으로는 다른 이미지를 띠어야 한다는 뜻이다. 이렇게 하면 공유 시점에 "내 결과를 정확히 반영한 카드"가 보여서 더 개인화된 경험을 만들 수 있고, 자연스럽게 바이럴 효과도 높아진다.

구현: 결과별 메타데이터를 동적으로

파일 구조를 보면 두 가지를 수정했다:

파일 역할 변경의 의미
opengraph-image.tsx OG 이미지 동적 생성 엔드포인트 결과 타입별로 다른 이미지를 렌더링
reading-panel.tsx 결과 판독/표시 UI 공유 버튼을 UI에 통합 + OG 메타데이터 전달

opengraph-image.tsx는 Next.js의 ImageResponse API를 쓰는 게 일반적이다. URL 파라미터([uid])에서 사용자 결과를 조회하고, 그 결과의 타입(별자리인지 일간인지)을 감지한 후 각각 다른 레이아웃, 색상, 텍스트로 이미지를 동적 생성하는 식이다.

// 결과 타입별 다른 OG 이미지 생성 패턴
export async function GET(request, { params }) {
  const result = await getResultFromDB(params.uid)

  if (result.type === 'astrology') {
    return new ImageResponse(
      <AstrologyOGCard data={result} />,
      { width: 1200, height: 630 }
    )
  } else if (result.type === 'daily') {
    return new ImageResponse(
      <DailyOGCard data={result} />,
      { width: 1200, height: 630 }
    )
  }
}

여기서 중요한 건 캐싱 전략이다. 같은 uid에 대해 반복적으로 요청이 올 때마다 DB를 조회하고 이미지를 렌더링하면 성능이 저하된다. Next.js의 ISR(Incremental Static Regeneration)이나 외부 CDN 캐싱을 활용해서 한번 생성한 이미지는 재사용하도록 설정하는 게 필수다. 특히 결과가 변하지 않는 한 같은 이미지를 계속 쓸 수 있으니, 최대한 오래 캐시하는 게 좋다.

reading-panel.tsx는 사용자가 결과를 보는 화면이다. 여기서 "공유" / "X로 공유" / "페이스북 공유" 버튼을 추가했다. 각 버튼은 플랫폼별 공유 URL을 호출하고, SNS 크롤러가 우리의 opengraph-image.tsx 엔드포인트에서 메타데이터를 받아가도록 하는 구조다.

회고: 비슷한 작업할 때 고려할 점

이런 동적 콘텐츠 공유 작업을 할 때 팀 리뷰에서 자주 나오는 포인트들:

  • 메타데이터 검증이 까다롭다: OG 이미지가 제대로 생성되는지 로컬에서는 확인하기 어렵다. 배포 전에 Facebook Sharing Debugger, LinkedIn 미리보기, Twitter Card validator 같은 도구를 써서 실제 플랫폼에서 검증해야 한다. 이 단계를 빼먹으면 배포 후 "왜 이미지가 안 떠?" 같은 보고가 들어온다.

  • 결과 타입별 로직을 초반부터 분리하기: 별자리/일간처럼 여러 결과 타입을 지원할 때는 각 타입마다 OG 카드 레이아웃이 달라질 수 있다. 처음엔 "모두 같은 템플릿 쓰면 되지 않나?" 생각하기 쉽지만, 실제로는 텍스트 길이, 강조색, 부가 정보 등이 타입별로 다르다. 초반부터 타입별 컴포넌트를 분리하는 게 나중에 수정하기 훨씬 쉽다.

  • 성능과 공유 UX: 공유 버튼을 눌렀을 때 지연이 발생하면 사용자는 답답해한다. 이미지 생성 로직이 무거우면 백그라운드 큐(queue)에서 처리하거나, 미리 생성해두는 방식도 고려할 가치가 있다.

  • 소셜 메타데이터의 세부사항: 제목, 설명, 이미지뿐 아니라 og:type, twitter:card, og:url 등 세부 메타도 정확히 설정해야 각 플랫폼에서 제대로 렌더링된다. 초기 설정이 부실하면 나중에 수정하는 데 시간이 오래 걸린다.

결과를 공유할 때 단순히 "링크를 복사했습니다" 메시지만 보여주는 것보다, SNS에 붙였을 때 예쁘게 보이는 카드가 뜨면 자연스럽게 클릭과 재공유가 늘어난다. 이 작업이 그런 점에서 의미 있었다고 본다.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.