기술

막으려던 누수는 0.62%, 그 필터가 같이 버린 건 85.7%였습니다

2026.09.268분 읽기

'어떤 매장의 7월 발주 GAP 이 +64.1% 과다로 뜹니다'라는 제보가 왔습니다. 프랜차이즈 ERP 를 운영하다 보면 흔히 오는 종류의 제보입니다. 그런데 그 매장은 본사 물류 발주가 6월부터 끊긴 곳이었습니다. 발주가 거의 0이면 과소(−)가 나와야 정상인데 부호가 정반대였습니다.

크기가 이상한 것과 부호가 반대인 것은 다른 종류의 문제입니다. 부호가 뒤집히는 건 정의나 필터가 잘못됐을 때입니다. 그래서 값을 튜닝하지 않고 계산식부터 열었습니다. 3시간 만에 결함이 셋 나왔습니다.


지표가 무엇을 견주는지부터 적어둡니다

발주 GAP 은 두 금액을 견줍니다. 한쪽은 매장이 본사 물류로 넣은 발주액입니다(이하 발주 쪽). 다른 한쪽은 POS 매출에 메뉴별 레시피를 곱해 낸 이론 소요액입니다(이하 소요 쪽). 발주가 이론보다 많으면 과다(+), 적으면 과소(−)로 판정합니다.

과다는 로스나 유용 신호이고, 과소는 물류를 안 쓰고 밖에서 사 오는 신호입니다. 부호가 틀리면 엉뚱한 매장이 경고 목록에 오릅니다.


양쪽 집계에 같은 필터가 걸려 있었습니다

발주 쪽과 소요 쪽 집계의 WHERE 절을 나란히 놓았습니다. 양쪽 모두에 '그 매장이 계약한 브랜드의 품목만'이라는 조건이 있었습니다. 문제는 그 조건이 무엇을 통과시키고 무엇을 떨어뜨리는지였습니다.

WHERE 브랜드 IN (계약 브랜드)   -- 브랜드가 NULL 이면 UNKNOWN → 행이 빠진다

외부 공급사 시스템에서 넘어오는 전족·후족·삼겹살 같은 축산 품목은 여러 브랜드가 함께 쓰는 공용 품목입니다. 공용이라서 브랜드 식별자 컬럼이 비어 있습니다. NULL IN (...) 은 SQL 3값 논리에서 거짓이 아니라 UNKNOWN 이고, WHERE 절은 UNKNOWN 인 행을 버립니다.

그래서 축산이 발주 쪽에서도 소요 쪽에서도 한 건도 안 잡혔습니다. 하필 그 브랜드는 축산 품목이 주재료였습니다. 주재료가 빠진 채 남은 부재료끼리 견주니 발주 쪽이 더 컸고, 그래서 +64.1% 가 나왔습니다.

브랜드 스코프 필터가 브랜드가 NULL 인 공용 축산 품목을 발주·소요 양쪽 집계에서 떨어뜨리는 구조


막으려던 것과 버린 것을 같이 셌습니다

이 필터는 원래 '다른 브랜드 품목이 섞여 들어오는 것'을 막으려고 걸렸습니다. 그렇다면 막는 양과 버리는 양을 세면 됩니다. 조건을 뺀 집계를 브랜드별로 한 번 돌렸습니다. 단일 브랜드 매장 270여 곳의 7월 소요 쪽 기준입니다.

구분

금액

비중

공용 축산 품목(브랜드 비어 있음)

14.1억

85.7%

계약 브랜드 품목

2.3억

13.7%

다른 브랜드 품목(막으려던 것)

0.1억

0.62%

막으려던 것이 0.62%, 그 필터가 같이 버린 것이 85.7% 였습니다. 138배입니다. 이 집계 한 번이 결론을 정했습니다. 필터를 걸 때 앞의 수만 봤고, 뒤의 수는 아무도 세지 않았습니다.

그 0.62% 도 다시 봤습니다. 대부분은 그 매장이 실제로 파는 사이드 메뉴의 재료였습니다. 재료가 다른 브랜드 접두가 붙은 품목에 물려 있을 뿐, 소진 자체는 진짜였습니다.

걱정하던 이중계상은 실측 0건이었습니다. 두 브랜드의 같은 이름 품목이 외부 공급사 시스템에 애초에 다른 코드로 등록돼 있었습니다.

막으려던 누수 0.62%와 같이 버린 공용 품목 85.7%의 138배 대비


원래 요구는 계산이 아니라 표시였습니다

처음 들어온 불만은 '목록에 저 브랜드 품목이 왜 뜨냐'였습니다. 화면에 안 보이게 해달라는 뷰 계층의 요구였습니다. 그 요구에 집계 쿼리의 WHERE 절로 답한 것이 화근이었습니다. 화면은 조용해졌고 지표만 틀렸습니다.

'양쪽에 같은 필터를 걸었으니 비율은 유지된다'는 생각도 틀렸습니다. 두 집계의 구성이 다르면 필터가 남기는 잔여의 성격도 다릅니다. 여기서는 양쪽 잔여가 서로 다른 품목군이었습니다. 필터가 대칭이어도 결과는 대칭이 아니었습니다.


같은 3시간에 나온 나머지 둘

두 번째 결함은 조인 열쇠였습니다. POS 메뉴명과 마스터 매핑을 상품명 정확일치로 붙이고 있었습니다. 대표 메뉴가 POS 쪽에는 띄어쓰기가 있고 매핑 쪽에는 붙어 있었습니다.

