← 블로그 · Projects
1/N 정산에서 나머지 1원을 누가 갖는가
#회고 #LOVETRIP #정산 #TypeScript
유주환 · Founder, Full Stack Developer
토리스(Toris) · 발행
프로젝트를 돌아보는 30일 · 20/30
과거 프로젝트 경험을 날짜별로 엮은 회고입니다. 표시 날짜는 연재 기준일이며, 실제 작업일과 다를 수 있습니다.
LOVETRIP에서 예산과 1/N 정산을 구현하며 금액 계산은 다른 UI 계산보다 보수적으로 다뤄야 한다고 느꼈다. 장소 추천이 조금 마음에 들지 않으면 다른 코스를 고르면 된다. 하지만 합계와 개인 부담액이 맞지 않으면 제품 전체를 다시 확인하게 된다.
나누기 연산 뒤에도 규칙이 남는다
원화 정수 금액을 여러 사람이 나누면 나머지가 생길 수 있다. 소수점 자릿수를 숨기는 것으로 해결하면 개인 금액의 합이 원래 합계와 달라진다. 문제는 자바스크립트 문법만이 아니다. 남은 금액을 누구에게 배분할지 제품 규칙이 필요하다.
아래 코드는 당시 운영 소스가 아니라, 합계를 보존하는 한 가지 방식을 설명하는 예제다. 음수가 아닌 안전한 정수 금액과 1~1,000명의 인원수를 입력으로 제한한다.
function splitWon(total: number, count: number): number[] {
if (!Number.isSafeInteger(total) || total < 0 ||
!Number.isInteger(count) || count < 1 || count > 1000) {
throw new Error('금액과 인원수를 확인하세요.');
}
const base = Math.floor(total / count);
const remainder = total % count;
return Array.from({ length: count }, (_, i) =>
base + (i < remainder ? 1 : 0));
}
// splitWon(10000, 3) → [3334, 3333, 3333]
정확해도 공정함을 설명해야 한다
이 예제는 앞쪽 사람에게 나머지를 배정한다. 따라서 사람의 순서가 바뀌면 부담액도 바뀐다. 실제 제품에서는 순서를 안정적으로 정하거나 사용자가 조정할 수 있게 하는 등 별도 선택이 필요하다. 수학적으로 합계가 맞는 것과 사용자가 납득하는 것은 다른 기준이다.
지금 다시 검증한다면 총액 0, 인원수보다 작은 총액, 나누어떨어지지 않는 금액을 먼저 보겠다. 개인 부담액 합계가 원래 금액과 같은지, 최댓값과 최솟값의 차이가 1원을 넘지 않는지가 이 단순 균등 분배 예제의 핵심 조건이다.
계산과 저장은 따로 확인해야 했다
화면에서 올바르게 계산해도 저장 중 일부 항목만 바뀌면 정산 상태는 틀어진다. 다시 설계할 때는 항목 수정과 합계 반영의 경계를 함께 검토하겠다. 환불·다중 통화·부분 참여까지 이 예제로 해결했다고 주장하지 않겠다. 그런 요구가 생기면 금액 단위와 분배 정책부터 다시 정해야 한다.
LOVETRIP은 작은 금액의 차이가 큰 신뢰 차이가 될 수 있다는 것을 알려 줬다. 다음에는 계산식을 먼저 쓰기보다 합계를 보존하는 조건과 나머지 처리 규칙을 먼저 적겠다.
관련 기록: LOVETRIP 예산 관리 경험
READERS / LIVE