파트너 수수료 계층별 마진 계산 로직 개선
목차
파트너 수수료 계층 구조는 얼핏 단순해 보이지만, 실제로 건드리다 보면 생각보다 촘촘하게 엮여 있다. 오늘 작업한 범위는 validation 제거 및 재추가, 건당 수수료 편집 기능, 마진 계산 방향 수정 세 가지였다. 규모는 작았지만 정산 로직이라 실수하면 이후 배치 전체가 틀어지는 종류여서 꼼꼼하게 짚었다.
수수료 모델 자체를 먼저 정리하자면, 유통 계층이 깊어질수록 요율이 높아지는 차등 구조다. 최하위 파트너가 가장 높은 요율을 부담하고, 상위 계층은 그 차액을 마진으로 가져간다. 표로 보면 이렇다.
| 계층 | 요율 | 마진(차액) |
|---|---|---|
| 최하위 | 1.0% | - |
| 중간 | 0.8% | 0.2% |
| 최상위 | 0.6% | 0.2% |
이 구조에서 마진은 항상 하위 요율 - 상위 요율로 계산된다. 양수가 보장되어야 정상이고, 만약 설정 실수로 상위 요율이 하위보다 높아지면 마진이 음수가 된다. 단순한 데이터 설정 오류인데 런타임에서는 조용히 음수 금액을 흘려보내기 때문에, 배치가 돌고 정산이 확정된 이후에야 발각되는 최악의 타이밍이 온다. 그래서 저장 시점에 계층 요율 순서를 검증하는 로직이 필요했다.
계산 코드와 타입 선택의 이유
수수료 금액 자체는 비율 수수료와 건당 고정 수수료를 합산하는 구조다.
// 계층별 수수료 계산 - 내부 클래스 패턴
long feeAmount = (long)(txAmount * feeRate) + perTxFee;
여기서 타입을 long으로 강제한 이유가 있다. txAmount * feeRate는 double 연산인데, 통화 금액 계산에서 부동소수점을 그냥 쌓으면 누적 오차가 생긴다. 거래 한 건에선 무시할 수준이지만 배치에서 수만 건을 돌리면 차이가 나기 시작한다. 그래서 원 단위로 버림 처리한 long으로 캐스팅하고, 고정 수수료를 더해 최종값을 확정한다.
이 계산을 BigDecimal로 바꾸는 방향도 고려했는데, 현재 시스템에서 수수료 요율 자체가 소수점 둘째 자리 수준이고 건당 금액 범위도 명확해서 long 캐스팅으로도 허용 오차 내에 들어온다고 판단했다. 다만 요율이 더 잘게 쪼개지거나 외화 환산이 붙으면 그때는 BigDecimal로 교체하는 게 맞다.
건당 수수료 편집 기능은 이번에 추가한 부분인데, 기존에는 비율 요율만 수정 가능하고 건당 고정 수수료는 초기 설정 이후 변경이 안 됐다. 운영팀에서 계층 재협의할 때마다 코드 수정이 필요했던 셈이라 이번에 편집 가능하게 열었다. 단, 변경 즉시 적용이 아니라 다음 정산 주기부터 반영되도록 했다. 이미 진행 중인 기간의 수수료를 중간에 바꾸면 기간 내 일관성이 깨지기 때문이다.
validation 설계에서 고민한 것
원래 코드에 validation이 있긴 했는데 이번에 한 번 제거했다가 다시 추가했다. 이유가 있었다. 기존 validation이 저장 레이어 안에 있어서 관리자 화면에서 직접 수정할 때는 검사를 피해갈 수 있는 경로가 있었다. 그래서 일단 그 validation을 걷어내고, 서비스 레이어에서 단일 진입점으로 검증하는 구조로 옮겼다.
계층 요율 순서 체크는 다음 조건을 만족해야 저장을 허용하도록 했다.
- 동일 계층 체인 내 하위 요율 >= 상위 요율
- 요율은 0 초과, 100 미만
- 건당 수수료는 0 이상 정수
첫 번째 조건이 핵심인데, 등호를 허용하는 이유는 같은 요율로 구성하는 경우(마진 0)를 유효 설정으로 볼 것인지가 정책 판단이기 때문이다. 마진 0은 수익이 없는 구조지만 그걸 금지할 근거는 시스템 레벨에서 없다고 봤다. 음수가 명확한 버그이니 그 선만 막는 게 맞다.
마진 계산 방향 수정은 기존 코드가 상위 요율 - 하위 요율로 빼고 있던 걸 하위 요율 - 상위 요율로 바꾼 거다. 잘못된 방향으로 계산하면 마진이 항상 음수로 나오는데, 이게 실제 배치에서 어떻게 처리됐는지가 약간 찝찝한 부분이다. 정산 배치가 마진 음수를 별도 처리 없이 그냥 흘렸을 수도 있어서, 기존 배치 결과 로그를 한 번 더 들여다볼 예정이다.
정산 UI 쪽은 이번에 직접 수정하진 않았지만 같이 논의가 나온 부분이 있어서 메모해 둔다. 정산 화면에서 총 거래액, 수수료, 실수령액 세 숫자가 핵심인데, 현재는 천 단위 구분자 처리가 일부 컴포넌트에서 누락돼 있다. 마이너스 금액은 빨간색 처리가 필요한데 현재는 단순 텍스트로만 표시된다. 수치 오류가 아니라 표시 문제지만, 운영팀이 이 화면을 매일 보고 판단을 내리는 만큼 직관성이 중요하다.
작업 규모 자체는 크지 않은데, 이런 계산 로직 수정이 신경 쓰이는 이유는 결과가 돈과 직결되기 때문이다. 렌더링 버그는 새로고침하면 되지만 정산 금액 오류는 이미 지급된 이후에 발견된다. 그래서 변경 범위가 작아도 배치 동작과 데이터 흐름을 머릿속에서 한 번 더 돌려보는 습관이 필요하다. 오늘 작업은 그 점에서 검증이 훨씬 중요한 로직이었고, 코드 줄 수보다 검증 범위 설계에 더 시간을 쏟았다.
댓글 0
첫 댓글 달아줘.