Skip to Content
Backend로컬 상품 조회 API 구현과 실제 수집의 한계
💻 Backend2026년 10월 4일

로컬 상품 조회 API 구현과 실제 수집의 한계

#go#sqlite#api#testing#personal-project

쿠팡 상품과 옵션별 가격을 로컬 API로 조회하는 도구를 만들었습니다. 기존 봇이나 OpenClaw에 바로 연결하기보다 Go HTTP API와 SQLite, 브라우저 수집 워커를 갖춘 독립 서비스로 시작했습니다.

로컬 API와 DB를 구현하는 것과 실제 상품을 가져오는 일은 달랐습니다. 테스트와 빌드는 통과했지만 실제 검색은 403으로 실패했습니다. 이 글에서는 구현한 구조와 외부 조회에서 막힌 지점을 함께 정리합니다.

옵션별 가격 이력 설계

상품 전체의 최저가와 특정 옵션의 가격을 구분하고, 옵션과 조회 시각별로 이력을 저장하도록 했습니다. 알 수 없는 가격은 0으로 넣지 않았습니다. 0이라는 값이 저장되면 최저가와 가격 변화 계산에도 영향을 주기 때문입니다.

관심 상품과 목표 가격, 계정별 조회를 위한 구조도 만들었습니다. 브라우저는 요청마다 새로 열기보다 전용 워커를 재사용하도록 구성했습니다.

처음 API 골격만 준비됐을 때는 수집 어댑터가 없어 검색 요청에 503 SOURCE_NOT_CONFIGURED를 반환했습니다. 이 응답은 서버가 떠 있다는 것과 상품을 조회할 수 있다는 것을 구분해 보여주는 상태였습니다.

수집 워커 연결과 실제 요청

로컬 테스트 21개와 race 검사, 빌드를 통과했고 HTTP 항목 8개를 점검했습니다. 이후 브라우저 엔진을 설치하고 JavaScript 엔진 속성의 호환 문제를 수정했습니다. 첫 실행이 느려 제한 시간도 조정했습니다.

하지만 실제 상품 검색 두 건은 모두 403 ACCESS_BLOCKED로 실패했습니다. 워커 연결을 고친 뒤에도 외부 자료를 확보하지 못한 것입니다.

범위당시 결과
로컬 API·DB구현과 테스트 완료
워커 연결엔진 호환 문제 수정
실제 상품 검색403으로 실패
계정 주문 조회실제 로그인 확인 미완료
메신저 연동작업 범위에서 제외

가격과 수집 결과를 따로 저장하는 이유

외부 조회가 막힌 상태에서 API 형식을 테스트하려면 샘플 가격과 실제 수집 상태가 섞이지 않아야 합니다. 다음은 옵션별 가격 수집 기록을 저장하는 간단한 스키마 예시입니다. 실제 프로젝트의 테이블을 그대로 옮긴 것은 아닙니다.

sql
example/product-observation.sql
CREATE TABLE price_observations ( product_id TEXT NOT NULL, option_id TEXT NOT NULL, observed_at TEXT NOT NULL, price INTEGER, status TEXT NOT NULL CHECK (status IN ('ok', 'blocked', 'unavailable')), CHECK (price IS NULL OR price >= 0), CHECK ((status = 'ok' AND price IS NOT NULL) OR (status <> 'ok' AND price IS NULL)), PRIMARY KEY (product_id, option_id, observed_at) );

조회 차단에는 가격이 없으므로 price를 NULL로 둡니다. 403을 최저가 0원으로 저장하면 가격 알림과 최저가 이력이 모두 잘못될 수 있습니다. 실제 상품을 받지 못한 이번 결과에도 이 구분이 중요했습니다.

상품 수준의 최저가와 옵션 하나의 가격 역시 다른 값입니다. 크기·수량·판매 조건이 다른 옵션을 같은 시계열로 합치면 가격이 내려간 것처럼 보일 수 있습니다. 따라서 어떤 옵션의 가격인지 구분할 키와 조회 시각을 함께 저장하도록 했습니다.

로컬 테스트와 외부 연결 테스트

테스트가 확인하는 대상을 나누면 구현 결과를 과장하지 않고 설명할 수 있습니다.

확인입력알 수 있는 것
저장 로직준비한 샘플 관측옵션 키·누락값·이력 처리
HTTP API모의 어댑터 결과상태 코드와 응답 형식
워커 연결브라우저 실행 결과프로세스·시간 제한·응답 전달
실제 검색원천 서비스 응답그 환경에서 실제 자료를 얻는지

Go에서는 저장소 루트에서 테스트와 race 검사를 실행하는 방식으로 내부 동작을 확인할 수 있습니다.

bash
example/check-go-service.sh
go test ./... go test -race ./... go build ./...

이는 Go 프로젝트의 검증 예시이며 현재 블로그 소스에서 실행하는 명령은 아닙니다. 실제 외부 검색이 차단된 상황에서는 테스트가 통과해도 정상 상품 JSON을 받았다고 쓰지 않습니다. 실패를 ACCESS_BLOCKED로 전달하고 이후 연결 대상이 그 상태를 처리할 수 있도록 남겼습니다.

수집 워커를 재사용하는 것은 브라우저 초기화 비용과 실행 관리를 위한 구성입니다. 외부 서비스의 접근 제한을 우회하는 기능은 아닙니다. 실제 상품 정보를 가져올 수 있어야 다른 서비스와 연동하거나 가격 알림을 붙이는 작업도 진행할 수 있습니다. 당시에는 로컬 API까지 만들었고, 실제 상품 수집은 해결하지 못한 상태였습니다.

구현 결과와 남은 작업

외부 검색이 실패했으므로 실제 상품 가격 이력을 수집한 결과는 없습니다. 계정 주문 조회와 선택적인 Partners 연결도 각각 로그인과 키 검증이 남아 있었습니다.

이 상태를 README와 검증 문서에 남겼습니다. 샘플 응답은 테스트용으로만 사용했으며, 실제 가격 수집과 주문 조회는 완료하지 못했습니다.

로컬 테스트는 API와 저장 로직을 확인하는 데 필요했지만 외부 자료를 얻는 경로까지 대신 검증해 주지는 않았습니다. 이 작업의 결과는 독립 로컬 구현과 실제 검색 차단 확인까지입니다. 다른 서비스에 연결하는 작업은 그 이후 범위로 남겼습니다.

Last updated on