Car Image API

활용 사례 · 렌터카

렌터카 차량 페이지용 자동차 이미지

모든 렌터카 클래스를 같은 방식으로 보여 주세요. 클래스마다 대표 모델 하나, trim, padding, fit을 적용한 동일한 구도, 이름이 지정된 도장 색상 하나, 그리고 캐시할 수 있는 URL을 사용합니다.

API의 문서화된 동작을 바탕으로 작성된 구축 가이드이며, 특정 고객을 언급하지 않습니다. 게시.

문제: 고객은 특정 차량이 아니라 차급을 빌립니다

렌터카 고객은 컴팩트, 중형 SUV, 미니밴 같은 차급을 예약하고, 그 차급 중 영업소에 있는 아무 차량이나 받아 갑니다. 그래도 예약 페이지에는 차급마다 이미지가 필요하며, 관례적으로 대표 모델 하나에 "또는 동급 차량"이라는 문구를 붙입니다.

이런 사진들은 대개 구할 수 있는 곳에서 제각각 가져옵니다. 여기는 보도용 사진, 저기는 딜러 사진이고, 각도도 배경도 다르며 카드 안에서 차가 차지하는 크기도 제각각입니다. 이렇게 모은 그리드는 티가 나기 마련입니다. 차량 목록 페이지에 필요한 것은 그 반대입니다. 모든 등급을 같은 방식으로 표현해 카드마다 달라지는 것은 오직 차뿐이어야 합니다.

연동 구조 한눈에 보기

  • 차급별 대표 모델 하나, 카탈로그 차량 ID로 보관하며, "또는 유사 차종" 문구는 라벨에만 넣고 이미지에는 절대 넣지 않습니다.
  • 모든 카드에 동일한 요청 형태: 같은 뷰, 박스, 맞춤 방식, 크롭, 패딩, 색상, 배경, 포맷을 사용합니다.
  • 클래스당 이미지는 최대 두 장: 그리드의 카드 이미지와 클래스 페이지의 히어로 이미지입니다.
  • 캐시합니다. 그리드는 모든 방문자에게 동일하기 때문입니다. CDN에 파일을 두거나, 서명된 URL을 한 번 발급해 재사용하세요.

1단계: 차량 등급별 대표 모델을 id로 선택하기

각 등급의 대표 판매 모델을 정하고 현재 연식을 조회하세요. GET /api/v1/vehicles?make=&model=은 무료 공개 API로, 한 모델의 모든 연식을 저장해 둘 고정 차량 ID와 함께 반환합니다. POST /api/v1/images/resolve는 "2026 toyota rav4" 같은 문구로 같은 작업을 수행합니다.

특정 연식의 차량 ID
# one model's years, each with its vehicle id (free, public)
curl -s "https://carimage.dev/api/v1/vehicles?make=toyota&model=rav4" | jq -c '.data.vehicles[] | select(.year == 2026)'
# {"year":2026,"id":"veh_e5w75c93f6cvk"}
fleet.ts
// One representative model per class: its current model year, by catalog id.
// "or similar" lives in the label; the picture never promises the car on the lot.
export const CLASS_IMAGES = {
  compact:        { vehicle: "veh_fy7r2yvwt4p1v", label: "Toyota Corolla or similar" },    // 2026 Toyota Corolla
  "midsize-suv":  { vehicle: "veh_e5w75c93f6cvk", label: "Toyota RAV4 or similar" },       // 2026 Toyota RAV4
  "fullsize-suv": { vehicle: "veh_9mzh9ejqjye43", label: "Chevrolet Tahoe or similar" },   // 2026 Chevrolet Tahoe
  minivan:        { vehicle: "veh_9jck7rrybf35p", label: "Chrysler Pacifica or similar" }, // 2026 Chrysler Pacifica
};

