Amazon 리뷰 API: 상품 링크에서 원문 근거를 갖춘 문제 목록까지
Amazon 리뷰를 읽는 단계별 연동 방법을 다룹니다. 국가별 마켓플레이스와 상품 식별자를 검증하고, 리뷰·변형 상품·관측 로그를 분리하고, 중복 제거와 누락 데이터를 처리하며, 검증 가능한 원문 발췌를 근거로 문제 분류를 구성합니다.
Amazon 리뷰에서 제품 개선 단서를 찾을 때 첫 단계는 모델로 모든 내용을 긍정과 부정 피드백으로 나누는 것이 아닙니다. 먼저 리뷰가 어느 국가 마켓플레이스에서 왔는지, 어떤 상품과 연결되는지, 여러 요청에 반복해서 나타나는지, 각 문제 결론이 정확히 어떤 문장을 인용하는지 알아야 합니다. 그렇지 않으면 같은 인기 리뷰를 열 번 읽은 것을 보고서가 구매자 열 명이 같은 문제를 제기한 것으로 해석할 수 있습니다.
이 가이드는 리뷰를 내부 조사 워크플로에 연동해야 하는 개발자와 제품 책임자를 위한 것입니다. 사용 권한이 확인된 상품 링크에서 시작해 상품, 리뷰, 관측 로그, 분류 근거 사이의 관계를 정립합니다. 최종 결과물은 검증 가능한 문제 목록이며, 매출 예측이나 리뷰 진위 검증, 전체 구매자 만족도 평가는 범위에 포함되지 않습니다.
상품 카탈로그와 리뷰 조사 구분하기
Amazon 공식 Creators API는 상품 검색, 상품 상세, 변형 상품, 카테고리 노드 작업 등 상품 카탈로그 접근을 제공하며, Amazon Associates 쇼핑 경험에 맞춰져 있습니다. 이는 EveryInfra의 amazon.reviews와 같은 제품이 아니며, 공식 상품 카탈로그 문서를 서드파티 리뷰 조회의 권한 증빙으로 쓸 수 없습니다.
연동하기 전에 대상 마켓플레이스, 데이터 사용 권한, 처리 목적, 보존 기간, 원문을 표시하거나 모델로 처리할 수 있는지 확인하십시오. Amazon.com 이용 약관의 LICENSE AND ACCESS 조항은 일반 라이선스와 데이터 수집 방식에 제한을 두고 있으며, 다른 마켓플레이스와 개별 프로그램은 따로 확인해야 합니다. 상품 브랜드를 소유했다고 모든 리뷰 콘텐츠를 임의로 재사용할 권리가 자동으로 생기지는 않습니다.
기존 권한으로 특정 내보내기 데이터셋만 사용할 수 있다면, 네트워크 조회 없이 아래의 식별자, 중복 제거, 분류 단계부터 바로 시작할 수 있습니다. 권한 범위를 워크플로 안에 기록해 두고, 범위를 벗어난 필드나 용도는 이후 파이프라인에서 제외하십시오.
다른 액션의 파라미터를 가져다 쓰지 말고 현재 리뷰 파라미터 확인하기
curl -fsS --max-time 30 \
'https://api.everyinfra.com/api/v1/social/catalog?platform=amazon' \
| jq -e '.capabilities[] | select(.action == "reviews") | {
platform, action, required_params, optional_params, param_meanings,
mode, returns_list, default_limit, max_limit, response_fields
}'2026-09-04 확인 기준으로 reviews는 url이 필수이고, 선택 파라미터로 domain이 있으며, 실행 모드는 sync이고, 결과는 목록으로 반환됩니다. 현재 카탈로그는 default_limit와 max_limit의 구체적인 값을 선언하지 않습니다. 빈 값은 “선언되지 않음”으로만 기록할 수 있으며, 항목 수 제한이 없다는 뜻으로 해석할 수 없고, 과거 리뷰 전체를 가져올 수 있다는 보장은 더더욱 아닙니다.
또한 다른 플랫폼이 sort, since, cursor를 지원한다고 해서 Amazon 요청에 이 필드를 추가하지 마십시오. 선택 파라미터는 현재 액션에 해당해야 하며, 인터페이스가 파라미터를 받아들이는지와 실제로 필터링이 적용되는지는 따로 검증해야 합니다. 현재 카탈로그로는 최신순 연속 페이지네이션 튜토리얼을 뒷받침할 수 없으므로, 아래에서는 소량 샘플 요청을 보여 줍니다.
상품 식별자보다 국가 마켓플레이스 먼저 확인하기
url에는 전체 상품 링크를, domain에는 amazon.com이나 amazon.co.jp 같은 마켓플레이스 도메인을 https://나 상품 경로 없이 사용합니다. 로컬 입력 파싱은 /dp/, /gp/product/, /product-reviews/ 같은 경로에서 대문자 영문자 또는 숫자 10자로 된 ASIN을 추출합니다. 스토어 홈페이지와 키워드 검색 페이지는 확인된 상품 입력으로 쓸 수 없습니다.
미국 외 마켓플레이스는 특히 주의해야 합니다. 현재 구현에서 리뷰 마켓플레이스의 기본값은 amazon.com이며, 임의의 입력 링크에서 국가 마켓플레이스를 자동으로 추론한다는 보장은 없습니다. 일본 마켓플레이스 상품을 준비할 때는 링크와 일치하도록 amazon.co.jp를 명시적으로 전달하십시오. 일본어 본문, 리뷰의 국가 필드, 페이지에 표시된 통화를 요청 도메인 대신 사용하지 마십시오.
- 상품 목록에는 원본 URL, 검증된 마켓플레이스, 요청 ASIN, 사내 상품 번호, 포함 근거를 저장합니다. 제목은 읽기용일 뿐 상품 기본 키로 쓰지 않습니다.
- 상품 연결 정보에는 응답의 product_asin과 variant를 따로 저장합니다. 검증 없이 요청 ASIN을 덮어써서는 안 되며, 값이 없을 때 하위 변형 상품을 추측해서도 안 됩니다.
- 같은 마켓플레이스와 ASIN을 가리키는 서로 다른 추적 링크는 요청을 보내기 전에 하나의 대상으로 병합할 수 있으며, 이때 원래 링크와의 매핑은 보존합니다. 마켓플레이스, 대상 또는 파라미터가 서로 다른 요청은 제목이 비슷하다는 이유만으로 병합해서는 안 됩니다.
요청한 마켓플레이스는 이번 관측의 출처 범위이며, 리뷰 작성자의 국적을 뜻하지 않습니다. country는 형식이 제각각인 지역 텍스트일 수 있고, variant도 불완전할 수 있습니다. 지역이나 사양별 그룹화는 명확한 정규화와 검증을 거친 뒤에만 적절합니다. 확인되지 않은 레코드는 "미지정"으로 분류하며, 미국 마켓플레이스나 기본 사양에 임의로 포함해서는 안 됩니다.
단일 대상으로 최소 요청 완성하기
아래는 요청 템플릿이며, 이번에는 실제 고객 요청을 실행하지 않습니다. 승인된 전체 상품 링크와 링크에 맞는 마켓플레이스를 환경 변수에 넣고, API 키는 반드시 자체 런타임 환경에만 보관해야 합니다. limit은 일반적인 목록 항목 수 요청값으로 params에 넣습니다. limit을 3으로 설정하는 것은 작은 구조를 확인하기 위한 것이며, 정확히 3개 항목이 반환되거나, 서버 측 처리가 3개 항목으로 제한되거나, 3개 항목을 기준으로 과금된다는 보장은 없습니다.
: "${EVERYINFRA_API_KEY:?set the API Key first}"
: "${EVERYINFRA_AMAZON_PRODUCT_URL:?set the authorized full product URL first}"
: "${EVERYINFRA_AMAZON_DOMAIN:?set the site domain matching the URL first}"
jq -cn --arg url "${EVERYINFRA_AMAZON_PRODUCT_URL}" \
--arg domain "${EVERYINFRA_AMAZON_DOMAIN}" '{
platform: "amazon",
action: "reviews",
params: {url: $url, domain: $domain, limit: 3}
}' | curl --silent --show-error --include --max-time 180 \
'https://api.everyinfra.com/api/v1/social' \
-H "Authorization: Bearer ${EVERYINFRA_API_KEY}" \
-H 'Content-Type: application/json' --data-binary @-먼저 HTTP 상태와 응답 유형을 확인한 다음, 실제 래퍼 구조에 따라 결과, 요청 식별자, 제공되는 과금 정보를 읽습니다. 타임아웃은 클라이언트가 완전한 결과를 받지 못했다는 뜻이며, 서버가 실행에 실패했다는 뜻은 아닙니다. 검증하기 전에 요청 컨텍스트를 보존해 곧바로 재전송하는 일을 피합니다. 빈 결과는 이번 요청이 사용 가능한 리뷰를 전달하지 못했다는 의미일 뿐이며, 이를 근거로 상품을 "리뷰가 한 번도 없었던" 상품으로 표시해서는 절대 안 됩니다.
리뷰 자체와 관측 로그를 분리하기
curl -fsS --max-time 30 \
'https://api.everyinfra.com/api/v1/social/fields?platform=amazon&action=reviews' \
| jq '{fields, undocumented}'현재 데이터 사전에는 review_id, title, text, rating, rating_scale, posted_at, helpful_count, is_verified_purchase, is_vine, variant, country, url, author_name, product_asin, platform이 포함되어 있습니다. 데이터 사전은 반환될 수 있는 필드를 설명할 뿐이며, 모든 레코드에 값이 빠짐없이 채워진다고 보장하지는 않습니다.
- 리뷰 레코드: 출처 범위, 안정적인 review_id, 제공되는 title/text/rating/평점 척도, 출처 링크를 저장합니다. ID는 문자열로 보관하고, 누락된 값은 명시적인 false 및 0과 구분합니다.
- 관측 로그: 작업 번호, 요청한 상품, 파라미터 스냅샷, observed_at, 실제로 반환된 리뷰와의 연결을 저장합니다. 요청에서 기존 리뷰를 다시 읽은 것은 새로운 관측이며, 새로운 리뷰가 아닙니다.
- 분석 레코드: 채택한 리뷰 버전, 분류 규칙 버전, 주제와 근거 발췌, 검토 상태를 저장합니다. 분류 규칙을 바꿔도 원본 리뷰를 다시 쓸 필요는 없습니다.
rating과 rating_scale은 함께 처리합니다. 상품 단위 종합 평점, 전체 평점 수, 이번에 가져온 리뷰 수는 서로 다른 지표입니다. 텍스트 없는 평점 레코드는 별도의 평점 표본으로 집계할 수 있지만, 의견을 지어내 텍스트 주제 분석에 섞어서는 안 됩니다. author_name은 표시 이름일 뿐 고유 신원으로 쓰기에 적합하지 않으며, 상품 문제 분석을 위해 여러 사이트의 작성자 프로필을 서로 연결할 필요도 전혀 없습니다.
is_verified_purchase는 구매 인증 상태이며, 의견의 정확성이나 전체 내용의 진위를 보장하지 않습니다. 값이 false인 경우와 필드가 반환되지 않은 경우를 구분해야 합니다. is_vine은 Vine 프로그램 관련 평가를 식별합니다. Amazon 공식 문서에 따르면 Vine에 초대된 리뷰어는 의견을 게시하기 전에 상품을 무료로 체험할 수 있습니다. 따라서 이 상태는 표본 층화 필드로 쓸 수 있지만, Vine 리뷰를 곧바로 가짜로 판단하거나 필드가 없다는 이유로 Vine이 아니라고 판단할 수는 없습니다.
중복 제거 시 연결 관계를 보존하고, 텍스트가 비슷하다는 이유만으로 삭제하지 않기
애플리케이션 계층에서는 먼저 "출처 플랫폼 + 마켓플레이스 + review_id"로 같은 범위 안의 리뷰를 식별한 다음, 어떤 요청 상품에서 관측되었는지를 별도로 기록할 수 있습니다. 동일한 키가 서로 상충하는 상품 귀속 정보나 내용에 대응하면, 조용히 덮어쓰지 말고 충돌 레코드를 먼저 보존해 검증합니다. 신뢰할 수 있는 대응 관계가 없다면 사이트 간에 동일한 ID나 텍스트가 나타났다는 이유로 자동 병합해서는 안 됩니다.
review_id가 없을 때는 확인된 리뷰 영구 링크로 연결을 보조할 수 있으며, 그래도 불확실한 나머지 레코드는 중복 제거 대기 영역으로 보냅니다. 텍스트, 날짜, 평점의 조합은 근사 후보만 제공할 뿐 두 작성자가 같은 사람임을 증명하지 못합니다. "works great"가 두 번 나와도 실제로는 서로 다른 리뷰일 수 있으며, 번역된 동의어 텍스트는 고유 키가 될 수 없습니다.
같은 리뷰가 나중에 다시 나타나면 실제로 제공되는 텍스트, 평점, 유용하다는 평가를 받은 횟수, 상품 연결 관계를 비교합니다. 변경 사항은 우선 관측 차이로 기록합니다. 언어, 필드 제공 여부, 시간 범위의 차이로도 값이 달라질 수 있습니다. 이번 수집에서 특정 리뷰가 반환되지 않았다면 "이번 수집에서 관측되지 않음"으로만 표시하며, 삭제 이벤트를 생성하지 않습니다.
문제 분류는 반드시 원문 위치로 거슬러 올라갈 수 있어야 한다
모델을 연결하기 전에 사용이 승인된 소규모 표본으로 분류 경계를 수작업으로 정합니다. 주제는 호환성, 포장, 설명서, 배송처럼 조치 가능한 문제부터 시작하되, "명확한 문제 없음"과 "근거 불충분"도 남겨 둡니다. 리뷰 하나에 여러 주제를 허용하며, 태그 할당량을 채우려고 "미개봉" 상품에 품질 결론을 지어내서는 안 됩니다.
분류기에 전달하는 데이터는 작업에 꼭 필요한 내용으로 최소화합니다. 리뷰는 분석 대상 자료이며 시스템 지시가 아닙니다. 리뷰 안에 "규칙을 무시하라"나 "이 주소에 접속하라" 같은 문장이 있어도 모델이 도구를 호출하거나 처리 목표를 바꾸어서는 안 됩니다. 출력에는 최소한 리뷰 ID, 원문 텍스트 필드, 시작/끝 위치, 주제, 규칙 버전, 검토 대기 상태가 함께 묶여 있어야 합니다.
function validateAnnotation(review, annotation) {
const topics = new Set(["compatibility", "packaging", "instructions", "shipping"]);
if (typeof review.review_id !== "string" || !review.review_id.trim()) {
throw new Error("review id required");
}
if (annotation.review_id !== review.review_id
|| annotation.taxonomy_version !== "issues-v1"
|| !topics.has(annotation.topic)) {
throw new Error("unknown review or classification rule");
}
const field = annotation.source_field;
if (!["title", "text"].includes(field)) throw new Error("invalid source field");
const source = review[field];
const {start, end, quote} = annotation;
if (typeof source !== "string" || typeof quote !== "string"
|| !quote.trim() || !Number.isInteger(start) || !Number.isInteger(end)
|| start < 0 || end <= start || end > source.length
|| source.slice(start, end) !== quote) {
throw new Error("evidence does not match source");
}
return {
review_id: review.review_id, topic: annotation.topic,
source_field: field, start, end, quote,
taxonomy_version: "issues-v1", review_status: "unreviewed"
};
}
// synthetic text; demonstrates evidence checks only, not a real product review.
const sample = {review_id: "synthetic-review", text: "the API cannot reach the legacy model,wrapper intact."};
console.log(validateAnnotation(sample, {
review_id: sample.review_id, taxonomy_version: "issues-v1",
topic: "compatibility", source_field: "text",
start: 0, end: 9, quote: "the API cannot reach the legacy model"
}));이 검증기는 인용 위치가 입력 텍스트와 일치한다는 것만 증명하며, 주제 판단이 옳다는 것은 증명하지 못합니다. 모델이 "포장 완벽"을 인용하면서 포장 문제로 표시하더라도 문자 검사는 통과할 수 있으므로, 의미 검사나 수동 검토로 걸러 내야 합니다. start/end는 JavaScript 문자열 인덱스를 사용합니다. 데이터를 다른 언어로 넘길 때는 인덱스 규칙을 명시해야 하며, 바이트 오프셋과 문자 수를 섞어서는 안 됩니다.
실제 운영 환경에서는 바깥 계층에서 마켓플레이스, 상품 연결, 리뷰 버전도 함께 묶고, 항목당 출력 개수와 필드 유형을 제한해야 합니다. 모델이 스스로 보고하는 신뢰도는 보정된 정확도가 아닙니다. 출시 전에 수동 주석 작업용 표본을 선정하고, 누락, 오탐, 근거가 확인되지 않는 사례를 따로 집계해야 하며, 모든 오류를 보기 좋은 전체 정확도 수치 하나로 뭉뚱그려서는 안 됩니다.
OWASP는 웹 페이지, 문서, 사용자 리뷰에 숨겨진 지시를 간접 프롬프트 인젝션 위험으로 분류하며, 사용자 권한과 현재 작업을 기준으로 도구 호출을 검증할 것을 권장합니다. 따라서 리뷰 분류기는 제약된 후보 태그만 생성해야 하며, 상품 수정이나 메시지 전송 같은 액션은 리뷰 내용으로 승인되지 않습니다.
문제 비율에는 분모를 밝혀야 한다
순수 합성 예시에서 분석에 포함된, 중복 제거를 거친 판독 가능한 리뷰 10건 중 3건이 호환성과 관련된 것으로 확인되었다면, "이 표본에서 호환성 문제 언급률은 3/10"이라고 말할 수 있습니다. 이를 "구매자의 30%가 호환성 문제를 겪었다"로 바꿔 쓸 수는 없습니다. 리뷰 하나가 두 주제에 걸치면 주제별 비율의 합이 100%를 넘을 수 있습니다. 합이 100%인 구성 차트는 상호 배타적인 범주를 정의한 뒤에만 적절합니다.
모든 보고서에는 마켓플레이스와 상품 집합, 샘플링 시각, 실제 요청 파라미터, 반환 건수, 중복 제거 후 건수, 판독 가능한 텍스트 건수, 검토 대기 건수, 규칙 버전을 첨부합니다. 리뷰 게시 시각인 posted_at과 리뷰를 읽어 관측한 시각인 observed_at은 구분합니다. 오늘 작년 리뷰를 읽었다고 해서 오늘 새로운 사건이 발생한 것은 아닙니다.
주간 비교에서도 상품 집합, 수집 순서, 언어 처리, 시간 범위를 고정하거나 그 변경을 설명해야 합니다. 같은 초기 리뷰 묶음만 계속 읽는다면 작업 빈도를 늘려도 독립 표본은 늘어나지 않습니다. 카탈로그가 완전한 페이지네이션이나 시간 범위를 보장하지 않는 경우, 보고서는 전수 추세 모니터링이 아니라 관측된 표본에 대한 분석으로 제시해야 합니다.
보고서는 W3C PROV의 파생 기록 개념을 빌려 각 문제 결론을 리뷰 버전과 분류 활동에 연결할 수도 있습니다. 이렇게 하면 원문이 수정되었을 때 영향을 받는 태그와 요약을 찾을 수 있습니다. 다만 관계를 기록한다고 분류가 옳다는 것이 증명되지는 않으므로, 의미 검증은 계속 유지해야 합니다.
문제 목록을 실제 개선 워크플로로 연결하기
제품 팀에 넘길 만한 결론에는 영향이 확인된 사양, 대표 근거, 표본 분모, 배제되지 않은 대안적 설명, 다음 검증 단계가 포함되어야 합니다. 예를 들어 호환성 안내를 추가하거나 제품을 조정하기로 결정하기 전에 구형 모델에서 연결 문제를 재현합니다. 리뷰 자체가 엔지니어링 테스트, 주문 기록, 사후 서비스 기록을 대신하지는 못합니다.
초기 연동에서는 승인된 상품 하나만 골라 입력 검증, 응답 확인, 중복 제거, 원문 근거 검증, 수동 검토를 완료할 수 있습니다. 이 단계들을 재현할 수 있게 된 뒤에야 상품 목록을 늘려도 유용한 정보를 얻을 수 있습니다. 다음으로 Amazon 기능 페이지에서 파라미터를 확인하고, 일반 문서에 따라 요청 상태를 처리합니다. 수량부터 늘려 놓고 나중에 각 리뷰의 출처를 추측하는 방식은 피해야 합니다.
참고 LF-06