Skip to content
isdnetworks
Go back

같은 값을 바꾸는 두 경로, 결과는 다르다

배송 정책의 값 하나를 고쳐야 했고 화면에서 고치는 방법과 DB에서 직접 고치는 방법이 있었다. DB가 빠르니 그것을 골랐고 값은 바뀌었는데, 화면 경로가 하는 일을 코드로 읽어 보니 값 저장 말고 셋이 더 있었다.

Table of contents

Open Table of contents

화면 경로가 함께 하는 셋

화면에서 저장하면 수정되었다는 이력을 남기고 그 정책에 연결된 계정 상태를 갱신 필요로 바꾸고 외부 마켓으로 보내는 전파 작업을 큐에 넣는다.

DB로 직접 고치면 이 셋이 전부 안 일어난다. 이력도 없고 계정 상태도 그대로이고 외부에는 옛 값이 남는다. 내부 값만 조용히 바뀐 상태가 되고 그 조용함이 나중에 다른 증상으로 돌아온다.

선택의 축

이걸 알고 나니 두 경로가 빠른 쪽과 느린 쪽의 차이가 아니었다. 외부에 반영돼야 하면 전파 작업이 생기는 화면 경로를 써야 하고, 내부 값만 조정하고 전파를 피해야 하면 DB 직접 경로가 맞다.

무엇을 고칠 것인가가 아니라 전파를 일으킬 것인가가 선택의 축이었다. 축을 잘못 잡으면 빠른 쪽을 고르는 것이 항상 합리적으로 보인다.

주석 처리된 가드

더 헷갈렸던 것이 있다. 그 화면 코드에 차단 조건이 둘 있었는데 둘 다 주석 처리돼 있었다.

// return '일주일 이내 재수정 할 수 없습니다';
// if ($manager->is_provider) abort(403);

코드만 훑으면 화면에서 수정이 막혀 있으니 DB로 해야 한다고 읽기 쉬운데 실제로는 열려 있다. 그리고 운영에는 정책을 수정하지 말고 새로 만들어 연동하라는 규칙이 있었다. 이것은 코드가 강제하는 제약이 아니라 그 전파를 피하려고 사람이 세운 가드였다. 코드가 막는 것과 사람이 안 하기로 한 것을 구분하지 않으면 어느 쪽도 정확히 읽히지 않는다.

반대 방향의 사례

삭제가 연쇄를 일으키는 경우도 봤다. 중복 반품을 정리하려고 DB에서 지우려 했는데 화면의 삭제 버튼은 단순 삭제가 아니었다. 하위 항목을 지우고 남은 것이 없으면 상위도 지우고 연관 상태를 이전 값으로 복원하고 상위 상태를 재계산하고 이력을 남기고 이벤트를 발행한다. DB로 지우면 그 여섯이 안 일어나고 데이터가 어긋난 채 남는다.

저장 함수가 삽입이 아닌 경우도 있었다. 작업을 하나 만든다고 생각한 함수가 실제로는 상위 레코드를 먼저 만들고 그 안에서 기존 것을 찾으면 조용히 건너뛰었다. 기존 것을 안 지우고 부르면 오류 없이 아무 일도 일어나지 않는다.

고치기 전에 보는 것

그 값을 바꾸는 정식 경로가 하는 일을 코드로 읽는다. 저장 말고 무엇이 더 일어나는지 보면 대개 이력과 연관 상태와 외부 전송 중 하나 이상이 나온다.

부수효과가 필요한지 정하고 그 선택을 기록에 남긴다. 필요하면 정식 경로를 쓰고 필요 없으면 직접 경로를 쓰되, 직접 경로를 골랐으면 빠진 부수효과를 목록으로 만든다. 나중에 왜 이력이 없느냐는 물음이 나왔을 때 답할 수 있어야 한다.

정리


Share this post on:

Previous Post
0건이 증명하는 것은 무엇인가
Next Post
결과를 만든 확인 행위