Post

[ECC 2026 Summer Project] SplitOpt - Week 2

[ECC 2026 Summer Project] SplitOpt - Week 2

기간: 2026. 07. 20 – 07. 26 (2주차)

내용: DB 스키마 설계, 구현 범위 확정, 파트 분담

파트: 백엔드


2주차는 코드를 쓰기 전 마지막 설계 주였다. 1주차에 API 명세서 초안(49개 엔드포인트)을 잡았으니, 이번엔 그 명세를 받쳐줄 테이블을 설계하고 한 달 안에 실제로 끝낼 범위를 정했다.

1. 구현 범위 확정

초안의 49개를 그대로 들고 가면 한 달 안에 끝나지 않는다. 그래서 필수 기능과 추가기능 1(일정·예산)까지인 1–40번만 구현 범위로 두고, 추가기능 3·5·6(41–49: 정산 그래프 시각화, 정산 메시지, 신뢰도 지표)은 범위 밖으로 미뤘다.

미룬 기능을 명세에서 지우지는 않았다. 나중에 붙일 때 구조가 흔들리지 않도록 엔드포인트는 초안에 남겨두고, 테이블만 범위 안의 것으로 설계했다.

2. DB 스키마 설계

8개 테이블로 정리했다.

테이블역할대응 API
users로그인 계정1–4
groups정산의 최상위 단위5–9, 14, 15
group_participantsusers ↔︎ groups 멤버십10–16
expenses지출 헤더(누가 얼마 결제)17–21
expense_shares지출 부담 분배(라인)22
settlements정산 송금 관계24–29
schedules여행·모임 일정33–37
budgets모임 예산38–40

설계하면서 판단이 필요했던 지점이 세 개 있었다.

참여자를 별도 테이블로 둔 이유

지출의 결제자·부담자, 정산의 송금인·수취인을 users.id로 바로 가리키면 “이 사람이 이 모임 소속인가”를 DB가 보장해주지 못한다. 그래서 group_participants를 N:M 연결 테이블로 두고, 지출·정산은 모두 사용자가 아니라 참여자 행을 가리키게 했다. (group_id, user_id)에 복합 유니크를 걸어 한 모임에 같은 사람이 두 번 들어가는 것도 막았다.

덤으로 모임 내 표시 이름(display_name)과 탈퇴 처리(is_active, left_at)를 여기에 둘 수 있게 됐다. 계정을 지우지 않고 모임에서만 빠지는 게 자연스럽기 때문이다.

지출과 부담을 헤더/라인으로 분리

expenses에 총액만 두고, 누가 얼마를 부담하는지는 expense_shares에 참여자별로 한 행씩 저장한다. 이렇게 나눠야 잔액 계산이 단순해진다.

1
잔액 = (그 참여자가 결제한 합) − (그 참여자가 부담한 합)

전체 N등분이든 일부 인원 분배든 개별 금액 지정이든, 결과는 모두 “참여자별 부담 금액”이라 share_amount 하나로 저장하고 복원할 수 있다.

삭제 정책을 컬럼마다 따로

FK마다 삭제 동작을 다르게 걸었다.

  • 모임에 딸린 것(참여자·지출·정산·일정·예산) → CASCADE. 모임을 지우면 함께 사라져야 한다.
  • 금액 기록이 참조하는 참여자 → RESTRICT. 정산 기록이 남아 있는데 참여자 행이 사라지면 “누가 누구에게”가 깨진다.
  • expenses.schedule_id → SET NULL. 일정을 지워도 지출 자체는 남아야 한다.

groups.owner_id도 RESTRICT로 뒀다. 소유한 모임이 있는 유저의 탈퇴는 애플리케이션에서 소유권 이전이나 모임 삭제를 먼저 강제해야 한다는 뜻이다.

3. 파트 분담

백엔드를 세 파트로 나누고, 각자 자기 도메인만 건드리는 방식으로 정했다.

파트API 범위
A인증·사용자(1–4), 모임·참여자(5–16)
B지출(17–22), 통계(30–32), 일정(33–37)
C정산 계산·최적화·상태(23–29), 예산(38–40)

나는 C 파트를 맡았다. 1주차에 확인한 대로 이 서비스의 난이도는 CRUD가 아니라 계산에 있고, 그 계산이 몰려 있는 부분이다.

정산은 잔액에서 출발하고 잔액은 지출·부담에서 나오므로, 파트 경계를 넘지 않으려면 계산 로직이 지출 테이블에 직접 묶이지 않아야 한다. 잔액을 입력으로 받는 형태로 설계해 최적화와 잔액 계산을 독립적으로 만들고, 지출 집계와의 연결은 별도 지점으로 분리하기로 했다.

This post is licensed under CC BY 4.0 by the author.