계층형 수수료 차액 분배 로직과 정산 검증 강화
목차
계층형 수수료 차액 모델은 구조 자체는 단순한데, 코드로 구현할 때 생각보다 놓치기 쉬운 포인트가 많다. 유통 채널이 여러 단계를 거칠수록 각 계층이 "내가 부담하는 요율 - 내 위 계층이 부담하는 요율 = 내 마진"이라는 원리로 수익을 가져가는 방식인데, 이걸 그냥 당연하게 받아들이고 코드 짜다가 요율 순서 하나 잘못 꽂으면 마진이 음수로 튀어나온다. 그래서 이번에 로직 추가하면서 validation도 같이 박았다.
차액 분배 계산이 왜 까다로운가
표면적으로는 간단해 보인다. 계층별로 요율 테이블 있고, 거래 금액에 곱해서 차이를 위 계층 수익으로 올리면 끝. 실제로는 두 가지가 복합적으로 얽힌다.
첫째, 비율 수수료와 건당 고정 수수료가 동시에 붙는다. 비율 수수료만 있으면 단순한데, 고정 수수료는 계층 간 차액 개념이 다르게 적용된다. 비율 차액은 거래 금액에 비례해서 커지지만, 고정 수수료 차액은 건수에 비례한다. 이 둘을 합산할 때 각각의 차액을 따로 계산하고 더하는 방식으로 가야 한다.
둘째, 정산 배치는 기간 집계 방식이라 건별 실시간 계산과 기간 합산 사이에 부동소수점 오차가 누적될 수 있다. 금액 계산에서 double이나 float을 쓰다가 정산 시점에 원 단위에서 수십 원씩 차이 나는 경우가 실무에서 종종 생긴다. long으로 원 단위 정수 처리하는 게 기본이고, 비율 수수료 계산 후 절사/반올림 기준도 명시해 둬야 한다.
// 계층 간 차액 분배 계산 - 건당+비율 복합 구조
long calcFeeAmount(long txAmount, double feeRate, long perTxFee) {
long rateFee = (long)(txAmount * feeRate); // 절사
return rateFee + perTxFee;
}
long calcMarginForTier(long txAmount, int txCount,
double upperRate, long upperPerTx,
double lowerRate, long lowerPerTx) {
long upperFee = calcFeeAmount(txAmount, upperRate, upperPerTx * txCount);
long lowerFee = calcFeeAmount(txAmount, lowerRate, lowerPerTx * txCount);
return lowerFee - upperFee; // 반드시 >= 0 이어야 함
}
이번에 작업한 것도 이 패턴이다. 계층별 요율과 건당 수수료를 분리해서 관리하고, 정산 배치가 집계할 때 계층 조합마다 margin을 뽑아내는 구조.
요율 순서 validation이 필요한 이유
실제로 이게 빠져 있으면 어떤 일이 생기냐면, 운영 중에 요율 테이블을 수정할 때 계층 순서를 실수로 뒤집어 넣어도 아무 오류 없이 저장된다. 다음 정산 배치가 돌 때 마진 값이 음수로 나오고, 그때서야 데이터 보고 이상하다는 걸 알게 된다. 배치가 야간에 돈다면 다음 날 아침에 발견하는 거다.
| 계층 | 요율 | 건당 수수료 | 차액(마진) |
|---|---|---|---|
| 최하위 | 1.0% | 200원 | - |
| 중간 | 0.8% | 150원 | 비율 0.2%p + 건당 50원 |
| 최상위 | 0.6% | 100원 | 비율 0.2%p + 건당 50원 |
요율이 이 순서를 지켜야만 마진이 항상 0 이상이 보장된다. 그래서 저장 시점에 바로 체크하는 validation을 넣었다. 계층 리스트를 상위에서 하위 순으로 정렬한 뒤, 인접 계층 간 lowerRate >= upperRate 조건을 순회하면서 검사한다. 건당 수수료도 같은 방향으로 확인한다.
실수가 가장 많이 나는 시점이 신규 계층 추가할 때다. 중간에 하나 끼워 넣으면 기존 계층들과의 관계를 다 다시 따져야 하는데, 이걸 사람이 눈으로만 검증하면 놓치기 십상이다. validation이 자동으로 잡아주는 것만으로도 배포 후 사고 가능성이 확 줄어든다.
정산 화면 숫자 표기
로직 작업이랑 같이 정산 UI도 손봤다. 정산 화면에서 결국 사용자가 가장 많이 보는 건 세 숫자다.
- 총 거래액
- 차감 수수료
- 실수령액
이 세 숫자가 명확하지 않으면 정산이 맞아도 사용자 입장에서 불안하다. 천 단위 구분자와 '원' 단위는 기본이고, 마이너스 금액은 빨간색으로 처리해서 한눈에 구분되게 했다. 작은 것 같지만 이게 없으면 담당자들이 숫자 읽다가 오해하는 경우가 생긴다.
수수료 계산 로직 자체보다 "이 숫자가 어떻게 나왔는지 추적할 수 있는가"가 운영에서 훨씬 중요하다는 걸 이번에 다시 느꼈다. 배치 돌고 나서 계층별 수수료 breakdown을 저장해 두면, 나중에 문의 들어왔을 때 바로 꺼내 보여줄 수 있다. 이번 작업엔 breakdown 저장까지는 안 들어갔는데, 다음 정산 개선 때 고려할 항목으로 남겨뒀다.
작업 규모 자체는 크지 않았다. 그래도 요율 순서 validation 하나가 빠져 있으면 언젠가는 밤에 배치 뒤집히는 상황이 올 수 있어서, 작은 보강이지만 넣어두길 잘했다 싶다.
댓글 0
첫 댓글 달아줘.