Skip to content
isdnetworks
Go back

번호 네 개가 비어 있었다

외부 시스템의 상품을 가져오는 동기화가 있다. 어느 날 특정 상품이 안 들어온다는 얘기가 나왔다.

Table of contents

Open Table of contents

증상 — 번호 네 개가 비었다

들어온 번호를 정렬해 봤다.

183188
183189
183190
183195      ← 191~194 가 없다
183196

183191 부터 넷이 통째로 빠지고 앞뒤는 멀쩡했다.

받다가 빠뜨렸다는 가정으로는 이 모양이 설명되지 않았다. 한둘이 아니라 붙어 있는 넷이 함께 빠진 것이라 다른 이유를 찾아야 했다.

판단 기준 — 원인 후보 셋

후보를 나눠 적었다.

1. 상대가 안 준다      삭제됐거나 비공개라 응답에서 제외됨
2. 조회 조건이 제외한다  우리가 요청한 범위에 안 들어감
3. 애초에 그 번호가 없다  채번이 연속적이지 않음

세 후보가 다 가능하고 확인 방법이 각각 달랐다.

1 번을 먼저 봐야 했다. 상대에 없는 것을 우리 코드에서 찾으면 아무리 봐도 답이 안 나오기 때문이다.

원인 — 수정된 것만 가져오는 조회

상대 화면에서 넷 다 있는 것을 확인하고 우리 API 호출을 봤다.

GET /api/products?InquiryType=mod&StartDate=...&EndDate=...

InquiryType=mod 는 문서상 수정된 상품만이었다.

여기서 답이 나왔다. 등록만 되고 한 번도 수정되지 않은 상품은 mod 조회에 안 나오는데 빠진 넷이 전부 그랬다.

제약 — 변경의 정의는 상대가 정한다

증분 조회는 전량보다 싸서 처음만 전체를 받고 그 뒤로는 변경분만 받는 구조를 흔히 쓴다.

문제는 무엇이 변경인지를 상대 시스템이 정한다는 것이다. 등록이 변경인지 삭제가 변경인지 재고나 가격만 바뀐 것이 변경인지가 우리 판단이 아니다.

InquiryType=reg     등록된 상품
InquiryType=mod     수정된 상품

이 시스템에서는 등록이 변경이 아니었고 reg 라는 조회가 따로 있었다.

우리가 reg 의 존재를 모르고 한쪽만 부르고 있었다. 둘 다 불러야 전체가 된다.

조치 — 두 유형 호출과 중복 제거

regmod 를 함께 부르게 고쳤다.

$products = array_merge(
    $this->fetch(['InquiryType' => 'reg', ...]),
    $this->fetch(['InquiryType' => 'mod', ...])
);

// 두 조회에 같은 상품이 나올 수 있다
$products = $this->uniqueByUid($products);

uniqueByUid 를 빼면 등록되고 바로 수정된 항목이 두 번 처리된다.

저장이 갱신과 생성을 겸하는 방식이라 결과는 같지만 호출이 두 배가 된다. 조회를 하나 늘리는 것이 처리 쪽까지 건드리는 자리였다.

재발 방지 — 전량 대조와 확인 순서

regmod 를 다 불러도 증분만으로는 언젠가 어긋난다.

상대 전체        17,840
우리 저장분      17,836
차이                  4  ← 이 목록을 출력한다

주 1회 전량을 받아 개수와 uid 를 대조하고 어긋난 것만 다시 가져온다.

상대가 응답을 빠뜨렸거나 우리가 처리 중 죽었거나 조회 유형에 안 잡히는 변경이 있으면 그 차이로 드러난다.

안 들어온다는 신고가 다시 왔을 때 볼 순서도 적었다.

1. 그 항목이 상대에 있는가     상대 화면이나 단건 조회로 확인
2. 우리 조회 조건에 들어오는가  조회 유형, 기간, 필터를 확인
3. 받았는데 저장이 실패했는가   처리 로그 확인
4. 저장됐는데 화면에서 안 보이는가  조회 조건 확인

1 번을 먼저 하지 않으면 없는 데이터를 찾느라 시간을 쓴다.

이번에도 그럴 뻔했는데 상대 화면을 확인하니 실제로 삭제된 번호도 섞여 있었다. 등록했다 지우면 그 번호는 재사용되지 않으므로 연속 번호는 채번의 성질이지 완전성의 지표가 아니다.

정리


Share this post on:

Previous Post
실패한 중지가 삭제 밑에 묻혔다
Next Post
태그가 말해 주지 않는 베이스