띄어쓰기 한 칸에 주력 메뉴가 통째로 소요 쪽에서 빠졌습니다. 그 매장의 미연결 금액 가운데 6할이 이것이었습니다.

열쇠를 이름에서 코드값으로 바꾸기 전에 판별력을 실측했습니다. 여러 상품에 같이 붙는 조합이 코드만으로는 774건이었습니다. 코드+브랜드로 좁히니 144건이었고, 코드+이름도 144건, 셋을 다 쓴 것도 144건이었습니다. 브랜드는 코드값이라 표기가 흔들리지 않는데, 판별력은 이름과 정확히 같았습니다.

남은 144건은 세트메뉴라 어느 열쇠로도 안 갈리고, 갈리면 안 되는 것들이었습니다. 열쇠를 바꾸자 전사 커버리지가 57.0% 에서 76.3% 로 올라갔습니다.

세 번째 결함은 경고 자체였습니다. 레시피 대상 여부 컬럼은 Y/N/빈값 3값입니다. 그런데 '미분류' 경고가 빈값만 셌습니다. N 으로 분류된 품목은 흔적 없이 사라졌습니다.

7월 전사 물류 발주 가운데 Y(43품목)만 지표에 잡혔고, N(271품목)은 금액으로 3분의 1이 넘는데도 조용히 제외되고 있었습니다.

봉투나 용기처럼 제외가 맞는 것도 있습니다. 그런데 장족(매출이 크고 매장도 많은 품목)처럼 레시피가 있어야 하는데 없는 것이 섞여 있었습니다.

그리고 그걸 볼 수 있던 창이 닫혀 있었습니다. 재료 관리 화면의 '레시피 제외' 필터 옵션이 한 달쯤 전에 제거돼 있었습니다. 값은 계속 쓰이는데 걸러서 볼 방법만 없어져 아무도 못 찾았습니다.

이 결함은 고치지 않았습니다. 제외가 맞는 품목과 아닌 품목이 섞여 있어 판단이 업무 쪽에 있습니다. 대신 경고를 둘로 갈랐습니다. '분류하라'(미분류)와 '그 분류가 맞나 보라'(제외됨)는 다른 경고입니다. 지워져 있던 필터 옵션도 복원했습니다.


88건이 뒤집혔습니다

두 결함을 고치고 7월 전 매장을 다시 돌렸습니다. 판정이 과다에서 과소로 바뀐 매장이 88곳이었습니다. 평균 |GAP| 은 60.1% 에서 39.1% 로 내려왔습니다.

±10% 적정 밴드 안의 매장은 24곳에서 38곳으로 늘었고, 50% 를 넘는 강조 대상은 87곳에서 71곳으로 줄었습니다. 경고가 줄어든 것이 아니라 엉뚱한 곳을 가리키던 것이 제자리로 갔습니다.

제보 매장은 +64.1% 과다에서 −80.5% 과소로 뒤집혔습니다. 실제로 그 매장의 축산 발주는 2~5월 월 8백만 원대였다가 6월부터 0이었습니다.

반대 방향으로 부호가 넘어간 매장도 5곳 있었는데, 전부 ±10% 밴드 안이었습니다. 큰 음수가 0 근처로 수렴하다 부호만 넘어간 것으로, 한 곳은 −53.9% 에서 +1.9% 였습니다. 반대로 틀린 게 아니라 맞게 수렴한 것입니다.

필터 수정 전후 7월 매장 판정 분포 변화 — 평균 GAP 60.1%에서 39.1%, 과다에서 과소로 88곳

88건이 뒤집히는 변경이라 배포 전 화면 확인을 조건으로 걸었습니다. 배포 뒤 제보 매장이 과소로 바뀐 것을 사람이 눈으로 확인했습니다.


필터를 걸기 전에 두 수를 셉니다

가져갈 것은 138배라는 배수가 아니라 양쪽을 세고 비교했다는 절차입니다. 다른 데이터에서는 막는 양이 더 클 수도 있습니다. 세는 데 든 것은 집계 쿼리 한 번이었습니다.

스코프 필터를 걸기 전에 막는 양과 버리는 양을 같이 셌는가

조건을 거는 컬럼의 빈값이 '공용'인지 '미입력'인지 아는가

'목록에 뜬다'는 표시 요구에 집계 필터로 답하고 있지 않은가

경고가 '모르는 것'만 세고 '잘못 분류된 것'은 놓치고 있지 않은가

읽기 전용 진단 필터를 정리 대상으로 지우고 있지 않은가

부호가 반대인 지표는 값을 튜닝하지 않고 정의를 뒤집어 봅니다. 방향이 반대면 거의 항상 필터·조인·정의 쪽입니다. 고친 뒤에는 '어디가 어떻게 움직였나'를 분포로 보고합니다. 그래야 받는 쪽이 그 변경이 개선인지 사고인지를 스스로 판단할 수 있습니다.

지표가 에러 없이 조용히 틀리는 일은 이번이 처음이 아닙니다. 세 경로로 모은 매출 합계가 늘 1.37% 어긋났던 것도 원천에서 빠진 항목이 원인이었습니다.

#SQL#NULL처리#3값논리#지표설계#데이터품질#조인키#경고설계#운영의기술