기술

월간 검수 배치는 매달 성공했는데, 판정 창 밖 누락 1,356건은 한 번도 안 봤습니다

2026.10.069분 읽기

B2B 채권 분석 시스템에는 월간 검수 배치가 하나 돌고 있습니다. 계좌마다 최상위 상태가 적히는 마스터 원장과, 그 아래 붙는 회차별 변제 계획표가 서로 다른 경로로 갱신되기 때문입니다. 두 쪽이 어긋나면 사람이 손으로 맞춰야 하고, 그 어긋남을 찾아 리포트로 내는 것이 이 배치의 일입니다.

이번 작업은 그 검수에 항목을 하나 더하는 일이었습니다. '마스터 원장은 실효인데 최신 계획표에는 실효·종결 표시가 없는 건'을 찾는 항목입니다. 규칙이 명확해서 반나절이면 끝날 줄 알았습니다.


리스트를 뽑았더니 네 자리였습니다

구현을 마치고 운영 쪽에서 목록을 뽑았습니다. 한둘을 예상했는데 1,356건이 나왔습니다. 그중 계좌 참조가 아직 살아 있어 바로 조치해야 하는 것이 456건이었습니다.

그 순간 질문이 바뀌었습니다. 몇 건인가가 아니라, 왜 여태 안 잡혔나였습니다. 같은 종류의 어긋남을 보는 배치가 이미 매달 돌고 있었기 때문입니다. 이 시스템을 몇 년째 돌렸는데 네 자리가 쌓여 있었다는 것은, 그 배치가 이 건들을 한 번도 보지 않았다는 뜻입니다.


판정 창이 직전 달까지였습니다

기존 배치의 판정 조건을 열어 봤습니다. 실효일이 '기준월 − 1개월 ~ 기준월' 안에 있는 건만 대상이었습니다. 이번 달에 실효 처리된 계좌를 이번 달에 확인한다는 뜻이고, 월간 검수로는 자연스러운 범위입니다.

문제는 그 창을 한 번 벗어난 건입니다. 이번 달 리포트에서 사람이 못 보고 넘긴 건은 다음 달에 더 오래된 건이 됩니다. 창에서 더 멀어질 뿐 돌아오지 않습니다. 한 번 새어나가면 어느 회차도 다시 보지 않는 영구 누락이 됩니다.

판정 창이 매달 오른쪽으로 이동하면서 창 왼쪽으로 밀려난 누락 건이 영영 다시 조회되지 않는 구조


실패처럼 보이지 않는 고장이었습니다

이 배치는 에러를 낸 적이 없습니다. 매달 성공으로 끝났고 리포트도 정상으로 나왔습니다. 모니터링에 걸릴 구석이 없었습니다.

결과물에서 두 가지가 똑같이 보였기 때문입니다. 아직 안 본 것과, 보고 이상이 없는 것입니다. 리포트에 안 적힌 계좌를 보면 사람은 깨끗하다고 읽습니다. 실제로는 대상에서 빠져 있었을 뿐입니다.

그래서 주기 배치를 설계할 때 질문 하나를 먼저 던지게 됐습니다. 이 배치가 지난달에 한 건을 놓쳤다면, 그 건은 언제 잡히는가. 답이 영영이면 창이 틀린 것입니다. 매달 돈다는 말과 언젠가는 다 본다는 말은 같은 말이 아닙니다.


고치려고 보니 취합 구조가 규모를 깎고 있었습니다

항목을 더하면서 리포트 전체를 같이 봤습니다. 기존 리포트는 항목 시트가 순서대로 늘어선 모양이었고, 앞 항목에 걸린 계좌는 뒤 항목 시트에서 빼는 구조였습니다. 같은 계좌를 두 번 건드리지 않게 하려는 의도였고, 조치하는 사람 입장에서는 시트 순서대로 돌면 되니 편합니다. 이 구조를 '배타 사슬'이라고 부르겠습니다.

문제는 그 방식이 통계까지 같이 깎는다는 것입니다. 이 항목이 몇 건인가를 물으면 시트의 행 수가 답인데, 그 수는 앞 항목에 얼마나 빠졌는지에 따라 달라집니다. 항목의 심각도를 잴 근거가 사라집니다.

배타 사슬 유지

전수 + 종합 시트

중복 조치 방지

앞 항목에 걸린 계좌를 뒤 시트에서 뺀다

시트에는 다 두고 맨 앞 시트가 우선순위를 보여준다

항목 시트의 성격

아직 안 걸린 것만 — 전수가 아니다

전수

그 항목의 진짜 규모

못 센다

그대로 나온다

조치자의 동선

시트 순서대로 돈다

맨 앞 한 장을 먼저 본다


목록은 전수로 두고, 순서는 층을 따로 얹었습니다

전수로 두고 종합 시트를 얹는 쪽을 골랐습니다. 중복 조치를 막는 책임을 거르기에서 보여주기로 옮긴 것입니다.

각 항목 시트는 그 항목의 전수로 둡니다. 이 어긋남이 지금 몇 건인가에 그대로 답합니다

맨 앞에 종합 시트를 붙입니다. 계좌당 한 행이고, 그 계좌에 걸린 항목들을 정해진 조치 순서대로 이어 붙입니다. 앞에 오는 것이 먼저 손댈 항목입니다

