은행 현장의 언어 · 일마감과 계정일자 · 이론
은행의 하루는 자정에 끝나지 않는다
한 줄 요약
은행 시스템에는 시계가 가리키는 시각과 장부가 인정하는 날짜가 따로 있고, 그 둘이 벌어져 있는 동안 들어온 거래를 어느 날짜에 잡느냐가 사고의 대부분을 만든다.
왜 이게 필요했나
일반적인 시스템에서 "오늘" 은 date 명령이 알려 주는 값입니다. 자정이 지나면 날짜가 바뀌고, 그걸로 끝입니다.
은행에서는 그렇지 않습니다. 어제의 거래를 모두 모아 계정별로 집계하고, 이자를 붙이고, 대외 기관과 정산하고, 감독 기관에 낼 자료를 만드는 일마감(EOD, End of Day) 배치가 돌아야 하루가 끝납니다. 이 배치는 보통 밤 10시쯤 시작해 새벽까지 돕니다. 그동안에도 ATM 은 돌고 인터넷뱅킹은 열려 있습니다.
그래서 은행 시스템에는 두 개의 날짜가 있습니다.
시스템 시각(posted_at) 실제로 그 거래가 들어온 순간. 서버 시계가 찍는다.계정일자(biz_date) 그 거래가 어느 날 장부에 속하는가. 마감 배치가 끝나야 넘어간다.새벽 1시에 들어온 이체가 계정일자로는 어제일 수 있고, 밤 11시에 들어온 이체가 계정일자로는 내일일 수 있습니다. 이 두 값을 헷갈리는 것이 은행 현장에 처음 들어간 엔지니어가 가장 자주 하는 실수입니다.
어떻게 동작하나
하루의 순서는 대략 이렇습니다.
09:00 계정일자 = 2026-08-25. 온라인 거래가 biz_date=2026-08-25 로 들어온다.22:10 마감 컷오프. 이 시각 이후 유입분은 biz_date=2026-08-26 으로 찍혀야 한다.22:10 마감 배치 시작. biz_date=2026-08-25 인 거래를 집계한다.22:40 마감 완료. 계정일자를 2026-08-26 으로 전진시킨다.핵심은 마감 대상을 시스템 시각이 아니라 계정일자로 고른다는 것입니다. WHERE posted_at BETWEEN ... 으로 마감 대상을 잡는 코드는 반드시 언젠가 틀립니다.
여기서 두 가지가 어긋날 수 있습니다.
하나, 컷오프 이후 유입분의 계정일자. 온라인 채널이 마감 상태를 읽지 않고 계속 옛 계정일자를 찍으면, 내일 거래가 오늘 장부에 들어갑니다. 그 거래를 나중에 익일자로 옮기려면 이미 만들어진 마감 산출물에서 빼내야 하는데, 산출물은 이미 대외 기관에 나갔을 수도 있습니다.
둘, 마감 배치가 죽었을 때의 재수행. 배치가 절반쯤 돌다 죽으면 일부 거래만 반영된 상태가 남습니다. 이 상태에서 배치를 다시 던지면 두 가지 중 하나가 됩니다. 이미 반영된 것을 또 더하면 이중 반영이고, 어디까지 갔는지 몰라 아무것도 안 하면 누락입니다.
그래서 마감 배치는 멱등(idempotent) 해야 합니다. 같은 계정일자에 대해 몇 번을 돌려도 결과가 같아야 한다는 뜻입니다. 멱등성을 만드는 방법은 크게 둘입니다.
증분 방식 아직 반영 안 된 것만 골라 기존 산출물에 더한다. 빠르지만 '이미 반영된 것이 전부 옳다' 를 전제한다. 잘못 들어간 것을 빼낼 수단이 없다.전량 재계산 해당 계정일자의 산출물을 통째로 지우고 처음부터 다시 만든다. 느리지만 이전 실행이 어디까지 갔는지에 의존하지 않는다.일마감처럼 하루에 한 번 도는 배치에서는 거의 언제나 전량 재계산이 정답입니다. 계산량은 하루치이고, 얻는 것은 "언제 다시 돌려도 안전하다" 는 성질입니다.
현장에서 만나는 모습
첫째, "어제 거래인데 오늘 잡혔다" 는 문의는 대개 컷오프 문제입니다. 고객은 시계를 보고 말하고 시스템은 계정일자로 답합니다. 조사할 때 두 값을 나란히 뽑아 보여 주는 것만으로 끝나는 경우가 많습니다. 반대로 두 값을 구분하지 않고 "시스템이 이상하다" 고 보고하면, 그건 정상 동작을 사고로 올린 것이 됩니다.
둘째, 마감이 죽었을 때 가장 위험한 상태는 전표의 한쪽만 반영된 상태입니다. 복식부기라 하루치를 온전히 집계하면 차변과 대변이 상쇄돼 잔액 합이 0 이 나옵니다. 그런데 배치가 전표의 차변 줄을 반영하고 대변 줄을 반영하기 전에 죽으면 이 합이 0 이 아닙니다. 이 숫자 하나가 "마감이 어중간하게 끊겼다" 를 알려 주는 가장 빠른 신호입니다.
셋째, 마감 배치가 대상을 실행 중 조회로 잡으면 마감이 도는 동안 들어온 거래가 딸려 들어갑니다. 22:10 에 시작한 배치가 22:12 에 조회를 돌리면 그 사이 2분간 들어온 거래가 조회 결과에 포함됩니다. 대상은 시작 시점의 계정일자로 고정해야 합니다. 이 버그는 평소에는 아무 일도 안 일으키다가, 마감이 오래 걸리는 날이나 재수행하는 날에만 드러납니다.
넷째, 마감 확정과 산출물 생성은 다른 일입니다. 집계 결과를 만들어 놓고 계정일자를 전진시키지 않으면 온라인 채널은 계속 옛 날짜를 찍습니다. 반대로 계정일자만 넘기고 산출물이 없으면 다음 날 조회가 빈 값을 받습니다. 두 가지를 한 트랜잭션 안에서 끝내거나, 순서와 실패 시 행동을 문서로 정해 두어야 합니다.
다음 실습에서 할 것
2026-08-25 일마감 배치가 22:10 에 시작해 도중에 죽은 상태를 그대로 만들고, 거기서 복구합니다. 240줄 중 153줄만 반영된 상태를 파악하고, 마감이 도는 동안 계정일자가 잘못 찍힌 18줄을 찾아 익영업일로 옮기고, 증분 재수행이 왜 이 상황에서 성립하지 않는지를 숫자로 보인 뒤, 전량 재계산 스크립트를 만들어 두 번 돌려도 결과가 같음을 증명합니다.