마켓API실전

쇼피에 가격 1,463건을 보냈는데 하나도 안 바뀌었습니다

열정의디케이 2026. 9. 18.

가격을 한 번에 1,463건 고치는 작업을 돌렸습니다. 오류는 한 건도 없었고, 쇼피가 돌려준 답은 전부 "성공" 이었습니다.

 
셀러센터를 열어 봤습니다. 가격이 하나도 안 바뀌어 있었습니다.
## 필드 이름 하나가 틀렸습니다
프로그램으로 쇼피를 다룰 때는 API 라는 창구를 씁니다. 사람이 셀러센터에서 손으로 누르는 대신, 프로그램이 쇼피에 "이 상품 가격을 얼마로 바꿔줘" 하고 보내는 통로입니다.
할인가를 보낼 때 쓰는 필드가 상품 종류에 따라 다릅니다.
| 상품 | 할인가를 넣는 필드 |
|---|---|
| 옵션 없는 상품 | `promotion_price` |
| 옵션 있는 상품 | `model_promotion_price` |
저는 옵션 있는 상품에 `promotion_price` 를 보내고 있었습니다.
쇼피는 그걸 거절하지 않았습니다. 정상으로 받고, 오류 칸을 비워서 돌려주고, 아무것도 바꾸지 않았습니다.
## 거절당하는 편이 나았습니다
오류가 났으면 그날 바로 알았을 겁니다. 대신 기록에는 "1,463건 성공" 이 남았고, 저는 다 끝났다고 적었습니다. 잘못됐다는 걸 알려 주는 게 아무것도 없었습니다.
없는 번호를 보낼 때도 똑같습니다. 그 상품에 존재하지도 않는 옵션 번호를 보내면 쇼피는 성공이라고 답합니다.
저희 상품 하나는 그래서 몇 달 동안 시스템에는 "판매 중지" 로 적혀 있으면서, 실제로는 재고 1,000개를 달고 계속 팔리고 있었습니다. 우리 쪽 표에 적힌 번호를 믿고 보냈기 때문입니다. 그 번호는 쇼피에 없는 번호였고, 쇼피는 모른 척 성공이라고 답했습니다.
## 화면에 뜬 말과 진짜 이유가 달랐습니다
다른 작업에서는 실패가 뜨긴 했습니다. 그런데 화면에 이렇게만 나왔습니다.
> `Update price failed, please try later.`
> 가격 수정에 실패했습니다. 나중에 다시 시도하세요.
그래서 몇 번을 다시 돌렸습니다. 될 리가 없었습니다. 쇼피가 돌려준 답을 통째로 뜯어보니 `failure_list` 라는 목록 안에 진짜 이유가 건별로 적혀 있었습니다.
> `Product category is prohibited for the channel. Channel detail: ...`
> 이 카테고리는 해당 채널에서 판매가 금지되어 있습니다.
"나중에 다시 하세요" 와 "이 카테고리는 애초에 안 됩니다" 는 해야 할 일이 완전히 다릅니다. 쇼피의 답은 겉면과 안쪽이 따로 놉니다. 겉면의 `message` 는 "실패" 한 줄이고, 왜 실패했는지는 `failure_list[].failed_reason` 에 들어 있습니다.
더 곤란한 건, 겉면이 성공이어도 안쪽에서는 옵션별로 거절될 수 있다는 점입니다. 안쪽을 안 읽으면 거절된 걸 성공으로 세게 됩니다.
## 제 실수인지 궁금해서 전부 세어봤습니다
이게 제가 문서를 대충 읽어서 생긴 일인지, 아니면 원래 이런 구조인지 확인하고 싶었습니다. 그래서 쇼피가 공개한 API 문서에서 기능 444개를 전부 받아 오류 목록을 세어봤습니다.
오류 코드는 297가지였습니다. 그런데 상위 몇 개가 이렇습니다.

 
`error_param` 이라는 코드 하나가 309가지 뜻으로 쓰입니다. 444개 기능 전부에 나옵니다. 쉽게 말하면, 이 코드를 받아도 어느 값이 왜 잘못됐는지 알 방법이 없습니다.
집계까지 갈 것도 없습니다. 재고 수정 기능의 문서에서 오류 표를 한 화면만 봐도 같은 코드가 네 번 나옵니다. 네 번 다 뜻이 다릅니다.

 
## 이름이 "인증 오류" 인데 재고 이야기가 들어 있습니다
`error_auth` 는 이름만 보면 로그인이나 권한 문제 같습니다. 그런데 실제로 이 코드가 덮는 범위가 이렇습니다.
| 실제로 오는 문구 | 우리말 뜻 | 인증 문제인가 |
|---|---|---|
| `Invalid access_token.` | 접속 토큰이 만료됨 | ○ |
| `Stock should be larger than reserved stock.` | 재고가 예약분보다 적음 | ✕ |
| `Please wait for the holiday mode set then to edit item.` | 휴가 모드라 지금은 못 고침 | ✕ |
| `The location_id input is not matched the shop's location_id.` | 창고 번호가 가게와 안 맞음 | ✕ |
| `The registered phone number of your shop is abnormal.` | 가게 전화번호 형식이 이상함 | ✕ |
이 코드를 보고 "로그인이 풀렸구나" 하고 접속을 다시 하는 프로그램을 짜면, 접속은 멀쩡한데 계속 실패하는 상태에 갇힙니다. 저희가 실제로 한동안 그랬습니다.
## 지금은 이렇게 합니다
보낸 뒤에 다시 읽어봅니다. 몇 건 보냈는지로 성공을 세지 않습니다. 다시 읽어서 값이 진짜 그렇게 됐는지 확인하고, 그 숫자로 셉니다. 이것만이 제가 예상하지 못한 실패까지 잡아줍니다.
번호는 쇼피에서 받아옵니다. 우리 표에 적힌 상품·옵션 번호를 믿지 않습니다. 지금 쇼피가 들고 있는 목록을 먼저 읽고, 거기에 맞춰 보냅니다.
주고받은 내용을 통째로 남깁니다. 한 줄만 기록하면 진짜 이유가 사라집니다. 요청과 답을 파일로 떨어뜨려 두면 나중에 문제가 생겼을 때 그것만 열어보면 됩니다.
새 기능을 쓰기 전에 이미 짜둔 코드를 먼저 찾아봅니다. 이번 건도 다른 화면에는 `model_promotion_price` 가 이미 제대로 들어가 있었습니다. 같은 경로를 부르는 코드를 한 번 찾아보면 20초에 끝날 일이었습니다.
## 셀러 입장에서 왜 중요하냐면
이런 실패는 조용합니다.
가격이 안 바뀌었는데 시스템은 바뀌었다고 알고 있으면, 며칠씩 예전 가격으로 팔립니다. 할인 행사를 걸었는데 실제로는 정가로 팔리고, 반대로 행사가 끝났는데 계속 할인가로 나갈 수도 있습니다. 그 며칠은 아무도 모릅니다.
자동화 프로그램을 쓰거나 만드실 때 확인해보실 게 하나 있습니다. "보냈다" 와 "바뀌었다" 를 구분해서 세고 있는가. 이 둘을 같은 걸로 세는 프로그램은 언젠가 조용히 틀립니다.
---
같은 실수를 하루에 네 번 했습니다. 네 번 다 원인이 달라 보였는데, 뿌리는 하나였습니다. 문서를 기억으로 쓰고, 이미 잘 돌아가는 코드를 안 봤습니다.

댓글

💲 추천 글