LabHub
배우기 러닝패스 코스

보험 도메인 심화 · 보험료 일할계산과 환급 정합성 · 이론

환급액이 1원 다른데 두 시스템 다 맞다고 한다

LabHub 에서 이어서 보기

한 줄 요약

중도 해지 환급액은 "연보험료 곱하기 미경과일수 나누기 총일수" 한 줄처럼 보이지만, 일수를 세는 기준과 끊는 자리와 구간을 나누는 방식이 각각 다른 답을 만든다. 세 가지를 정책으로 못박고 계산 경로를 하나로 모으는 것이 이 문제의 전부다.

왜 이게 필요했나

고객이 5월에 계약을 해지했습니다. 청구 시스템은 환급액 412,331원을 안내했고, 며칠 뒤 회계 시스템이 만든 정산 파일에는 411,982원이 적혀 있습니다. 349원 차이입니다. 두 팀을 불러 놓고 계산을 짚어 보면 양쪽 다 틀린 곳이 없습니다. 한쪽은 실제 달력 일수로 나눴고, 다른 쪽은 한 달을 30일로 세는 오래된 관행을 따랐습니다. 한쪽은 원 단위에서 반올림했고, 다른 쪽은 절사했습니다. 한쪽은 3월에 있었던 보장 변경을 반영해 기간을 둘로 쪼갰고, 다른 쪽은 계약 시점의 보험료로 전체 기간을 한 번에 계산했습니다.

이런 차이는 한 건에서는 몇백 원입니다. 그런데 매달 수천 건이 지나가면 대사 항목이 되고, 대사 항목은 누군가 매달 손으로 설명해야 하는 일이 됩니다. 그리고 고객이 물으면 "시스템마다 다릅니다" 라고 답할 수는 없습니다.

어떻게 동작하나

첫째, 일수를 세는 기준(day count convention). 실제 일수(actual/actual)는 달력 그대로 셉니다. 2월은 28일이거나 29일이고, 1년은 365일이거나 366일입니다. 30/360 은 모든 달을 30일, 1년을 360일로 보는 방식이라 채권 이자 계산에서 오래 쓰였고, 손으로 계산하던 시절의 단순함이 그대로 남은 것입니다. 두 방식은 같은 기간에 다른 일수를 줍니다. 파이썬의 [date 객체](https://docs.python.org/3/library/datetime.html)는 뺄셈으로 실제 일수를 바로 주고, 30/360 은 날짜 숫자를 손으로 조정해 만들어야 합니다.

기간의 끝을 정하는 일에도 함정이 있습니다. 2024년 2월 29일에 시작한 1년 계약의 만기일은 언제일까요. 2025년에는 2월 29일이 없습니다. [calendar 모듈](https://docs.python.org/3/library/calendar.html)의 monthrange() 로 그 달의 말일을 구해 당기는 것이 흔한 처리인데, 어느 쪽으로 당길지를 약관이 정해 두지 않았다면 두 시스템이 갈라지는 첫 지점이 됩니다. 날짜는 [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) 의 YYYY-MM-DD 로 주고받아 자리 순서 때문에 싸우는 일을 없앱니다.

둘째, 끊는 자리와 반올림 방식. 원 단위로 끊는다는 것까지는 쉽게 합의되지만, 0.5원을 올릴지 버릴지는 다릅니다. 보수적으로 절사하는 회계 관행과, 고객에게 불리하지 않게 반올림하는 청구 관행이 한 회사 안에 같이 있는 일이 흔합니다. 파이썬 [decimal 모듈](https://docs.python.org/3/library/decimal.html)의 quantize()ROUND_HALF_UP ROUND_DOWN 같은 모드를 명시적으로 고르게 합니다. 실수(float)로 계산하면 이 선택 자체가 무의미해집니다 — 0.5 가 애초에 정확히 0.5 가 아니기 때문입니다.

셋째, 구간 분리. 보장을 기중에 바꾸면 보험료도 그 날부터 달라집니다. 환급액은 변경 전후를 나눠 계산해 더해야 맞습니다. 그런데 나누면 반올림을 두 번 하게 되고, 구간마다 끊은 합은 전체를 한 번에 끊은 값과 1원씩 어긋납니다. 이것은 오류가 아니라 선택입니다. 구간마다 끊을 것인지, 끝에서 한 번만 끊을 것인지를 정하고 그 규칙을 적어 두어야 합니다.

계약기간 |-----------------------------------------|변경일           ^                 해지일 ^구간1    |-------|                          (옛 보험료)구간2            |-------------------------|(새 보험료)미경과분                              |----|  ← 이 겹침만 환급

현장에서 만나는 모습

차이를 마주쳤을 때 가장 쓸모없는 보고는 "349원 차이가 납니다" 입니다. 쓸모 있는 보고는 "349원 중 300원은 일수 기준, 49원은 반올림, 나머지는 구간 반영 여부" 입니다. 원인을 규칙 단위로 가르는 방법은 단순합니다. 한 시스템의 계산에서 규칙을 하나만 상대 쪽으로 바꿔 보고 결과가 달라지는지 봅니다. 세 규칙을 하나씩 토글하면 어떤 규칙이 이 계약에 실제로 영향을 주는지 나옵니다.

또 하나 자주 보는 것은 월납 계약의 분할입니다. 연보험료를 12로 나누면 대개 나머지가 남는데, 그것을 버리면 1년 치 청구 합계가 연보험료에 못 미치고, 모든 달에 올리면 넘칩니다. 어느 달에 1원을 더 붙일지까지 정해 두어야 청구 시스템과 수납 원장이 연말에 맞습니다. 앞 달부터 붙이는 회사도 있고 마지막 달에 몰아 붙이는 회사도 있는데, 어느 쪽이든 규칙이 있어야 합니다.

그리고 정정은 숫자만 바꾸는 일이 아닙니다. 어느 계산을 기준으로 삼기로 했는지, 그 결정으로 얼마가 움직이는지, 대상 계약이 몇 건인지가 한 장에 있어야 결재가 납니다. 차액만 적힌 목록은 두 번째 정정 때 쓸모가 없어집니다 — 출발점이 어디였는지 아무도 모르기 때문입니다.

실무에서 진짜 중요한 것

다음 실습에서 할 것

계약 60건과 기중 보장 변경 15건을 직접 만들고, 같은 해지 건을 실제 일수와 30/360 으로 각각 계산해 얼마나 갈라지는지 봅니다. 그다음 변경이 있는 계약을 구간으로 쪼개고, 구간마다 끊은 합과 한 번만 끊은 값의 차이를 세고, 월납 12분할이 연보험료와 정확히 맞게 만듭니다. 마지막으로 청구와 회계 두 경로를 나란히 돌려 계약별 차이의 원인을 규칙 단위로 지목하고 정정 목록을 냅니다.