Skip to content
isdnetworks
Go back

버그로 보이는 조용한 무시

(수정됨)

프로모션이 걸린 상품의 가격 수정이 실제로 막히는지와 막힌다면 무엇을 돌려주는지를 확인해 달라는 요청을 받았다. 경로를 따라가 보니 세 계층에서 모두 막고 있었고 그중 둘은 아무것도 돌려주지 않았다.

Table of contents

Open Table of contents

상황 — 세 계층에 중복된 보호

첫째는 products 에서 channel_products 로 값을 전파하는 syncPrice() 였는데 프로모션이 살아 있으면 넘어온 price 를 하위의 기존 값으로 되돌린다. 둘째는 저장 직전의 ChannelProductRequest 이고 price 와 discount_rate 를 요청 데이터에서 unset() 으로 통째로 제거해 데이터베이스까지 가지 않게 한다.

셋째는 Vue 화면이며 가격 입력과 할인 토글이 disabled 가 되고 적용된 프로모션 목록이 함께 표시된다. 같은 보호가 여러 계층에 중복돼 있으므로 각각이 어디서 막는지를 분리해 봐야 어느 경로에 안내가 빠졌는지가 드러난다.

원인 — 오류 없이 값만 안 바뀌는 처리

앞의 두 계층은 오류도 경고도 내지 않으므로 저장 요청이 성공하고 응답도 200 으로 돌아온다. 바뀌는 것은 값뿐이고 그 사실을 알릴 통로가 없다.

되돌리기와 unset() 은 둘 다 예외를 발생시키지 않는 방식이라 호출자가 실패를 감지할 수단이 없다. 화면 계층만 disabled 로 상태를 보여 주므로 그 경로를 타지 않는 사용자에게는 아무 단서가 없다.

증상 — 사용자 눈에 남는 것

담당자가 products 화면에서 discount_rate 를 바꾸고 저장하면 성공 응답을 받는다. 그 뒤 channel_products 화면을 열면 값이 그대로이므로 반영이 안 된다고 인식한다.

몇 번 더 시도해도 같은 결과라 결국 문의로 이어진다. 정상 동작인데 문의가 발생하는 것이 이 구조의 실제 비용이었다.

결론 — 로직이 아니라 안내가 빠진 문제

확인 요청의 답은 막힌다는 것이었지만 거기서 끝내면 요청자가 다음에 무엇을 할지 정할 수 없다. 막는 것은 맞고 왜 막혔는지를 알려 주지 않는 것이 문제였다.

두 가지 방법이 있었는데 syncPrice() 가 되돌릴 때 422 로 거절하게 바꾸는 것과 차단 규칙은 그대로 두고 응답에 skipped_fields 와 사유를 실어 화면이 안내 문장을 띄우게 하는 것이다. 뒤쪽을 골랐다. 이유는 배치가 같은 경로를 타므로 거절로 바꾸면 밤마다 프로모션 상품 수만큼 실패가 쌓여서다. 대신 저장이 성공했는데 일부 필드는 무시됐다는 두 겹의 상태를 화면이 표현해야 하는 것을 감수했다. 필요한 것은 프로모션이 진행 중이면 가격 수정이 적용되지 않는다는 문장 하나이지 로직 수정이 아니었다.

사용자가 없던 코드에 사용자가 생길 때

이런 조용한 처리가 어떻게 생기는지는 짐작이 된다. syncPrice() 를 만들 때는 프로모션 값을 지켜야 한다는 것만 생각하고 그 코드가 배치에서만 돌기 때문이다.

나중에 화면에서 상위 상품 수정 기능이 열리면 같은 코드를 사람이 타게 된다. 배치용으로 만든 조용한 처리가 사용자 경로에 노출되는 순간부터 그것은 결함으로 읽힌다.

정리


Share this post on:

Previous Post
이미 빠진 것의 이중 차감
Next Post
스냅샷과 근본 원인