퀵스타트 — 예제 리포트 만들기

미리 준비된 샘플 이미지로 항상 성공하는 예제 리포트를 만들고, 공유 리포트까지 바로 확인합니다.

이 페이지의 호출은 전부 복사해서 그대로 실행할 수 있습니다. 발급받은 테스트 키만 넣으면, 미리 준비된 분석 가능한 샘플 이미지로 예제 리포트를 만들고 — 상태 확인 → 공유 리포트 열람까지 — 한 번에 따라가 볼 수 있습니다.

처음이라면 인증·호스트·모드 개념을 시작하기에서 먼저 보고 오면 좋습니다.

준비물

  • 발급받은 테스트 키 (atr_test_…). 아직 없다면 콘솔에서 프로젝트(test 환경)를 만들고 API 키를 발급하세요 — 전체 키 값은 발급 시 한 번만 표시됩니다. 자세한 절차는 시작하기를 참고하세요.
  • curl, 그리고 JSON 파싱을 위한 jq.
export ATRACE_API_KEY=atr_test_xxxxxxxxxxxxxxxxxxxx

이 예제가 항상 성공하는 이유

아래 이미지 URL은 ATRACE가 호스팅하는 분석 가능한 실차 샘플입니다. 촬영 품질·각도 문제로 분석이 실패할 일이 없으므로, 키만 올바르면 리포트가 끝까지(분석 → 자동 공개) 완료됩니다. 실제 연동에서 쓰는 계약(요청·응답 형태)과 100% 동일하니, 여기서 동작을 확인한 뒤 이미지 URL만 자사 것으로 바꾸면 됩니다.

준비된 샘플 이미지

타이어 4개 위치 × {tread, sidewall} 슬롯에 매핑된 공개 샘플입니다. 트레드 4장은 마모(그루브 깊이)가 서로 다른 실차 샘플이라, 리포트에 위치별로 다른 트레드 깊이가 나타납니다.

슬롯샘플 URL비고
front_left · treadhttps://docs.atrace.ai/samples/tire/tread-a-8mm.jpg트레드 약 8mm
front_right · treadhttps://docs.atrace.ai/samples/tire/tread-a-6mm.jpg트레드 약 6mm
rear_left · treadhttps://docs.atrace.ai/samples/tire/tread-b-4mm.jpg트레드 약 4mm
rear_right · treadhttps://docs.atrace.ai/samples/tire/tread-c-2mm.jpg트레드 약 2mm
front_left · sidewallhttps://docs.atrace.ai/samples/tire/sidewall-205-55R16.jpg단면폭 205 · 편평비 55 · 림 16인치
rear_right · sidewallhttps://docs.atrace.ai/samples/tire/sidewall-205-65R15.jpg단면폭 205 · 편평비 65 · 림 15인치
front_right · sidewallhttps://docs.atrace.ai/samples/tire/sidewall-165-60R15.jpgtire_4t_4s에서만 사용
rear_left · sidewallhttps://docs.atrace.ai/samples/tire/sidewall-185-65R14.jpgtire_4t_4s에서만 사용

사이드월 위치는 고정이 아닙니다

위 예시는 사이드월을 앞좌 + 뒤우 조합으로 보냅니다. 현장에서는 공간 제약으로 어느 바퀴를 찍게 될지 달라질 수 있고, 좌·우를 구분할 수 없으면 한쪽을 임의로 골라 보내도 됩니다. 자세한 배경은 이미지 수집을 보세요.

번호판 이미지(plate 모듈)는 아직 지원되지 않습니다. 다만 아래 예제는 plate_number(차량 번호)에 무작위 예시 번호를 만들어 함께 보내, 생성된 샘플 리포트에 차량 번호가 표시되도록 합니다 — plate_number선택 필드이므로 생략해도 됩니다.

방법 1 — 고객 URL 모드 (가장 빠름, 한 번의 호출)

이미지 URL을 요청에 동봉하면 호출 한 번으로 분석이 시작됩니다. template촬영 구성을 정하는 템플릿입니다 — 6장짜리 tire_4t_2s와 8장짜리 tire_4t_4s 중 고릅니다.