조치하는 사람은 종합 시트를 따라가고, 분석하는 사람은 항목 시트를 셉니다. 두 독자의 요구가 서로를 깎지 않습니다

규격 통일은 이 결정에 따라온 작업입니다. 모든 행을 다섯 칸으로 맞췄습니다. 계좌 키, 조정 번호, 유형, 검수 항목, 메모입니다. 유형별로 갈라 두던 시트 둘은 유형이라는 칸 하나로 접혔고, 성격이 같은 중단 미반영 항목 넷은 한 시트로 모았습니다. 시트가 전수가 되면 시트 수가 늘어날 텐데, 행 모양이 같으면 시트를 합치고 나누는 비용이 싸집니다.

앞 항목이 잡은 계좌를 뒤 시트에서 빼는 구조와 모든 시트를 전수로 두고 종합 시트를 앞에 붙인 구조의 비교


오늘 기준과 회차 기준을 섞지 않습니다

같이 손본 항목이 하나 더 있습니다. 미상각 여부를 보는 항목이 판정 기준일을 오늘 날짜로 잡고 있었습니다. 회차가 기준월 단위로 도는 데이터인데 기준시각만 오늘이었습니다.

이러면 같은 데이터에 같은 배치를 돌려도 돌린 날에 따라 답이 달라집니다. 월말에 돌린 결과와 다음 달 3일에 돌린 결과가 다르면, 그건 검수 결과가 아니라 실행 로그입니다. 기준월이 있는 도메인에서는 기준월 말이 시계입니다. 판정 기준을 기준월로 바꿨고, 종결 판정 목록에 빠져 있던 코드 하나도 같이 더했습니다.


창을 넓히는 결정에는 짝이 있습니다

창을 넓히는 것은 공짜가 아닙니다. 전 구간을 보면 이미 조치를 끝낸 건이 매달 다시 올라옵니다. 조치 이력을 남기는 자리가 없으면 넓힌 창이 곧 소음이 되고, 사람이 리포트를 안 보게 됩니다. 창을 넓히는 결정과 조치했음을 기록하는 결정은 한 쌍입니다. 뒤쪽 없이 앞쪽만 하면 두 달 뒤에 원래대로 돌아갑니다.

배타 사슬이 맞는 경우도 있습니다. 조치가 실제로 서로 배타적이고, 하나를 고치면 나머지가 자동으로 사라지고, 항목별 규모 집계가 필요 없는 운영이라면 거르기가 더 싸고 단순합니다. 이 사례에서 전수 쪽이 이긴 이유는 항목별 규모가 곧 의사결정 근거였기 때문입니다. 종합 시트도 한계가 있습니다. 계좌 하나에 걸린 항목이 열 개씩 되면 한 행이 길어져 오히려 못 읽습니다. 그때는 가장 앞선 항목 하나와 나머지 개수로 접는 편이 낫습니다.

그리고 판정 창이 좁은 것이 의도인 배치도 있습니다. 실시간 알림처럼 최근 것만 알면 되는 일이 그렇습니다. 문제는 검수와 정합성 점검이 그 모양으로 짜였을 때입니다. 둘은 이름이 비슷해서 같은 틀로 만들어지기 쉽습니다.

주기 배치의 판정 창을 설계할 때 확인하는 네 가지 질문을 체크 목록으로 정리한 그림


주기 작업을 맡기기 전에 확인하는 것

정합성 점검을 자동화해 두면 그 뒤로는 사람이 결과만 봅니다. 그래서 창이 어디까지인지가 운영 기간 내내 조용히 영향을 줍니다. 비슷한 배치를 두고 있다면 아래 네 가지를 한 번 확인하는 편이 좋습니다.

이 배치가 지난 회차에 한 건을 놓쳤다면, 그 건은 어느 회차에 다시 대상이 되는가. 답이 없으면 창을 다시 잡습니다

리포트에 안 적힌 대상이 점검을 통과한 것인지, 애초에 대상이 아니었던 것인지 결과물에서 구분되는가

항목별 건수를 보고 우선순위를 정하고 있다면, 그 수가 다른 항목에 걸러진 뒤의 수가 아닌지 확인합니다

판정 기준시각이 실행 시점인지 회차 기준인지 확인합니다. 재실행해서 같은 답이 나오는지 한 번 돌려 보면 드러납니다

같은 시스템에서 월간 재판정을 다루다 겪은 반대 방향의 사고도 있습니다. 판정 범위를 넓게 잡고 매달 다시 재다가, 조치 이력이 없는 상태에서 지난 판정이 지워진 경우입니다. 창을 넓히는 결정과 이력을 남기는 결정이 한 쌍이라고 적은 근거가 그쪽에 있습니다.

검수 결과를 사람이 눈으로 확인할 때 어떤 대상을 고르는지도 같은 종류의 문제입니다. 표본 하나로 통과를 선언하면 영향 범위를 못 봅니다.

이번 작업에서 가장 오래 걸린 부분은 항목을 구현하는 일이 아니었습니다. 1,356건이 왜 여태 리포트에 없었는지를 설명하는 일이었습니다. 검수 배치는 멀쩡했고, 멀쩡한 채로 보지 않고 있었습니다.

#배치설계#판정창#누락탐지#데이터정합성#검수리포트