이미지 프록시
Discord가 지원되는 외부 CDN의 프레즌스 이미지를 직접 불러오지 못할 때 Nowly 이미지 프록시를 사용하세요.
사용 목적
이미지 프록시는 특정 상황을 위한 기능입니다. 프레즌스는 페이지의 공개 이미지를 볼 수 있지만 Discord는 원본 URL에서 이미지를 안정적으로 불러오지 못할 수 있습니다.
외부 CDN의 동영상 썸네일, 아바타, 포스터 또는 카테고리 이미지에 다음 문제가 있을 때 유용합니다.
- 이미지가 공개되어 있고 브라우저에 이미 표시됩니다.
- CDN URL이 Discord Rich Presence에서 사용하기에 너무 깁니다.
- Discord가 원본 이미지를 거부하거나, URL이 만료되거나, 다운로드에 실패합니다.
- 서비스 로고 대신 콘텐츠에 맞는 이미지를 표시해야 합니다.
범용 이미지 프록시가 아닙니다. API는 명시적으로 허용된 서비스와 도메인만 받습니다.
작동 방식
권장 흐름에서는 일시적인 짧은 URL을 사용합니다.
TXTPOST https://api.nowly.me/images-proxy
GET https://api.nowly.me/images-proxy/<id>프레즌스가 실제 CDN 이미지 URL을 API에 보냅니다. API는 서비스 지원 여부를 확인하고 이미지를 다운로드한 뒤 MIME 유형과 크기를 검증하여 잠시 캐시합니다. 다음과 같은 짧은 URL을 반환합니다.
TXThttps://api.nowly.me/images-proxy/abc123...이 URL은 올바른 Content-Type과 함께 이미지 데이터를 직접 반환합니다. largeImageKey 또는 smallImageKey에 사용하도록 설계되었습니다.
import { createCachedImageProxyUrl } from "@nowly/sdk"
const image = await createCachedImageProxyUrl("tiktok", imageUrl)
await presence.setActivity({
details: "Watching a video",
largeImageKey: image ?? Assets.Logo,
})캐시는 단기간 유지되며 현재는 5분입니다. 헬퍼는 프레즌스 내부에도 메모리 캐시를 유지해 업데이트할 때마다 API를 호출하지 않습니다.
직접 엔드포인트
기존 직접 프록시는 수동 테스트나 이미 충분히 짧은 URL에 계속 사용할 수 있습니다.
TXThttps://api.nowly.me/image-proxy?service=<service>&url=<encoded-url>
https://api.nowly.me/i?u=<encoded-url>url과 u 값은 encodeURIComponent로 인코딩해야 합니다. Discord는 이미지 키를 300자로 제한하므로 Rich Presence에는 createCachedImageProxyUrl을 권장합니다.
프레즌스에서 설정하기
먼저 페이지에서 실제 이미지 URL을 추출합니다.
const getPoster = (video: HTMLVideoElement): string | undefined => {
if (video.poster) return video.poster
const image = video.closest("[data-video]")?.querySelector("img")
return image?.getAttribute("src") ?? undefined
}활동을 설정하기 전에 해당 URL을 헬퍼에 전달합니다.
import { createCachedImageProxyUrl } from "@nowly/sdk"
const poster = await createCachedImageProxyUrl("tiktok", getPoster(video))
await presence.setActivity({
details: "Watching a video",
largeImageKey: poster ?? Assets.Logo,
})대체 이미지를 항상 준비하세요. 페이지에 이미지가 없거나 너무 크거나 출처가 허용되지 않아도 프레즌스는 Assets.Logo 또는 로컬 이미지로 계속 동작해야 합니다.
서비스 추가
허용 도메인은 프레즌스가 아닌 API에서 확인합니다. 실행 중에 요청하는 것만으로 임의의 도메인을 프록시할 수는 없습니다. 별도 승인 단계나 API 코드 변경 없이, 프레즌스의 metadata.json에 필요한 호스트를 직접 선언하세요. 헬퍼에 전달한 것과 동일한 service 값(프레즌스 슬러그)을 사용합니다.
"imageProxy": {
"hostSuffixes": ["netflix.com", "nflxvideo.net", "nflximg.net"],
"headers": { "Referer": "https://www.netflix.com/" }
}선언은 나머지 metadata.json과 함께 API에 자동으로 게시됩니다. API는 해당 프레즌스 자신의 service ID에 대해서만 선언을 신뢰합니다. 다른 프레즌스를 대신해 호스트 이름을 선언할 수 없고, 대상 URL의 호스트 이름이 선언된 접미사 중 하나와 실제로 일치해야 요청이 허용됩니다.
PR에서 imageProxy를 변경하면 프레즌스 미리보기 봇이 이를 자동으로 감지하고, 선언된 호스트 이름을 나열한 Image Proxy Requested 섹션을 댓글에 추가하며 image-proxy 라벨을 적용합니다. 병합 전 검토자가 호스트가 공개되어 있고 프록시에 안전한지 확인해야 합니다. Discord가 원본 이미지 URL을 사용할 수 없는 이유와 사용자에게 표시될 이미지를 PR에 설명하세요.
제한 및 보안
프록시는 검토된 프레즌스가 선언한 호스트의 공개 이미지만 제공합니다. HTTPS가 아닌 URL, 선언된 접미사와 일치하지 않는 호스트, 이미지가 아닌 응답, 너무 큰 파일은 거부합니다.
엔드포인트는 공개되어 있으며 인증이 필요하지 않습니다(프레즌스가 브라우저에서 직접 호출하므로 첨부할 비밀 정보가 없습니다). API의 전체 요청 제한을 공유하며 프레즌스별 할당량은 없습니다. 비공개 계정 콘텐츠, 인증이 필요한 리소스, 추적 URL, 임의의 사용자 입력 또는 이미지가 아닌 콘텐츠에는 프록시를 사용하지 마세요.