ID는 절대 바뀌지 않으므로 보유 차량 변경이 영향을 미치는 곳은 이 맵 하나뿐입니다. 중형 클래스가 다른 모델이나 다음 연식으로 바뀌면 ID 하나만 교체하세요. 이 맵을 읽는 모든 카드, 히어로 이미지, 이메일이 그대로 따라 바뀝니다.

2단계: 모든 클래스에 동일한 요청 형식

9가지 카메라 뷰는 카탈로그의 모든 차량에서 동일한 구도로 촬영되므로 그리드가 가지런하게 정렬됩니다. 카드의 나머지는 한 번만 정해 두면 되는 몇 가지 파라미터입니다.

  • 카드에는 view=side: 모든 차량이 같은 기준선 위에서 같은 방향을 향합니다. 왼쪽 면을 보여주는 각 각도에는 -right 쌍(side-right)이 있어 카드가 레이아웃 안쪽을 향하게 할 수 있습니다. 차급 페이지에는 대표 각도인 front-3-4를 사용합니다.
  • w=640&h=320&fit=contain: 모든 차급에서 정확히 640×320이며 차량 전체가 보입니다. 응답의 X-Image-Width와 X-Image-Height로 캔버스 크기를 확인할 수 있습니다.
  • trim=1&padding=6: 맞추기 전에 차량 영역으로 잘라내고, 긴 변의 6%를 여백으로 둡니다. 그러면 Corolla와 Tahoe가 정사각형 원본 프레임 안에 떠 있지 않고 카드를 같은 방식으로 채웁니다.
  • background=f4f4f4는 카드를 그리드 자체의 회색 배경 위에 합성합니다. 투명 배경을 유지해 카드 색상이 비쳐 보이게 하려면 이 값을 생략하세요.
  • 저장할 파일에는 format=webp, 서명된 URL에는 format=auto를 사용합니다. auto는 브라우저마다 WebP 또는 PNG를 제공합니다.
한 등급의 카드와 히어로 이미지
# the class card: the same box, view, crop, paint and backdrop for every class
curl --fail-with-body -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
  "https://carimage.dev/api/v1/images/car?vehicle=veh_e5w75c93f6cvk&view=side&color=white&w=640&h=320&fit=contain&trim=1&padding=6&background=f4f4f4&format=webp" \
  -o midsize-suv-card.webp

# the class page's hero: the three-quarter view, the full width the API delivers
curl --fail-with-body -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
  "https://carimage.dev/api/v1/images/car?vehicle=veh_e5w75c93f6cvk&view=front-3-4&color=white&w=1024&format=webp" \
  -o midsize-suv-hero.webp

3단계: 그리드 전체에 이름으로 지정한 색상 하나 적용

