교환 건 하나에서 재배송 송장이 안 들어간다는 문의가 왔는데 화면에서 몇 번 눌러 봐도 결과가 같다고 했다.
Table of contents
Open Table of contents
송장이 안 들어가는 건
먼저 그 건을 SELECT 해 어느 컬럼이 비어 있는지 봤다.
SELECT delivery_company_code, delivery_tracking_number FROM order_returns WHERE id = ?;
-- NULL, NULL
delivery_company_code 와 delivery_tracking_number 가 둘 다 NULL 이었고 그 뒤에 들어가야 할 값들도 비어 있었다.
여러 컬럼이 동시에 NULL 이면 각각 실패한 것이 아니라 앞쪽 하나가 막혀 있을 가능성이 크다. 운영에서는 교환관리 화면에서 대상을 골라 「교환 재배송 처리」로 택배사와 송장을 넣으면 된다고 봤는데 눌러도 안 됐다. 그래서 그 컬럼들을 채우는 처리를 grep 으로 찾았다.
코드의 상태 가드
나온 함수 앞부분에 가드가 있었다.
// Helper.php
public function exchangeDelivery($return, $params)
{
if ($return->return_status !== 'collected') {
return; // 여기
}
}
return_status 가 collected 일 때만 아래로 내려간다. 그런데 그 건의 return_status 는 collected 가 아니었다.
조건에 안 맞으면 함수가 조용히 돌아가므로 오류도 안 나고 아무 값도 안 생긴다. 화면에는 눌린 것처럼 보이고 실제로는 아무 일도 일어나지 않는다.
가드를 못 넘으면 화면으로는 못 푼다
이런 구조에서는 화면에서 몇 번을 눌러도 결과가 똑같이 나온다. 화면 조작은 그 함수를 부를 뿐이고 가드는 그 안에 있기 때문이다.
그래서 막힌 건은 화면을 누르기 전에 지금 상태가 무엇인지부터 봐야 한다. 상태를 안 보고 누르면 안 되는 이유를 모른 채 반복하게 된다.
비어 있는 뒤쪽 값들
왜 그 상태에 있는지를 거슬러 올라가 보니 앞선 단계가 정상 순서와 다르게 진행돼 있었다. 어느 처리가 먼저 들어가면서 상태가 다른 경로로 넘어간 것이었다.
그러면 뒤에 이어질 처리들이 전부 가드를 못 넘고 뒤쪽 값이 다 비어 있던 것이 그 하나의 결과였다.
안 나오는 것과 안 저장하는 것
답하는 과정에서 외부 시스템의 내부 번호를 우리가 갖고 있는지도 물어 왔다. 관련 표를 전부 SELECT 해 봤는데 그 번호는 어디에도 없었다.
없다는 답을 할 때 저쪽이 안 주는 것인지 우리가 안 저장하는 것인지를 갈라서 적었다. 둘은 다음에 할 일이 다르고 그 답의 근거는 관련 표를 다 SELECT 해 봤다는 사실이었다.
정리
- 처리 흐름에 상태 가드가 있으면 그 상태일 때만 진행된다
- 조건에 안 맞으면 오류 없이 조용히 끝난다
- 가드를 못 넘으면 화면 조작으로는 못 푼다
- 뒤의 컬럼이 전부 비어 있는 것은 앞쪽 하나가 막혀서다
- 막힌 건은 화면을 누르기 전에 상태부터 본다
- 앞선 단계의 순서가 어긋나면 상태가 다른 경로로 간다
- 저쪽 내부 번호가 우리
MySQL어디에도 없을 수 있다 - 안 나오는 것과 안 저장하는 것을 구분해 답한다