트레드 4장 + 사이드월 2장 = 6장.

# 무작위 예시 번호판 (선택 필드 plate_number). 직접 지정하거나 생략해도 됩니다.
PLATE="$((RANDOM%90+10))가$((RANDOM%9000+1000))"
RUN_ID="quickstart-4t2s-$(date +%s)-$RANDOM"

curl -X POST https://app.atrace.ai/api/v1/reports \
  -H "Authorization: Bearer $ATRACE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $RUN_ID" \
  -d '{
    "plate_number": "'"$PLATE"'",
    "external_inspection_id": "'"$RUN_ID"'",
    "template": "tire_4t_2s",
    "images": [
      { "module_type": "tire", "slot": { "position": "front_left",  "image_type": "tread" },
        "source": { "url": "https://docs.atrace.ai/samples/tire/tread-a-8mm.jpg" } },
      { "module_type": "tire", "slot": { "position": "front_right", "image_type": "tread" },
        "source": { "url": "https://docs.atrace.ai/samples/tire/tread-a-6mm.jpg" } },
      { "module_type": "tire", "slot": { "position": "rear_left",   "image_type": "tread" },
        "source": { "url": "https://docs.atrace.ai/samples/tire/tread-b-4mm.jpg" } },
      { "module_type": "tire", "slot": { "position": "rear_right",  "image_type": "tread" },
        "source": { "url": "https://docs.atrace.ai/samples/tire/tread-c-2mm.jpg" } },
      { "module_type": "tire", "slot": { "position": "front_left",  "image_type": "sidewall" },
        "source": { "url": "https://docs.atrace.ai/samples/tire/sidewall-205-55R16.jpg" } },
      { "module_type": "tire", "slot": { "position": "rear_right",  "image_type": "sidewall" },
        "source": { "url": "https://docs.atrace.ai/samples/tire/sidewall-205-65R15.jpg" } }
    ]
  }'

트레드 4장 + 사이드월 4장 = 8장. 위 6장에 사이드월 2장(앞우 + 뒤좌)을 더합니다.

# 무작위 예시 번호판 (선택 필드 plate_number). 직접 지정하거나 생략해도 됩니다.
PLATE="$((RANDOM%90+10))가$((RANDOM%9000+1000))"
RUN_ID="quickstart-4t4s-$(date +%s)-$RANDOM"

curl -X POST https://app.atrace.ai/api/v1/reports \
  -H "Authorization: Bearer $ATRACE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $RUN_ID" \
  -d '{
    "plate_number": "'"$PLATE"'",
    "external_inspection_id": "'"$RUN_ID"'",
    "template": "tire_4t_4s",
    "images": [
      { "module_type": "tire", "slot": { "position": "front_left",  "image_type": "tread" },
        "source": { "url": "https://docs.atrace.ai/samples/tire/tread-a-8mm.jpg" } },
      { "module_type": "tire", "slot": { "position": "front_right", "image_type": "tread" },
        "source": { "url": "https://docs.atrace.ai/samples/tire/tread-a-6mm.jpg" } },
      { "module_type": "tire", "slot": { "position": "rear_left",   "image_type": "tread" },
        "source": { "url": "https://docs.atrace.ai/samples/tire/tread-b-4mm.jpg" } },
      { "module_type": "tire", "slot": { "position": "rear_right",  "image_type": "tread" },
        "source": { "url": "https://docs.atrace.ai/samples/tire/tread-c-2mm.jpg" } },
      { "module_type": "tire", "slot": { "position": "front_left",  "image_type": "sidewall" },
        "source": { "url": "https://docs.atrace.ai/samples/tire/sidewall-205-55R16.jpg" } },
      { "module_type": "tire", "slot": { "position": "front_right", "image_type": "sidewall" },
        "source": { "url": "https://docs.atrace.ai/samples/tire/sidewall-165-60R15.jpg" } },
      { "module_type": "tire", "slot": { "position": "rear_left",   "image_type": "sidewall" },
        "source": { "url": "https://docs.atrace.ai/samples/tire/sidewall-185-65R14.jpg" } },
      { "module_type": "tire", "slot": { "position": "rear_right",  "image_type": "sidewall" },
        "source": { "url": "https://docs.atrace.ai/samples/tire/sidewall-205-65R15.jpg" } }
    ]
  }'

