관세율 조회한국어 · 日本語 · English

가이드

[API 튜토리얼] 상품명만 넣으면 관세율까지 — HS코드 자동분류 API 사용법

작성 2026-08-18 · 갱신 2026-08-18

상품명 질의가 재작성-임베딩-검색 단계를 거쳐 RRF로 후보 목록과 관세율을 반환하는 흐름을 보여주는 다이어그램

“나이키 운동화”처럼 사람이 쓰는 말을 그대로 넣으면 HS코드 후보와 국가별 관세율을 함께 돌려주는 API가 있다. GET /api/v1/classify 하나로 끝난다. 이 글은 그 엔드포인트의 실제 스펙(docs/openapi-classify.yaml)과 구현(src/pages/api/v1/classify.ts)을 그대로 옮긴 사용법이다.

요청

GET https://duty.pix-make.com/api/v1/classify?q=무선+이어폰&limit=3
파라미터 필수 설명
q 자연어 상품명, 최대 200자. 숫자 4~10자리(HS코드)를 그대로 넣어도 된다
lang 아니오 응답 언어. ko(기본)·ja·en
countries 아니오 콤마로 구분한 국가 코드. 기본값은 kr(원산지 협정 없이 적용되는 기본세율·WTO양허세율). 그 외 us, eu, cn, gb, vn, jp, asean, au, ca, in, sg, tr, nz, cl은 대한민국이 체결한 FTA·RCEP 상대국이다. 지원하지 않는 코드를 넣으면 조용히 무시되고 응답의 meta.unsupported_countries에 표시된다
limit 아니오 반환할 후보 개수. 1~5, 기본값 5. 범위를 벗어나면 기본값으로 대체된다

인증은 헤더로 한다. X-RapidAPI-Proxy-Secret 또는 X-Internal-Key 둘 중 하나가 필요하다.

curl -s "https://duty.pix-make.com/api/v1/classify?q=%EB%AC%B4%EC%84%A0%20%EC%9D%B4%EC%96%B4%ED%8F%B0" \
  -H "X-Internal-Key: <구독 후 발급되는 키>"

응답

{
  "query": "무선 이어폰",
  "normalized_query": "이어폰",
  "candidates": [
    {
      "rank": 1,
      "hs_code": "8518300000",
      "title": { "ko": "그 밖의 것[헤드폰ㆍ이어폰]", "ja": null, "en": null },
      "score": 0.87,
      "tariffs": [
        {
          "country": "kr",
          "rates": [
            { "kind": "basic", "rate": "8%", "label_ko": "기본세율" }
          ]
        }
      ]
    }
  ],
  "meta": {
    "limit": 5,
    "unsupported_countries": [],
    "disclaimer": "score는 검색 순위 점수(RRF 정규화)이며 분류 정확도 확률이 아님. 실측: top1 64% / top5 재현율 93%. 법적 효력 없음, 관세사 확인 필요."
  }
}

normalized_query는 브랜드명·모델명을 제거하고 일반 명사로 바꾼 질의다. 숫자 코드로 직접 질의하면 이 값은 원문과 같다. title.en은 계층 제목의 영문판이 원본 데이터에 없어 항상 null로 온다 — 빈 문자열 대신 정직하게 null을 준다.

score는 정확도가 아니다

각 후보의 score는 검색 순위를 RRF(Reciprocal Rank Fusion) 방식으로 0~1 사이 값으로 정규화한 것이다(감쇠 상수 k=60). 분류가 맞을 확률이 아니라 검색 결과 안에서의 상대적 순위를 나타낼 뿐이다. 그래서 모든 응답에 meta.disclaimer로 실제 정확도 실측치를 함께 준다: 정답 세트 28건 기준 top1 정확도 64%, top5 재현율 93%. 1위 후보가 정답이 아닐 수 있다는 뜻이므로, 중요한 판단에는 limit을 늘려 상위 몇 개를 함께 확인하는 편이 안전하다.

검색 방식과 호출 비용

질의는 벡터 임베딩(bge-m3)으로 변환돼 Vectorize에서 의미 유사 품목을 찾고, 이 결과가 LIKE 검색 결과·질의 재작성(브랜드명 제거) 결과와 RRF로 합쳐져 최종 후보가 정해진다.

이 과정에서 Workers AI 호출은 질의 유형에 따라 달라진다.

질의 유형 AI 호출 횟수
숫자 4~10자리(HS코드 직접 입력) 0회
일반 자연어 상품명 최대 3회(질의 재작성 1회 + bge-m3 임베딩 최대 2회)

재작성된 질의가 원문과 같거나 재작성이 실패하면 임베딩 호출은 1회로 줄어든다. 결과 캐시(1일)·AI 캐시(7일)가 적중하면 실제 호출 수는 더 줄어든다. 즉 같은 질의를 반복해서 보내는 워크플로라면 캐시가 비용을 상당 부분 흡수한다.

국가 코드와 관세율 종류

countries=kr,jp처럼 여러 국가를 한 번에 요청하면 후보마다 국가별 tariffs 배열이 함께 온다. kr은 기본세율·WTO양허세율(basic/wto)을 뜻하고, 그 외 국가 코드는 해당 국가와 체결된 협정세율에 대응한다. 협정세율은 원산지증명서 요건이 붙는다는 점을 감안해서 봐야 한다 — 기본세율과 같은 자리에 나온다고 해서 조건 없이 적용되는 세율은 아니다.

숫자 코드 질의는 AI 호출 0회, 일반 상품명 질의는 재작성 1회와 임베딩 최대 2회로 갈리는 결정 트리와 400·401·405·500·503 에러 코드별 원인을 정리한 표

에러 처리

상태 코드 error.code 상황
400 missing_query / query_too_long q 누락 또는 200자 초과
401 unauthorized 인증 헤더 누락 또는 값 불일치
405 method_not_allowed GET 이외의 메서드로 호출
500 internal_error 서버 내부 오류(원인은 서버 로그에만 남고 응답에는 노출하지 않는다)
503 not_configured 인증 시크릿이 아직 서버에 배포되지 않은 상태

401과 503을 구분해서 응답하는 이유가 있다. 401은 “키가 틀렸다”이고 503은 “서버가 아직 인증을 받을 준비가 안 됐다”이다. 이 둘을 같은 코드로 묶으면 호출하는 쪽에서 재시도해야 할지 키를 다시 발급받아야 할지 구분할 수 없다.

정리

이 API는 duty-site 화면(search.astro)이 쓰는 것과 완전히 동일한 검색 로직(searchItems())을 그대로 호출한다. 화면과 API가 다른 결과를 낼 일이 없고, 화면에서 검증된 정확도(top1 64%, top5 재현율 93%)가 API 응답에도 그대로 적용된다. score는 순위 지표일 뿐 확신도가 아니라는 점, 그리고 실제 세액 계산에는 관세사·세관 확인이 필요하다는 점만 기억하면 된다.

출처