Skip to content
isdnetworks
Go back

외부 시스템의 성공 응답을 그대로 믿지 않게 된 이유

외부 시스템에 값을 보내고 성공 응답을 받았는데 나중에 보니 상대 쪽에 반영이 안 돼 있었다.

Table of contents

Open Table of contents

증상 — 성공인데 반영이 안 됐다

한 번이면 실수라고 넘겼을 텐데 여러 번 나왔다. 성공 응답을 받았다는 것과 저쪽 자료가 바뀌었다는 것은 서로 다른 사실이다. 우리는 그동안 앞의 것을 뒤의 것으로 읽고 있었고 반영 안 된 건이 우리 쪽에서는 완료로 남았다.

원인 — 성공이 성공이 아닐 때

사례를 모아 보니 몇 갈래로 나뉘었다. 우선 접수만 했다는 뜻인 경우가 있었다. 응답은 요청을 받았다는 것이고 실제 처리는 나중에 하는데 그때 실패하면 다른 데 기록되고 우리는 모른다.

한쪽만 반영된 경우도 있었는데 열 건을 보냈으나 여덟 건만 처리됐고 어느 것이 실패했는지는 응답에 없었다.

우리가 응답을 잘못 읽은 경우도 있었다.

{ "code": "0000", "message": "정상" }

code0000 이면 성공인 줄 알았는데 어떤 요청은 code 가 없고 result 안에 들어 있었다.

code 가 없으면 우리 코드가 빈 값으로 읽고 성공으로 판단했다. 상대가 필드를 추가하고 알려 주지 않아 해석이 조용히 어긋난 적도 있었다.

조치 — 모르는 것은 실패로

응답 파싱부터 엄격하게 고쳤다.

if ($response['code'] === '0000') { /* 성공 */ }

이 형태는 code 가 없으면 조건이 거짓이 되어 실패로 간다.

그런데 다른 곳에서는 같은 판정을 이렇게 쓰고 있었다.

if (($response['code'] ?? '') !== 'ERROR') { /* 성공 */ }

?? 로 기본값을 주고 있어서 code 가 없으면 성공이 된다.

이런 코드를 찾아 전부 고쳤다. 명시적으로 성공이라고 확인되지 않으면 실패로 본다는 기준 하나로 정리했다.

바꾸고 나니 처음에는 실패 건수가 늘어난 것처럼 보였는데 원래 실패였던 것이 그동안 성공으로 세어지고 있었던 것뿐이다.

검증 — 보낸 뒤 조회로 확인

API 로 보내고 나서 조회로 확인하는 단계를 넣었다.

1. 값을 보낸다
2. 성공 응답을 받는다
3. 잠시 뒤 조회해서 실제로 반영됐는지 본다
4. 안 됐으면 다시 보낸다

3 번을 넣기 전에는 2 번에서 끝났는데 보낸 것과 반영된 것은 다르다.

상대가 조회 API 를 제공하는 경우만 되지만 되는 곳은 이것이 확실했다. 다만 전부 확인하면 요청이 두 배가 되고 상대에게도 부담이라 금액이나 재고처럼 어긋나면 바로 문제가 되는 것만 붙였다.

대응 — 보낸 것을 기록으로 남겼다

무엇을 언제 보냈고 어떤 응답이 왔는지 전부 저장했다. 지우지 않고 계속 쌓았는데 이것이 나중에 크게 도움이 됐다. 문제가 생겼을 때 우리가 API 로 보냈는지를 확인할 수 있고 전에는 그것을 알 방법이 없어 매번 추측했다.

주의 — 실패를 완료로 기록하지 않기

가장 크게 걸린 것이 이것이었는데 상품 판매 중지를 보냈더니 그런 상품이 없다는 응답이 왔다. 코드는 그 응답을 보고 완료 로 기록하고 연동을 끊었다.

그런데 상대 쪽에는 상품이 남아 있어 그 응답 자체가 틀린 것이었다. 연동이 끊겨 있으니 그 뒤로 들어온 주문을 못 받았다.

상대가 없다고 했다를 근거로 우리 쪽 데이터를 정리한 것이 문제였다.

실패는 실패로 기록한다. 완료 시각을 채우지 않는다
재시도 대상에서 빼지 않는다
몇 번 실패하면 사람이 보게 한다

이 쪽이 느리기는 해도 건이 조용히 사라지는 것보다 낫다.

아직 못 정한 것도 있다. 조회 API 가 없는 곳은 확인할 방법이 없고 재시도 횟수도 정해 뒀을 뿐 그 숫자의 근거는 없다.

정리


Share this post on:

Previous Post
소스에서 거꾸로 스키마를 그렸다
Next Post
이력에는 생성이라고 찍혀 있었다