응답(202)에는 report_id이미 사용 가능한 share_url이 들어 있습니다.

{
  "report_id": "123e4567-e89b-42d3-a456-426614174000",
  "status": "processing",
  "share_url": "https://app.atrace.ai/r/sh_abcdef"
}

완료 확인 (폴링)

share_url은 생성 즉시 받지만, 분석·공개가 끝나야 열람 가능해집니다. GET /reports/{id}analysis_statuspublication_status를 폴링합니다.

REPORT_ID=123e4567-e89b-42d3-a456-426614174000   # 위 응답의 report_id로 교체

for i in $(seq 1 60); do     # 최대 약 5분 (5초 × 60)
  REP="$(curl -s "https://app.atrace.ai/api/v1/reports/$REPORT_ID" \
    -H "Authorization: Bearer $ATRACE_API_KEY")"
  ANALYSIS="$(echo "$REP" | jq -r '.analysis_status')"
  PUBLICATION="$(echo "$REP" | jq -r '.publication_status')"
  SUMMARY="$(echo "$REP" | jq -r '.summary_status // "-"')"
  echo "[$i] analysis=$ANALYSIS publication=$PUBLICATION summary=$SUMMARY"
  [ "$ANALYSIS" = "complete" ] && [ "$PUBLICATION" = "published" ] && break
  sleep 5
done

if [ "$ANALYSIS" = "complete" ] && [ "$PUBLICATION" = "published" ]; then
  echo "완료! 공유 리포트: $(echo "$REP" | jq -r '.links.share')"
  curl -s "$(echo "$REP" | jq -r '.links.content')" \
    -H "Authorization: Bearer $ATRACE_API_KEY" | jq '{status, content_revision, overall, sections}'
else
  echo "아직 완료되지 않음 (analysis=$ANALYSIS, publication=$PUBLICATION). 슬롯을 확인하세요."
fi
  • 자체 렌더링 분석 완료 조건은 analysis_status == "complete", ATRACE 공유 화면 공개 조건은 publication_status == "published"입니다. 활성 열람 링크는 links.share 값을 그대로 쓰세요.
  • 이 퀵스타트의 큐레이션 샘플은 템플릿의 성공 개수 조건을 충족하므로 두 조건에 곧 도달합니다.
  • 자사 이미지에서 template.requirements[].minimum_success_count를 충족하지 못하면 공개 게이트를 통과할 수 없습니다. POST /reports/{id}/publish도 같은 조건을 우회하지 않습니다. 부족한 슬롯을 재분석하거나 새 원본으로 교체한 뒤 다시 폴링하세요.
  • 429·5xx에는 지수 백오프로 재시도하세요. 자세한 상태 전이는 리포트 생성 흐름을 보세요.

방법 2 — Pre-Signed 모드 (자체 스토리지 없이, bash 스크립트)

자사 이미지 호스팅이 없다면 ATRACE가 발급한 URL에 직접 PUT으로 업로드합니다. 서명 URL에 PUT 하는 흐름이 처음이면 헷갈리기 쉬우므로, 아래 스크립트가 전 과정을 대신 처리합니다 — 샘플을 내려받아 업로드하고, 슬롯을 등록한 뒤, 완료까지 폴링합니다.

# 스크립트 내려받기
curl -O https://docs.atrace.ai/scripts/atrace-quickstart.sh
chmod +x atrace-quickstart.sh

# 실행 (키만 있으면 됩니다)
export ATRACE_API_KEY=atr_test_xxxxxxxxxxxxxxxxxxxx
./atrace-quickstart.sh                       # tire_4t_2s (6장)
TEMPLATE=tire_4t_4s ./atrace-quickstart.sh   # tire_4t_4s (8장)

