채널에서는 취소로 처리됐으니 우리 시스템도 CANCELED 로 정합 전환해 달라는 문의가 들어왔다. orders.status 하나만 바꾸면 되는 일로 보여서 가능하다고 답해 버렸다.
Table of contents
Open Table of contents
검증 — 실행 직전의 확인
실제로 바꾸기 전에 OrderStateMachine 부터 열어 봤다. cancel() 이 허용되는 이전 상태가 PAID 와 READY 를 포함해 넷이었는데 전부 발송 전 단계였다.
문의 건은 DELIVERED 를 거쳐 RETURN_REQUESTED 에 있었으므로 그 허용 목록에 없었다. forceCancel() 경로가 있는지도 봤는데 발송 이후 상태는 가드가 명시적으로 거부하고 있었다.
원인 — 성공해도 남는 부작용
그 가드를 넘겼다고 가정하더라도 문제가 하나 더 있었다. forceCancel() 이 성공하면 seller_penalties 를 새로 생성하는 코드가 이어서 돌기 때문이다.
정합을 맞추려던 조치가 없던 페널티를 만들어 내는 셈이 된다. 전환이 가능한지만 보고 그 뒤에 무엇이 따라오는지를 안 보면 조치가 새 문제를 만든다.
주의 — 단계에 매인 개념
여기까지 정리하면 취소 상태는 발송 전 단계에만 적용되는 개념이었다. 발송 전에는 취소가 종착 상태이고 발송 후에는 반품이 종착 상태다.
배송 완료 후 환불받은 건은 RETURNED 가 정상 종착 상태이므로 취소로 바꿀 수 없고 바꿀 이유도 없다. 구조적으로 불가능한 요청이었다.
조치 — 채널 쪽의 표기 사정
그러면 채널은 왜 그것을 취소라고 부르는지도 함께 확인했다. 채널 쪽에 수거와 검수가 끝나면 반품 전환이 안 되는 제약이 있어서 그 시점 이후의 환불을 구매확정 후 취소라고 부르고 있었다.
채널 측 제약에 따른 표기이고 우리 상태 모델과 대응하지 않는다. 회신은 두 가지 방법이 있었는데 안 된다고만 짧게 답하는 것과 왜 안 되는지까지 적는 것이다. 뒤쪽을 골랐다. 이유는 이미 가능하다고 답했던 터라 근거 없이 뒤집으면 신뢰가 더 깎여서다. 대신 회신이 길어져 담당자가 읽는 부담을 감수했고 무엇이 정상 종착인지와 그 표현이 라벨 차이라는 것을 함께 적어 정정 회신했다.
배경 — 확인 전의 약속
이 건에서 내가 한 실수는 확인하기 전에 가능하다고 답한 것이었다. 상태값 하나 바꾸는 일처럼 보였지만 실제로는 상태 모델의 전제가 걸려 있었다.
가능해 보인다와 가능하다는 다른 말이고 문의 대응에서는 그 차이가 특히 크다. 한 번 가능하다고 하면 상대는 그것을 전제로 다음을 진행하므로 확인 전에는 확인해 보겠다고 답해야 한다. 앞으로도 채널마다 같은 실체를 다르게 부를 것이므로 라벨 불일치는 channel_status_map 으로 관리하고 모델을 라벨에 맞추지 않는다.
정리
- 채널의 표현을 그대로 우리 상태에 매핑하지 않는다
- 상태에 적용 가능한 단계가 정해져 있을 수 있다
- 강제 전환이 성공해도 부작용이 생길 수 있다
- 정합을 맞추려다 정합이 깨지는 경우가 있다
- 확인 전에 가능하다고 답하지 않는다
- 잘못 약속했으면 왜 안 되는지와 무엇이 맞는지를 같이 준다
- 라벨 불일치는 매핑표로 관리한다
- 모델을 라벨에 맞추지 않는다