Skip to content
isdnetworks
Go back

이력에는 생성이라고 찍혀 있었다

이력 테이블에 이렇게 찍혀 있었다.

3월 14일 23:03   출고 생성 · 송장 43937812472

Table of contents

Open Table of contents

증상 — 이력과 자료가 안 맞았다

그런데 order_exports 에는 1건뿐이었다.

[이력]   출고 생성 (3월 14일)
[출고]   1건, created_at 3월 2일

생성됐다는데 created_at 이 3월 2일인 것 하나뿐이었다.

문구가 자료와 어긋나면 둘 중 하나는 사실이 아니다. 이력은 사람이 아니라 코드가 남기는 것이라 처음에는 그쪽을 믿었다.

검증 — 시각 두 개를 봤다

그 1건의 두 시각을 함께 봤다.

SELECT created_at, updated_at, delivery_tracking_number
  FROM order_exports WHERE id = ?;
created_at   3월 2일 ...
updated_at   3월 14일 23:02
송장         43937812472

updated_at 이 3월 14일이고 송장이 이력에 찍힌 것과 같았다.

created_atupdated_at 이 며칠 차이가 났고 이력 시각은 뒤쪽과 붙어 있었다. 그 시점에 일어난 것은 생성이 아니라 갱신이었다.

원인 — 하위 층 기준의 문구

이렇게 놓으니 앞뒤가 맞아떨어졌다.

새 출고를 만든 게 아니라
기존 출고의 송장과 출고시각을 덮어씀
created_at은 그대로
updated_at만 갱신

이력 문구는 생성인데 실제로는 갱신이었다.

이력 문구를 남기는 자리를 grep 으로 찾았다.

$this->addHistory($item, '출고 생성 · 송장 ' . $number);

addHistory 가 붙어 있는 대상이 하위 항목이었다.

export_item   새로 생김   ← "생성"
export        기존 것 갱신

export_item 기준으로는 그 문구가 생성인 것이 맞았다.

같은 사건이라도 어느 층에서 보느냐에 따라 생성이기도 하고 갱신이기도 하다. 문구가 틀린 것이 아니라 그것이 무엇에 대한 것인지를 내가 잘못 읽은 것이었다.

교훈 — 같은 측정의 반복

이 건을 조사하면서 오진을 두 번 했다.

[1차]  출고 1건 → 재출고 안 함
[2차]  다시 세어 봄 → 여전히 1건 → 재출고 안 함

같은 방법으로 두 번 세면 두 번 다 같은 답이 나온다.

세 번째 확인에서는 아예 다른 것을 봤다.

[1·2차]  건수
[3차]    created_at 대 updated_at, 그리고 이력

세는 것에서 대조하는 것으로 바꾸니 그때 판정이 갈렸다.

COUNT 라는 측정 자체가 틀렸는데 그것을 반복해서 확인한 것이었다. 같은 측정을 반복하는 것은 확인이 아니다.

판단 기준 — 두 시각의 대조

이 유형의 판별법을 적어 뒀다.

SELECT created_at, updated_at FROM order_exports WHERE order_id = ?;
같으면   손댄 적 없음
다르면   뭔가 갱신됨   ← 이력으로 확인

출고가 1건뿐인 것만 보고 재출고를 안 했다고 단정하지 않는다.

이력과 두 시각을 반드시 대조한다. 건수만 세고 있으면 덮어쓰기가 있었는지 없었는지가 아예 안 갈린다.

주의 — 오염된 경과일

이 덮어쓰기가 created_at 을 쓰는 다른 계산에 영향을 줬다.

$elapsed = now()->diffInDays($export->created_at);
if ($elapsed > 7) { /* 기한 초과 */ }

created_at 기준으로 경과일을 재는 자리가 있었다.

created_at   3월 2일
재발송       3월 14일
경과일 계산  → 12일

재발송 직후인데 elapsed 가 12일이라 이미 기한 초과로 잡힌다.

덮어쓰기 설계 때문에 created_at 이 가장 최근 출고 시점이 아니게 됐고 그것을 기준으로 재는 계산이 전부 틀어졌다.

grep -rn "export->created_at\|exports.created_at" app/

created_at 을 쓰는 자리를 전부 찾아 그 뜻이 유효한지 확인했다.

덮어쓰기가 있는 표에서 그 컬럼은 최초 생성이지 최근 동작이 아니다. 한 곳의 설계 선택이 무관해 보이는 곳을 깬다.

정리


Share this post on:

Previous Post
외부 시스템의 성공 응답을 그대로 믿지 않게 된 이유
Next Post
두 벌 중 하나 고르기