주문 건수가 팀마다 달랐다. 같은 날 같은 것을 세는데 숫자가 셋이었다.
Table of contents
Open Table of contents
증상 — 같은 말에 세 숫자
회의 자리에 올라온 숫자가 이랬다.
우리 화면 41,882
정산 쪽 38,204
지표 쪽 45,110
셋 다 어제 주문 건수라고 불리고 있었다. 숫자가 다르면 그중 하나가 틀렸을 것으로 보게 된다.
그래서 세 숫자를 뽑은 SELECT 를 나란히 놓고 diff 를 떴다. 갈린 부분은 전부 WHERE 였고 SELECT 뒤쪽은 셋이 같았다.
어느 쪽은 취소된 것을 빼고 세었고 어느 쪽은 결제 전 상태까지 세고 있었다. 틀린 조건을 찾으려고 떴는데 나온 것은 서로 다른 조건 셋이었다.
status 와 state 처럼 컬럼 이름부터 화면마다 달라서 대조에 시간이 걸렸다. 조회가 세 벌로 따로 자란 흔적이 그대로 남아 있었다.
무엇을 세고 있는지 물었다
조건이 다른 이유를 알려면 각자에게 물어보는 것이 빨랐다.
우리 결제까지 끝난 주문
정산 취소·환불을 뺀 주문
지표 주문서가 만들어진 것 전부 (결제 전 포함)
셋 다 맞는 숫자였고 세는 대상이 달랐을 뿐이었다.
정산 쪽은 실제로 돈이 오간 것을 세야 하고 지표 쪽은 유입이 얼마나 되는지를 봐야 한다. 각자의 업무에 맞는 대상을 고른 결과라서 하나로 합칠 수 있는 것이 아니었다.
틀린 숫자를 찾는 문제가 아니라 같은 말이 셋을 가리키는 문제였다. 이 말을 그대로 두면 회의 때마다 같은 대조를 다시 하게 된다.
실제로 그전에도 두어 번 SELECT 를 나란히 놓고 맞춰 본 적이 있었다. 그때는 조건이 다르다는 것까지만 확인하고 말을 손대지 않아서 같은 자리로 돌아왔다.
조치 — 말을 나누고 이름을 붙였다
셋에 각각 다른 이름을 붙였다.
주문서 생성 결제 전 포함. 장바구니에서 넘어온 것
결제 완료 주문 결제까지 끝난 것
유효 주문 결제 완료에서 취소·환불을 뺀 것
그리고 화면과 문서에서 이 이름을 쓰게 했다.
숫자만 보여주던 자리에 무엇을 센 것인지를 함께 적었다.
[어제 결제 완료 주문] 41,882건
숫자 옆에 이름이 붙으니 셋이 다른 것 자체가 문제가 아니게 됐다. 다르다는 사실이 아니라 무엇이 다른지를 모르는 것이 문제였다.
이름을 정할 때는 세 팀이 각자 쓰던 말을 그대로 쓰지 않았다. 한쪽 말을 고르면 나머지 둘이 자기 것을 빼앗긴 것으로 읽히므로 주문 앞에 무엇인지를 붙이는 형태로 셋 다 새로 지었다.
변경 내용 — 코드와 컬럼 이름
말을 나눴으니 코드에서도 갈라야 했다.
// 전에는 하나였다
public function countOrders(string $date): int;
// 나눴다
public function countCreated(string $date): int;
public function countPaid(string $date): int;
public function countValid(string $date): int;
countOrders 하나였을 때는 부르는 쪽이 무엇을 세는지 모르고 썼다.
이제 countCreated 와 countPaid 와 countValid 중에서 고른다. 고르는 순간 무엇을 세는지 정하게 되고 이름만 봐도 갈린다.
집계 표의 컬럼 이름도 같이 봤다.
`order_count` -- 무엇을 센 것인지 모른다
`paid_count` -- 바꿨다
order_count 는 몇 년치가 쌓여 있는데 그동안 무엇을 담았는지 아무도 확언하지 못했다. 이름이 모호하면 지나간 자료의 성격까지 함께 모호해진다.
쌓인 값을 지울 수는 없어서 paid_count 를 새로 만들고 앞으로는 그쪽에만 적게 했다. order_count 는 어느 시점까지의 값인지를 주석에 적고 그대로 뒀다.
설정 — 용어 목록과 정의
같은 문제가 더 있을 것 같아 자주 쓰는 말을 훑었다.
회원 가입한 사람인가, 탈퇴 안 한 사람인가, 최근 산 사람인가
매출 결제 금액인가, 확정 금액인가, 수수료 뺀 것인가
상품 판매 단위인가, 옵션까지 포함인가
재고 실제 수량인가, 판매 가능 수량인가 (예약분 제외)
넷 다 팀마다 달랐고 특히 재고는 화면과 정산이 서로 다른 것을 보고 있었다.
그래서 용어 목록을 만들면서 각 말이 어느 표의 어느 값인지를 함께 적었다.
용어 정의
주문서 생성 order 테이블에 행이 생긴 것. state='READY' 포함
결제 완료 state 가 PAID 이상인 것
유효 주문 결제 완료에서 CANCEL, REFUND 를 뺀 것
가용 재고 stock - reserved. 화면에 보이는 수량
실물 재고 stock. 창고에 있는 수량
말로만 적으면 읽는 사람마다 다시 갈리므로 state 와 컬럼 식으로 적었다.
이렇게 적어 두면 정의를 읽은 사람이 그대로 WHERE 에 옮길 수 있다. 정의와 조회가 어긋날 여지가 줄고 새로 만드는 화면도 같은 조건으로 센다.
숫자를 낼 때도 정의를 함께 내보내게 했다.
return [
'count' => $n,
'definition' => '결제 완료(state >= PAID), 취소·환불 포함',
'period' => $date,
];
받는 쪽이 definition 을 같이 받으니 무엇인지 다시 묻지 않아도 된다. 화면에도 작게 표시해서 마우스를 올리면 정의가 나오게 했다.
맞춰 볼 수 있게 했다
세 숫자가 서로 설명되는지 보는 화면을 만들었다.
주문서 생성 45,110
- 결제 전 3,228
= 결제 완료 41,882
- 취소·환불 3,678
= 유효 주문 38,204
셋이 한 화면에 있고 뺄셈이 맞으면 셋 다 정상이다.
실제로 한 번 안 맞았다. 결제 완료로 넘어간 뒤 다시 결제 전으로 내려간 주문이 있었고 그런 상태 변화는 원래 없어야 하는 것이었다.
state 가 PAID 에서 READY 로 내려간 자리를 찾아보니 관리 화면의 되돌리기 기능이었다. 그 기능이 결제 기록은 그대로 두고 상태만 내리고 있어서 어느 쪽으로 세느냐에 따라 건수가 달라졌다.
정의를 맞추니 자료 쪽 문제가 드러난 셈이었다. 숫자가 안 맞을 때 그것이 정의 탓인지 자료 탓인지 처음으로 갈렸다.
정리
- 같은 말이 팀마다 다른 것을 가리키면 숫자가 안 맞는다
- 어느 하나가 틀린 것이 아니라 셋 다 맞을 수 있다
- 무엇을 세는지부터 물어본다
- 틀린 숫자를 찾는 것이 아니라 말을 나누는 것이 답이다
- 셋에 다른 이름을 붙이고 숫자 옆에 그 이름을 적는다
countOrders를countPaid처럼 갈라 이름만 봐도 알게 한다order_count처럼 모호한 컬럼은 지나간 자료까지 모호하게 만든다- 용어 정의에 어느 표의 어느 값인지 적는다
- 숫자를 낼 때
definition을 같이 낸다 - 셋이 뺄셈으로 설명되는지 보면 자료 쪽 문제가 드러난다