스크립트가 하는 일은 다음과 같습니다.

리포트 생성images 없이 POST /reports를 호출하면, 타이어 8개 슬롯 전체의 upload_targets를 받습니다. 각 타깃에는 스토리지 PUT URL과 필수 UUID asset_id가 들어 있습니다. 스크립트는 무작위 예시 번호판(plate_number)도 함께 보내 완성된 샘플 리포트에 차량 번호가 표시되도록 합니다(선택 필드).

# 무작위 예시 번호판 (선택 필드 plate_number).
PLATE="$((RANDOM%90+10))가$((RANDOM%9000+1000))"
RUN_ID="quickstart-presigned-$(date +%s)-$RANDOM"

curl -X POST https://app.atrace.ai/api/v1/reports \
  -H "Authorization: Bearer $ATRACE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $RUN_ID" \
  -d '{ "plate_number": "'"$PLATE"'", "external_inspection_id": "'"$RUN_ID"'", "template": "tire_4t_2s" }'

샘플 다운로드 + PUT 업로드 — 각 슬롯의 upload_url에 이미지 바이트를 그대로 PUT 합니다. 업로드는 스토리지로 바로 가고, ATRACE Report API를 거치지 않습니다.

curl -X PUT "<upload_url>" \
  -H "Content-Type: image/jpeg" \
  -H "Cache-Control: max-age=60" \
  --data-binary @tread-a-8mm.jpg
# → HTTP 200

슬롯 등록 (= 분석 자동 시작) — 실제로 업로드한 타깃만 등록합니다. 각 항목에는 생성 응답에서 받은 asset_id와 그 타깃의 중첩 슬롯(slot: { position, image_type })을 함께 보냅니다.

curl -X POST https://app.atrace.ai/api/v1/reports/$REPORT_ID/images \
  -H "Authorization: Bearer $ATRACE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "images": [
    { "asset_id": "1d2f4836-12f8-4bde-9e51-1aac3d848a50",
      "module_type": "tire", "slot": { "position": "front_left", "image_type": "tread" } }
  ] }'

asset_id 없이 슬롯만 보내는 이전 요청 형태는 v1.1부터 지원하지 않습니다.

완료 폴링 + 결과 조회 — 방법 1과 동일하게 analysis_status=completepublication_status=published를 확인합니다. 객관 결과는 report 응답, 문구와 자체 렌더링 데이터는 links.content, 공유 화면은 links.share에서 읽습니다.

Pre-Signed PUT 규약 (이대로 보내면 됩니다)

  • 메서드: HTTP PUT. - 본문: 원본 이미지 바이트 그대로(--data-binary). multipart·base64 아님. - Content-Type: image/jpeg 또는 image/png. - 성공 응답: 200. - 만료: 발급 후 2시간(7200초). 만료되면 POST /reports/{id}/upload-targets로 새 타깃을 발급받습니다.

재촬영할 때도 새 타깃을 발급받아 PUT한 뒤, 새 asset_idPOST /reports/{id}/images?replace=true로 등록합니다. 현재 슬롯에 적용된 같은 asset_id의 등록 재시도는 멱등입니다. 교체·재분석 중에는 기존 공유 링크가 일시 비공개되고, 성공 후 자동으로 다시 공개됩니다.

결과 확인

공유 리포트(links.share)를 브라우저에서 열면, 위치별(T1~T4) 타이어 카드가 보입니다. 트레드는 측정된 그루브 깊이(mm), 사이드월은 인식된 규격이 표시됩니다. 이 예제는 마모 정도가 다른 트레드를 일부러 골랐으므로 위치마다 다른 깊이가 나타납니다.

위치라벨트레드 그루브 깊이
앞좌T1약 8mm
앞우T2약 6mm
뒤좌T3약 4mm
뒤우T4약 2mm

이제 이미지 URL만 자사 것으로 바꾸면 실제 연동 코드가 됩니다.

다음 단계

On this page