15개의 프리셋은 이름이 붙은 도색입니다: white, black, gray, silver, blue, red, green, brown, beige, tan, orange, yellow, gold, burgundy, purple. 기본값은 silver이며, grey는 gray로 인식됩니다. 카드가 한 세트로 보이도록 모든 차량 등급에 같은 프리셋을 선택하세요. 위 예시는 white입니다. 각 프리셋은 같은 이름의 CSS 색상이 아니라 고유한 도색 견본을 사용하며(red는 #b3151b), hex를 포함한 모든 도색은 준비된 하나의 뷰를 다시 칠한 것이므로 도색 하나가 차량 이미지 하나입니다.

4단계: 파일 또는 URL 캐시하기

차급 그리드는 모든 방문자에게 동일하므로, 방문당 비용이 거의 들지 않아야 합니다. 방법은 두 가지입니다:

  • 파일을 저장하세요. 각 카드 이미지와 히어로 이미지를 GET /api/v1/images/car로 한 번 가져와 다른 에셋처럼 CDN에서 제공하세요. 유료 플랜에서는 플랜이 활성 상태인 동안 제품 제공을 위해 자체 서버에 사본을 보관할 수 있습니다(플랜 종료 후 30일 이내에 삭제하거나, Image Pack을 구매해 이미지 세트를 영구적으로 보관하세요). 각 파일의 ETag를 보관해 두세요. If-None-Match로 매일 밤 재확인하면 304로 응답하며 비용이 들지 않습니다. 위의 차량군 기준으로 이는 이달의 차량 이미지 8개이며, 필요한 만큼 재사용할 수 있습니다.
  • 또는 서명된 URL을 한 번 발급해 재사용하세요. POST /api/v1/image-urls는 호출당 최대 50개의 이미지를 받아 키가 없는 URL을 반환하며, 이 URL은 최대 7일 동안 유효합니다. 사용 횟수가 무제한인 URL은 유효 기간 내에 공개적으로 캐시할 수 있으므로, 모든 방문자가 같은 URL을 불러오면 반복 요청은 CDN에서 무료로 제공됩니다. renew: true를 추가하면 저장된 URL이 유효 기간이 지나도 계속 작동합니다. 갱신 시 갱신이 이루어진 달에 이미지가 한 번 집계되며, 그달에 이미 집계된 이미지라면 추가로 집계되지 않으므로 위의 보유 차량은 한 달에 최대 차량 이미지 8개로 유지됩니다.

대시보드에서 URL을 발급하는 키를 예약 도메인으로 제한하면, 다른 사이트로 복사된 URL은 403을 반환합니다.

TypeScript SDK로 그리드 URL을 한 번만 발급하기
import { CarImageClient, type ImageParams } from "@meterapp/car-image-sdk";
import { CLASS_IMAGES } from "./fleet";

const client = new CarImageClient({ apiKey: process.env.CAR_IMAGE_API_KEY });

// Framed once, for every class.
const card = (vehicle: string): ImageParams => ({
  vehicle, view: "side", color: "white", width: 640, height: 320,
  fit: "contain", trim: true, padding: 6, background: "#f4f4f4", format: "auto",
});
const hero = (vehicle: string): ImageParams => ({ vehicle, view: "front-3-4", color: "white", width: 1024, format: "auto" });

// Every visitor sees the same grid: mint the URLs once and serve the stored ones.
// renew keeps each URL working past its 7-day lifetime, one credit per image
// for each further week in which it is loaded.
const classes = Object.entries(CLASS_IMAGES);
const { data } = await client.createImageUrls(
  classes.flatMap(([, entry]) => [card(entry.vehicle), hero(entry.vehicle)]),
  { ttlSeconds: 604800, renew: true, idempotencyKey: "class-grid-2026-10" }
);
await saveClassImages(
  classes.map(([key], index) => ({ key, card: data[2 * index].url, hero: data[2 * index + 1].url, renewsUntil: data[2 * index].renews_until }))
);

5단계: 예약 확인

예약 확인 이메일에는 예약된 클래스가 표시되며, 이메일은 대여자가 원할 때 열어 봅니다. 해당 이미지를 갱신형 URL로 발급하세요. ttl_seconds는 최대치인 7일로, renew: true로, renew_days는 반납일 이후까지로 설정합니다. 아무도 이메일을 열지 않는 주에는 비용이 들지 않으며, 대여가 끝나면 URL 갱신이 중지됩니다. 예약마다 Idempotency-Key를 사용하면 재시도된 발송 시 두 번째 URL을 발급하는 대신 첫 번째 URL을 다시 반환하며, URL을 예약에 저장해 두면 이후 모든 재발송에서 재사용할 수 있습니다. 저희 라이프사이클 이메일도 이 방식으로 작동합니다. 메커니즘과 HTML은 이메일 사례에서 확인하세요.

예약 확인 한 건을 위한 자동 갱신 URL
// The booking confirmation: opened today, again at the counter, maybe never.
const { data: [classImage] } = await client.createImageUrls(card(booking.classVehicle), {
  ttlSeconds: 604800,
  renew: true,
  // A week past the return date, and no renewals after it (365 days at most).
  renewDays: Math.min(daysUntil(booking.returnDate) + 7, 365),
  // A retried send replays the first URL instead of minting a second one.
  idempotencyKey: `booking:${booking.id}:class`,
});
booking.classImageUrl = classImage.url; // later resends reuse it

CLI, SDK 및 MCP

  • CLI: npx @meterapp/car-image get --vehicle veh_… --view side --width 640 --height 320 --fit contain --trim --padding 6 --out card.webp는 카드를 파일로 저장하고, car-image url --batch classes.json --renew는 URL을 일괄 발급합니다.
  • SDK: id는 client.vehicles({ make, model }), 파일은 client.getImage(…), URL은 client.createImageUrls(…)를 사용합니다.
  • MCP: resolve_vehicle와 create_car_image_urls를 사용하면 어시스턴트가 "중형 SUV, RAV4 또는 동급"이라는 설명으로 등급 카드 초안을 작성할 수 있습니다. 설정 방법은 MCP 페이지에 있습니다.

자주 묻는 질문

카드에 고객이 실제로 받을 차량을 정확히 보여 줄 수 있나요?
아니요, 그렇게 하려고 해서도 안 됩니다. 차량 등급은 '또는 동급'으로 대여되며, 렌더는 귀사 주차장에 있는 차량이 아니라 카탈로그의 제조사, 모델, 연식을 보여 줍니다. 대표 모델 하나를 보여 주고 라벨에 '또는 동급'을 표기하세요. 카운터에서 특정 차량이 배정되면 해당 VIN을 무료로 디코딩해 카탈로그 차량을 찾을 수 있으니, 원하시면 그 모델을 대신 보여 주셔도 됩니다.
그리드의 차량 크기가 실제 비율과 다른 이유는 무엇인가요?
trim이 각 렌더링을 차량에 맞게 잘라내고 fit=contain이 카드를 차량으로 채우기 때문에, 소형차와 대형 SUV가 카드를 똑같이 채웁니다. 덕분에 그리드가 깔끔하게 유지됩니다. 크기는 클래스 이름, 좌석 수, 수하물 개수 등 텍스트로 표시하세요.
클래스 그리드 비용은 얼마인가요?
클래스마다 카드 이미지와 히어로 이미지가 하나씩 있는 4개 클래스의 차량군은 매월 차량 이미지 8개이며, 각 이미지는 어떤 크기로든 필요한 만큼 제공됩니다. 유료 요금제가 활성 상태인 동안 파일을 CDN에 저장하면 가져온 달에만 계산되며, ETag를 통한 재확인은 무료입니다. 대신 갱신되는 서명된 URL로 제공하면 같은 이미지가 페이지가 열린 달마다 한 번씩 계산됩니다.
그리드에는 어떤 도장 색상을 사용해야 하나요?
모든 등급에 같은 프리셋 하나를 사용하면 카드가 하나의 세트처럼 보입니다. 프리셋 15개는 white, black, gray, silver, blue, red, green, brown, beige, tan, orange, yellow, gold, burgundy, purple이며, 기본값은 silver입니다. 어떤 hex 값도 같은 가격으로 사용할 수 있습니다. 임차인은 주차장에 있는 색상의 차를 받게 되며, 카드는 색상을 약속한 적이 없습니다.
차량 등급의 모델이 카탈로그에 없으면 어떻게 하나요?
카탈로그에 없는 차량은 404와 함께 가장 가까운 카탈로그 차량을 각각의 id와 함께 제안합니다. 그중 하나를 사용하거나 공개 요청 게시판에서 해당 차량을 요청하세요. 카탈로그는 오픈 소스입니다.

계속 읽기

고객 사례 · 개발자 도구깨지지 않는 서명된 URL로 이메일에 차량 이미지를 삽입하는 방법저희 라이프사이클 이메일은 각 고객의 첫 렌더를 1년간 자동으로 갱신되는 실시간 서명된 URL로 그대로 삽입합니다. 그 작동 방식과 따라 하는 방법을 소개합니다.