OG 이미지 502 에러, 정적 폴백으로 해결
목차
사용자 공유 기능에서 동적으로 생성되던 OG(Open Graph) 이미지가 standalone 모드에서 502 에러를 반복적으로 던지고 있었다. next/og 패키지를 사용해 실시간으로 썸네일을 만들려던 작업을 결국 정적 이미지 폴백으로 전환한 이야기다.
동적 생성의 매력과 현실의 벽
처음엔 합리적인 선택으로 보였다. 사용자 고유 페이지마다 다른 이미지를 동적으로 렌더링하면, 공유할 때마다 맥락에 맞는 이미지가 표시된다. Next.js 의 next/og 는 이를 위해 설계된 라이브러리고, 메타데이터 라우팅 패턴도 깔끔했다. 하지만 실제 운영 환경(standalone 빌드)에 배포했을 때 문제가 터졌다.
Vercel 이나 일반 클라우드 serverless 환경에서 동적 이미지 생성은 생각보다 비싼 작업이다. 이미지 처리 라이브러리(Skia, Cairo 등)가 CPU와 메모리를 크게 잡아먹고, 콜드 스타트 환경에선 더욱 그렇다. 요청이 타임아웃되거나 리소스 제한에 걸려 502 게이트웨이 에러가 반복되는 상황이 생긴 것.
선택의 기준: 비용 대 효과
| 접근법 | 장점 | 단점 | 환경 친화도 |
|---|---|---|---|
| 동적 next/og | 페이지마다 맥락 있는 이미지 | 리소스 비용, 502 위험 | ❌ serverless 부적합 |
| 정적 og.jpg 폴백 | 빠름, 안정적, 예측 가능 | 모든 페이지가 같은 이미지 | ✅ 가볍고 신뢰성 높음 |
| CDN 캐싱 + 동적 | 재사용 가능, 빠른 응답 | 초기 생성 시 여전히 502 위험 | △ 부분적 해결 |
팀 관점에서 결정 요소는 이랬다:
- 안정성 우선: 공유 이미지가 깨지는 것보다 같은 이미지라도 일관되게 표시되는 게 낫다
- 유지보수 비용: 동적 이미지 재생성, 캐싱 전략 관리를 줄일 수 있다
- 공유 버튼 기능: 버튼 자체는 동작하고, 단지 이미지만 정적화하면 된다
구현: 최소 변경으로 최대 효과
// opengraph-image.tsx → 제거됨
// next/og 동적 생성 로직 삭제
// 대신 public/og.jpg 를 상속 폴백으로 처리
// src/app/layout.tsx 의 메타데이터 설정에서
export const metadata = {
openGraph: {
images: [
{
url: '/og.jpg',
width: 1200,
height: 630,
}
]
}
}
파일 제거는 간단했지만, 정책 결정이 중요했다:
- 동적 라우트를 버리되, public 에 정적 og.jpg 배치
- 모든 공유 링크가 같은 이미지 사용 (브랜드 대표 이미지)
- 향후 필요시 AWS Lambda 같은 외부 이미지 생성 서비스로 대체 가능하게 아키텍처 열어둠
돌아본 것들
이 결정에서 배운 점:
- "동적이 항상 좋다" 는 아니다 — serverless 환경의 제약을 먼저 이해해야 한다.
- 초기 설계 검증 중요 — 프로토타입 단계에서 standalone 빌드로 테스트했으면 이 문제를 미리 잡았을 것.
- 트레이드오프 명시 — 팀원들에게 "이미지가 정적화됩니다, 대신 공유 안정성 상승" 을 분명히 전달.
- 폴백의 가치 — 완벽함보다 견고함. 정적 og.jpg 는 동적 생성 실패의 좋은 대체 방안.
비슷한 상황은 자주 만난다. 사용자 프로필 썸네일, 동적 배너, 실시간 차트 이미지 등이 그렇다. 각 경우마다 "이게 정말 동적이어야 하나? 정적 폴백이 충분하지 않나?" 라고 묻는 습관이 생겼다.
🛒 이 글과 어울리는 추천 상품
*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.
댓글 0
첫 댓글 달아줘.