핀테크를 위한 룰 엔진: 한도, 심사, 승인 결정
핀테크의 한도, 심사 기준, 승인 결정은 규제가 바뀔 때마다, 리스크 모델이 바뀔 때마다 함께 바뀌고, 서비스 코드에 박아 넣으면 감사에서 무너집니다. 이 규칙들을 어디에 둬야 하는지, 코드에 박아 넣은 방식이 왜 감사를 통과하지 못하는지, 배포 없이 한도를 바꾸는 방법.
한 고객이 화요일에 본인 인증을 마치고, 곧바로 자기 등급 한도를 넘는 금액을 보내려 합니다. 이 이체는 통과될까요? 한도가 이체 서비스 안의 상수로 박혀 있다면, 가령 18개월 전 지금은 퇴사한 누군가가 적어 둔 TIER1_DAILY_MAX 한 줄이라면, 솔직한 답은 "그 숫자가 무엇이든 그대로"입니다. 그 숫자가 컴플라이언스 팀이 문서로 약속한 한도와 지금도 맞든 아니든 상관없이요. 그리고 그 불일치는 보통, 감사관이 "그날 적용된 한도가 집행했어야 할 한도와 같다는 걸 이체 건건이 증명해 보라"고 요구할 때에야 드러납니다.
핀테크는 이런 결정으로 돌아갑니다. 한도, 승인, 차단. 그리고 두 가지가 이 결정들을 다른 도메인의 같은 로직보다 까다롭게 만듭니다. 규제가 바뀌면 규칙도 따라 바뀐다는 것, 그리고 하나하나가 나중에 해명을 요구받을 수 있다는 것입니다. 이 글에서는 이 규칙들을 어디에 둬야 하는지, 코드에 박아 넣은 방식이 왜 무너지는지, 특히 왜 감사를 통과하지 못하는지, 그리고 무슨 일이 있었는지 증명하는 기록을 잃지 않으면서 한도와 심사 기준과 승인 결정을 서비스 코드 밖으로 빼내는 방법을 다룹니다.
핀테크 결정이 다른 이유
룰이 많은 도메인은 대체로 한 가지 공통점이 있습니다. 로직이 사업상의 이유로 바뀌고, 언제 바꿀지도 개발이 아니라 사업 쪽이 정한다는 점입니다. 핀테크는 여기에 두 가지 압력을 더해 문제의 성격 자체를 바꿉니다. 그 전에, 이 결정들도 다른 곳과 똑같이 조합이 빠르게 불어나기 마련입니다. 쌓이고, 하나씩 보면 다 무해해 보입니다.
- 등급별 한도: 고객의 KYC 인증 등급에 묶인 일일·건별 한도입니다. 더 인증할수록 한도가 올라갑니다.
- 심사 기준: 신용점수, 소득, DTI 구간에 따라 승인·거부·조건부 중 하나로 가릅니다.
- 속도·이상거래 차단: 거래 패턴이 리스크 임계를 건드리면, 현재 한도와 무관하게 막습니다.
- 계좌 자격: 누가 계좌를 열거나 상품을 이용할 수 있는지를 지역, 상태, 제재 대상 스크리닝으로 가릅니다.
- 단계 상향(step-up): 결정이 추가 인증을 거친 뒤에만 진행되도록 하는 조건입니다.
이 중 하나하나는 주니어 개발자가 점심 전에 짤 수 있는 단일 조건입니다. 문제는 어디서나 그렇듯, 이것들이 한 요청에 같은 순간 한꺼번에 몰리고, 조합의 수가 아무도 따라잡지 못할 속도로 불어난다는 데 있습니다. 그런데 핀테크를 특별히 가혹하게 만드는 게 두 가지 있습니다.
첫째, 규칙이 바깥에서 바뀝니다. 한도는 우리가 바꾸고 싶을 때만 바뀌는 게 아닙니다. 규제 기관이 새 가이드라인을 내놓으면 거기에 맞춰 바꿔야 하고, 언제까지 바꿀지도 우리가 아니라 규제 기관이 정합니다. 그러면 이 변경은 우리 개발 일정이 아니라 컴플라이언스 마감에 맞춰 배포해야 합니다. 규제 기관에는 "다음 배포 때 넣겠습니다"라는 말이 통하지 않으니까요.
둘째, 모든 결정이 증거가 될 수 있습니다. 대부분의 도메인에서 지난 결정은 내려지는 순간 잊힙니다. 여기서는 몇 달 뒤에, 특정 고객이 특정 날짜에 왜 승인·거부·차단됐는지 정확한 사유를 제출하라고, 그리고 그 기록이 이후 수정되지 않았음을 보이라고 요구받을 수 있습니다. 규칙이 자주 바뀌는 것 하나라면 코드 안에서도 버틸 만합니다. 문제는 세 가지가 한꺼번에 온다는 데 있습니다. 자주 바뀌고, 그 시점을 우리가 아니라 규제 기관이 정하고, 게다가 한 번 내린 결정을 두고두고 책임져야 합니다. 이 셋이 겹치는 순간, 이 로직은 더 이상 코드 안에 둘 수 없습니다.
코드에 박아 넣은 방식, 그리고 감사에서 무너지는 지점
시작은 늘 그렇듯 이체나 심사 서비스 안의 if-else 블록입니다. 파일 맨 위에 임계값을 상수로 박아 두고 그걸로 분기하는 식이죠. 고객 등급이 1이면 일일 한도를 그 상수 값으로 묶고, 점수가 그 기준 아래면 거부합니다. 한도가 하나로 고정돼 있고, 그 값을 알아야 하는 사람도 그걸 맡은 엔지니어 한 명뿐이라면, 이렇게 두는 게 맞습니다. 이럴 때 플랫폼까지 동원하는 건 오히려 과한 설계입니다.
문제는 늘 같은 네 곳에서 터지는데, 규제 도메인에서는 그중 네 번째가 곧바로 감사에서 지적받는 사항이 됩니다.
변경할 때마다 배포가 필요하고, 규제 기관은 우리 배포 일정을 기다려 주지 않습니다. 규제로 정해진 한도 변경에는 날짜가 붙어 있고, 그 날짜가 우리 배포 주기와 맞는 경우는 드뭅니다. 한 줄짜리 임계 수정이 티켓이 되고, 리뷰가 되고, 배포가 됩니다. "법에서 규칙이 바뀐 날"과 "프로덕션에서 규칙이 바뀐 날" 사이의 간격은 우리가 해명해야 하는 간격입니다.
같은 임계값이 서비스마다 어긋납니다. 등급 1의 한도 값은 이체 서비스에만 있는 게 아닙니다. 한도를 넘으면 전송 버튼을 막는 모바일 앱에도 같은 값이 들어 있고, 한도 초과 건을 골라내는 야간 배치 작업에도 또 들어 있습니다. 같은 값이 세 곳에 복사돼 있으니, 하나만 고치고 나머지를 잊기도 그만큼 쉽습니다. 그러면 실제로 집행하는 한도, 화면에 보여 주는 한도, 모니터링하는 한도가 서로 다른 세 숫자가 됩니다.
결정이 왜 그렇게 나왔는지 아무도 복원하지 못합니다. 서비스는 "거부"를 돌려주고 넘어갔습니다. 어느 임계가 걸렸는지, 입력값이 뭐였는지, 어느 규칙 버전이 살아 있었는지, 무엇도 적히지 않았습니다. 고객이 결과에 이의를 제기하거나 감사관이 그 과정을 짚어 달라고 할 때, 남은 기록이라곤 오늘 시점의 코드뿐이고, 그건 그날 돌아간 코드가 아닐 수도 있습니다.
정작 정책을 소유한 사람은 손을 못 댑니다. 임계값을 정하는 건 리스크와 컴플라이언스이고, 그걸 배포할 수 있는 건 엔지니어링뿐입니다. 규제 기관 앞에서 책임지는 팀이 구조적으로 규칙을 직접 바꾸지 못하고, 바꿀 수 있는 팀에 요청을 넣어야 합니다. 그리고 그 모든 변경은 두 팀 사이의 번역이며, 오류는 바로 그 번역에서 끼어듭니다.
등급별 한도, 그리고 어긋나는 임계값
아무것도 아닌 것처럼 보이다가 전부가 되는 실패가 여기 있습니다. KYC 등급별 한도는 단순한 아이디어입니다. 더 인증하면 더 보냅니다. 등급 1은 일일 한도가 낮고, 등급 2는 더 높고, 등급 3은 더 높습니다. 이걸 상수로 적으면, 각 등급의 숫자는 처음 필요한 자리에 놓입니다. 그리고 같은 숫자가 다른 곳에서 또 필요해지면, 복사됩니다. 몇 달 뒤 그 사본 중 하나가 정책 변경으로 갱신되고 나머지는 그대로 남으면, 등급 2 고객이 무엇을 할 수 있는지를 두고 시스템의 답이 갈립니다.
여기서 팀들이 흔히 놓치는 교훈은 이것입니다. 한도는 숫자가 아니라 결정이고, 결정의 기준은 오직 한 곳에만 있어야 합니다. 버그는 한 곳의 값이 틀린 게 아닙니다. 같은 값이 서로 일치한다고 보장된 적 없는 여러 곳에 흩어져 있다는 것입니다. 제어 흐름에는 "이것들은 모두 같은 규칙이다"를 강제할 장치가 없습니다. 그저 우연히 맞아떨어지다가 어긋나는 상수들이 있을 뿐입니다.
구조적인 해법은 한도를 서비스마다 복제된 숫자가 아니라 하나의 규칙 집합의 속성으로 만드는 것입니다. 등급과 한도의 대응이 데이터가 되고(kyc_level이 한도를 결정합니다), 한도를 넘는 이체는 무언가 실패했다고만 말하는 예외가 아니라, 막힌 이유를 함께 담는 차단 규칙으로 멈춥니다. 한도가 필요한 모든 서비스가 같은 규칙 집합에 묻고 같은 답을 받습니다. 그리고 한도가 바뀔 때, 한 곳에서 바뀝니다.
규칙 정의 전체와 차단 동작, 그리고 엣지 케이스, 즉 정확히 한도에 걸렸을 때 어떻게 되는지, 대기 중인 이체가 일일 합계에 어떻게 잡히는지, 사유가 호출자에게 어떻게 전달되는지는 차단 규칙으로 KYC 등급별 이체 한도 집행하기 패턴에서 처음부터 끝까지 풀어 둡니다. 여기서 가져갈 한 가지는 이것입니다. 서비스마다 복제된 한도는 손으로 맞춰 두는 값이 아니라, 모든 서비스에서 끄집어내 하나의 규칙 집합에 모아야 하는 단일 결정이라는 것.
한도는 얼마까지인지를 정합니다. 한 단계 위에는 애초에 승인할지 자체를 정하는 결정이 있습니다. 대출이나 계좌 신청 하나가 승인·거부·조건부 중 하나로 돌아와야 한다면, 그건 같은 문제를 한 단계 더 끌고 간 것입니다. 여러 규칙이 하나의 결과를 두고 경합하고, 그중 정확히 하나만 이겨야 하며, 어느 규칙이 이겼는지 말할 수 있어야 합니다. 코드에 박으면 누구도 빠짐없다고 증명하지 못하는 분기 더미가 되지만, 규칙 집합으로 두면 하나의 규칙이 결정을 내리고 그 결정 기록이 어느 규칙인지까지 남기는 우선순위 그룹이 됩니다. 우선순위와 동점 처리, 그리고 조건부로 분류된 신청을 어떻게 표시하는지는 우선순위 상호 배타 그룹으로 신용 신청 판정하기 패턴에서 풀어 둡니다.
결정이 증거가 될 때
이커머스에서 잘못된 결정은 수익을 깎고, 월말에 발견됩니다. 규제 도메인에서는 결정이 옳았든 아니든, 기록되지 않은 결정 자체가 책임이 됩니다. 감사관의 질문은 "이 한도가 맞느냐"인 경우가 드뭅니다. "이 고객이 이 날짜에 왜 차단됐는지 보여 주고, 그걸 만든 규칙이 그 시점에 적용 중이던 규칙임을 증명하고, 이 기록이 우리가 질문받을 걸 안 뒤에 작성된 게 아님을 증명하라"입니다.
if-else는 그 어디에도 답이 없습니다. 결과를 계산하고, 거기에 이르게 한 모든 것을 버립니다. 로그를 더할 수는 있지만, 애플리케이션 로그는 고칠 수 있고, 일정 기간이 지나면 사라지고, 결정을 구조화된 사실로 남기는 게 아니라 개발자가 찍기로 한 것만 담습니다. 규제 대상 결정에 필요한 건 정반대입니다. 결정이 내려지는 순간 기록되어, 그 결정에 쓰인 입력값, 걸린 규칙, 사유, 버전, 시각을 담고, 이후에는 바꿀 수 없는 불변 기록입니다.
이게 순수 룰 엔진이 부실하게 다루는 반쪽이고, 감사라는 관점이 따로 필요한 이유입니다. 모든 결정이 그 기록을 자동으로 남기면, "이 고객은 왜 거부됐나"는 더 이상 발굴 작업이 아닙니다. 답은 불러오기만 하면 되는 결정 하나입니다. 그때의 사실, 걸린 규칙, 그 사유, 그 버전, 그 시각. 감사관을 만족시키는 바로 그 기록이 고객의 문의 티켓도 닫아 주고, 지금 코드를 보고 짐작한 동작이 아니라 시스템이 그때 실제로 한 일을 우리 팀에 알려 줍니다. 결과를 내는 건 사소한 일입니다. 1년 뒤에도 해명할 수 있는 결과를 내는 게 요구 사항이고, 그건 나중에 덧붙이는 게 아니라 결정이 돌아가는 자리의 속성입니다.
고객에게 닿기 전에 한도 변경을 테스트하라
큰 대가가 따르는 또 한 가지는 임계값을 눈감고 바꾸는 일입니다. 어느 등급의 한도를 올리거나, 승인 기준 점수를 낮추거나, 속도 규칙을 조이면, 실제로 몇 명의 고객이 영향을 받을까요? 의도하지 않은 리스크 구간으로 새로 승인되는 신청자는 몇 명일까요? 지금 통과하던 거래 중 더 엄격해진 규칙이 이제 막는 건 어느 것일까요? 배포 전에는 모든 답이 추측이고, 이 도메인에서 틀린 추측은 수익을 놓치는 데 그치지 않습니다. 해명해야 할 승인·차단 건을 무더기로 떠안게 됩니다.
스테이징은 이걸 해결해 주지 못합니다. 스테이징에는 신청자와 거래의 실제 분포가 없기 때문입니다. "지난달 거부된 신청 가운데 이 느슨해진 임계였다면 승인으로 바뀌었을 건수가 얼마인가"는 우리의 실제 모집단에 대한 질문입니다. 실제 고객이 하루 동안 보여 주는 점수, 소득, 등급, 거래 패턴의 분포 말입니다. 손으로 적은 테스트 케이스 몇 개는 규칙이 발동한다는 걸 확인해 줍니다. 하지만 한 달치 실제 결정의 형태는 재현하지 못하고, 영향 범위를 알려 주는 건 오직 그 형태뿐입니다.
실제로 통하는 방법은 제안한 변경을 실제 과거 결정에 다시 돌려 보는 것입니다. 새 임계를 지난달의 실제 신청자나 이체에 적용하고, 아무것도 배포하기 전에 몇 건의 결과가 뒤집히는지, 어느 고객군에 속하는지, 승인율 또는 차단율이 어떻게 움직이는지를 읽습니다. 추측이 아니라 근거로 판단하고, 의도하지 않은 영향을 규제 조회가 아니라 보고서에서 잡습니다.
변경을 실제 과거에 다시 돌리고 그 영향을 나란히 읽는 것, 즉 뒤집힌 결정과 비율 변화와 규칙별 통계를 보는 것은 변경 영향 시뮬레이션으로 배포 전 규칙 변경 테스트하기 패턴에서 다룹니다. 이 절에서 가져갈 원칙은 이것입니다. 임계 변경에는 측정할 수 있는 모집단 영향이 있고, 선택지는 그걸 고객보다 먼저 측정할지, 아니면 규제 기관보다 나중에 측정할지뿐이라는 것.
이게 필요 없는 경우
먼저 규모를 솔직하게 따져야 합니다. 작은 경우에 잘못된 도구를 쓰는 건, 큰 경우에 도구가 없는 것만큼이나 실수이기 때문입니다. 한도가 하나로 고정돼 바뀌지 않거나, 승인 규칙 하나를 엔지니어 한 명이 온전히 맡아 이해하고 있다면, 코드에 두고 PR로 바꾸십시오. config 파일의 상수 하나가 답의 전부이고, 거기에 플랫폼을 얹는 건 나중에 떠안기 싫어질 무게입니다.
이 로직을 서비스 코드 밖으로 빼는 근거는 누가 바꾸는지, 얼마나 자주 바꾸는지, 누가 그 결과를 책임지는지이지, 도메인이 핀테크라는 사실이 아닙니다. "규제 대상"이라는 이유만으로 이 모든 장치가 필요해지는 건 아닙니다. 규제 상품이라도 한 번 정하면 바뀌지 않는 임계라면, 여전히 상수 하나로 충분합니다. 이 장치가 값을 하는 경우는 따로 있습니다. 우리가 아니라 규제 기관이 정한 일정에 따라 바뀌는 임계값, 배포 권한이 없는 리스크·컴플라이언스 팀이 직접 다뤄야 하는 규칙, 나중에 근거를 대야 하는 결정. 이 세 가지가 있을 때입니다. 이것들이 없다면 여기 있는 무엇도 그 비용만큼의 값을 하지 않으니, 손을 떼는 게 맞습니다.
아직 그 지점이 아니라면, 갖지도 않은 문제를 위한 장치를 짓지 마십시오.
핀테크의 한도와 심사 기준과 승인 결정은 규제 기관의 일정에 맞춰 바뀌고, 돌아간 지 한참 뒤에도 해명을 요구받을 수 있습니다. 이걸 서비스 코드에 박아 넣으면, 외부 마감에 쫓기는 배포 병목, 서비스마다 어긋나는 임계값, 복원할 수 없는 결정, 자기 규칙에 손대지 못하는 정책 담당자를 함께 떠안습니다. 데이터로 빼내면 형태가 달라집니다. 한도가 셋이 아니라 하나의 규칙 집합에 담기고, 막힌 이체마다 사유가 남고, 변경의 영향을 배포 전에 읽고, 모든 결정이 1년 뒤에도 꺼내 보일 수 있는 기록을 남깁니다.
LexQ는 핀테크 도구가 아니라 의사결정 운영 플랫폼입니다. 바로 그래서 규제 대상 결정에, 그리고 다른 많은 도메인에 들어맞습니다. 핀테크만을 위해 만든 도구는 하나의 규제 워크플로우, 하나의 모델에 묶입니다. 결정을 데이터로 다루는 플랫폼은 같은 메커니즘을, 즉 사유를 담는 차단 규칙과 실제 과거에 돌리는 변경 영향 시뮬레이션과 불변 감사 기록을 이커머스 가격 정책과 SaaS 권한 관리에도 똑같이 재사용합니다.
고객 한 명에게 닿기 전에 한도 변경을 테스트하세요.
→ lexq.io에서 무료로 시작하기
관련 글
- 차단 규칙으로 KYC 등급별 이체 한도 집행하기: 규칙 정의 전체와 차단 동작, 그리고 막힌 이체마다 남는 사유
- 우선순위 상호 배타 그룹으로 신용 신청 판정하기: 승인·거부·조건부를 하나의 결정으로, 그 결정을 내린 규칙까지 기록
- 변경 영향 시뮬레이션으로 배포 전 규칙 변경 테스트하기: 한도 변경의 영향 범위를 실제 과거 데이터로 측정하는 법
- 애플리케이션 코드 수정 없이 비즈니스 룰을 바꾸는 방법: 한도 예시 뒤에 있는 일반적인 경우