이미지 URL에 서명하기

OG 이미지 URL은 다음과 같습니다.

https://api.mocco.club/v1/og/<project id>/article.png?brand=Acme%20Docs&title=Install%20in%20five%20minutes&s=<signature>

항목은 쿼리 파라미터이고 s가 서명입니다. URL 전체를 페이지의 og:image(와 twitter:image) 태그에 넣으세요. 이미지를 불러올 때 API 키는 필요 없습니다. 서명이 곧 인증입니다.

먼저 프로젝트의 서명 시크릿을 만드세요(서명 시크릿 참고).

콘솔에서

프로젝트를 열고 API 키로 가서 OG 이미지 서명 카드의 템플릿 갤러리 열기를 누릅니다. OG 이미지 페이지는 모든 멤버가 쓸 수 있습니다.

  1. 템플릿을 고릅니다. 항목 입력란이 나타나고, 브랜드에는 프로젝트 이름이, 강조 색상에는 헬프 센터에 강조 색상이 있으면 그 색이 미리 들어갑니다.

  2. 항목을 채웁니다. 입력하는 대로 미리보기가 다시 그려지고, 너무 길거나 필수인데 비어 있는 항목은 보내기 전에 알려 줍니다.

  3. 서명된 URL 복사를 누르거나, 코드 탭에서 지금 값이 들어간 @mocco/node 코드를 복사합니다.

article 템플릿을 채운 OG 이미지 페이지와 미리보기

시크릿이 없으면 페이지에 그렇게 표시됩니다. 소유자와 관리자에게는 시크릿을 만드는 링크가, 다른 멤버에게는 누가 만들 수 있는지가 보입니다.

미리보기는 저장되지 않고 프로젝트의 이미지 한도에도 포함되지 않지만, 한 사람이 1분에 30번까지 그릴 수 있습니다.

서버에서 @mocco/node로

import { createOgSigner } from '@mocco/node';

const og = createOgSigner({
  projectId: process.env.MOCCO_PROJECT_ID,
  secret: process.env.MOCCO_OG_SECRET,
});

const image = og.url({
  template: 'article',
  params: { brand: 'Acme Docs', eyebrow: 'Guides', title: 'Install in five minutes' },
});
// https://api.mocco.club/v1/og/<project id>/article.png?…&s=…

서명은 네트워크 요청 없이 서버에서 이루어지므로, 페이지를 그릴 때마다 하거나 빌드할 때 해도 됩니다. 이미 createMoccoServer를 쓰고 있다면 og: { projectId, secret }을 넘기고 server.og.url(…)을 부르세요. undefined로 둔 항목은 빠집니다. 서명 도구는 시크릿과 프로젝트 ID만 확인하고, 항목은 이미지를 불러올 때 Mocco가 확인합니다.

다른 언어에서

서명을 직접 만듭니다.

  1. s를 뺀 모든 항목을 이름순으로 정렬하고, JavaScript의 encodeURIComponent처럼 이름과 값을 인코딩해 name=value 쌍을 &로 잇습니다.

  2. /v1/og/<project id>/<template>.png?<이은 항목> 문자열을 만듭니다. Mocco API가 다른 호스트나 경로 아래에서 제공되더라도 이 경로를 씁니다.

  3. 시크릿(64자 문자열을 UTF-8로)을 키로 이 문자열의 HMAC-SHA256을 구하고, base64url로 인코딩해 앞 32자를 남깁니다. 이것이 s입니다.

  4. URL 끝에 &s=<서명>을 붙입니다. 최종 URL에서 파라미터 순서는 상관없습니다.

import { createHmac } from 'node:crypto';

function ogImageUrl(projectId, template, fields, secret) {
  const path = `/v1/og/${projectId}/${template}.png`;
  const query = Object.keys(fields)
    .sort()
    .map(name => `${encodeURIComponent(name)}=${encodeURIComponent(fields[name])}`)
    .join('&');
  const s = createHmac('sha256', secret).update(`${path}?${query}`).digest('base64url').slice(0, 32);
  return `https://api.mocco.club${path}?${query}&s=${s}`;
}

Mocco의 응답

상황응답
없는 템플릿, 또는 서명 시크릿이 없는 프로젝트404
서명이 없거나 맞지 않음(다른 프로젝트의 시크릿이나 교체 전 시크릿으로 서명한 경우 포함)401
필수 항목이 없거나, 템플릿에 없는 항목, 한도를 넘는 값, 잘못된 accent400, 문제가 된 항목을 알려 줌
프로젝트에서 1분에 새로 그리는 이미지가 60개를 넘음429, Retry-After 포함
그 밖의 경우PNG 이미지, 하루 동안 캐시

1분에 60개 한도에는 새로 그리는 경우만 포함됩니다. 한 번 그린 이미지는 같은 URL로 다시 불러오면 저장된 이미지로 제공됩니다. 크롤러가 렌더링을 기다리는 일이 없게 하려면 CI에서 이미지를 미리 그려 두세요.

항목을 바꾸면 URL이 바뀌고, 그래서 이미지도 바뀝니다. 카카오톡 같은 앱이 이미 캐시한 카드를 새로 고치는 방법도 이것입니다. 이런 앱은 예전 URL을 다시 가져오지 않습니다.