Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
Tags
- 로또 등수 코드
- sops
- 채팅방 구현
- 로또 등수 알고리즘
- sops age
- 중간 테이블 엔티티 최적화
- 리사이클러뷰 멀티뷰
- springboot
- jpa 최적화
- 로또 앱 만들기
- Androoid Studio
- java
- jpa bulk insert
- 시크릿 암호화
- sops 암호화
- 스프링 환경변수 설정
- spring 채팅방
- 쿠버네티스 #fabric8
- mysql multi-row insert
- oauth 로그인
- 스프링 소셜 로그인
- 시크릿 깃에 올리기
- jpa dto 매핑
- hibe
- 스프링 환경변수
- android studio
- 안드로이드 스튜디오
- 스프링 시큐리티 없이
- multiview
- 스프링 오어스
Archives
- Today
- Total
야미의 개발
여러 명이 나누는 월세, 어떻게 정산할까? – UserPayment와 Payment로 구현하는 자동 정산 시스템 본문
이번 글에서는 얼마전에 만들었던
블록체인 기반 룸쉐어 서비스 ‘ChainG' 의 자동이체 + 상태 관리 시스템 설계 과정을 소개해보려 합니다.
💡 서비스 개요
ChainG는 여러 명이 함께 거주하는 룸쉐어 환경에서, 월세와 공과금 등을 자동이체로 분할 납부하고,
그 상태를 정확히 추적 및 관리할 수 있는 서비스를 제공하였습니다.
간단하게 납부 흐름을 보면 다음과 같이 그릴 수 있습니다.
1. 모으기
2. 집주인에게 송금하기
단순하게 월세를 '한 명이 내고 나중에 정산'하는 구조가 아니라,
각자 자신의 몫만큼 자동으로 이체되며, 전체적으로 실패나 재시도에 따라
다양한 상태 흐름을 가질 수 있도록 설계했습니다.
⚙️ 주요 컴포넌트
- PaymentEntity: 전체 월세 납부를 나타내며, 달마다 생성
- UserPaymentEntity: 각 유저가 부담해야 하는 개별 납부 항목
- PaymentStatus: 그룹 전체 상태를 나타내며, 총 금액이 모아졌는지, 어디에서 실패했는지 등...
- UserPaymentStatus: 각 유저의 납부 상태를 표현
(참고로 PaymentStatus와UserPaymentStatus는 공동 Enum으로 재사용)
🔁 자동이체 상태 간단하게 보기
- 그룹 상태 (PaymentStatus):
STARTED(생성 직후)
→ COLLECTED(모두 모아졌을 때) / PARTIALLY_PAID(연체 유저가 있을 때)
→ PAID(납부 성공) / FAILED(완전히 실패) - 개별 상태 (UserPaymentStatus):
PENDING(생성 직후)
→ COLLECTED(납부 완료)
→ FAILED(납부 실패)
🧩 상태 흐름 정리
1. 월세 납부 생성 (PaymentEntity)
- 매월 특정 시점(예: 1일 기준), 그룹별로 월세 납부 건이 생성됩니다.
- 이때 그룹 상태는 STARTED로 설정됩니다.
2. 하위 개별 납부 건 생성 (UserPaymentEntity)
- 각 유저는 계약된 비율에 따라 개별 UserPayment가 생성됩니다.
- 이들은 기본적으로 PENDING 상태에서 시작합니다.
3. 월세 전날 모으기 작업 (collectToJointAccount)
- 지정된 날짜에 각 유저의 계좌에서 공동 계좌로 자동이체를 시도합니다.
- 결과에 따라 UserPaymentStatus는 다음과 같이 바뀝니다:
- 성공: COLLECTED
- 실패: FAILED → 이후 스케줄러가 RETRY_PENDING으로 재등록
- 모든 유저가 성공하면 → PaymentStatus = COLLECTED
- 일부만 성공하면 → PARTIALLY_PAID, 일부 실패 → RETRY_PENDING
4. 월세 당일 송금 (payToOwner)
- 모든 유저의 납부가 COLLECTED일 경우, 집주인 계좌로 이체
- 이체 성공 시 전체 상태 → PAID
5. 재시도 로직
- FAILED인 유저는 최대 n회까지 재시도를 시도하며, 성공 시 COLLECTED로 전환
- 계속 실패하면 최종적으로 FAILED 상태 유지
🔎 상태 머신
머메이드 상태 머신 다이어그램으로 실제 납부 상태를 다음과같은 흐름으로 도식화 할 수 있습니다.
저는 하면서 어려웠는데... 실제로 개발하다 보면 그렇게 어렵지 않다고 하네요
티스토리에서는 머메이드 변환 해주는 기능이 없어서 아래에 첨부!
stateDiagram-v2
title : 📦 Payment (그룹 상태) 상태머신
[*] --> STARTED
STARTED --> COLLECTED : 전원 모으기 성공
STARTED --> PARTIALLY_COLLECTED : 일부 유저 송금 실패
STARTED --> FAILED : 전체 실패
PARTIALLY_COLLECTED --> COLLECTED : 재시도 후 전원 성공
PARTIALLY_COLLECTED --> FAILED : 재시도 실패
COLLECTED --> RETRY_PENDING : 집주인 송금 실패
RETRY_PENDING --> FAILED : 최대 재시도 실패
COLLECTED --> PAID : 집주인 송금 성공
🍡 마무리하며
이처럼 ChainG에서는 단순한 자동이체를 넘어서, 다양한 실패와 재시도, 그리고 상태 전이까지 명확하게 관리하며 안정적인 월세 정산 서비스를 구축해낼 수 있었습니다.
개발 당시에는 추상적인 정책들을 실제 서비스로 정의하고 설계하는 것이 어려웠지만, 이제는 곧잘 할 수 있을거같다는 생각이 듭니다. 개발전에 상태 머신같은 다이어그램을 미리 설계를 해보는 것도 중요할 듯 합니다. :)
'스프링 > 웹 개발' 카테고리의 다른 글
SOPS+Age로 시크릿을 git으로 관리하기 (0) | 2025.06.03 |
---|---|
[Spring/SpringBoot]GitLabRunner로 ci 파이프라인 작성하기 JPA, H2, test 빌드 시 오류 날때 (0) | 2025.02.06 |
[Spring/SpringBoot] 채팅방 쿼리 개선기 | JPA(Hibernate)+Mysql에서 BulkInsert(벌크 인서트) | Native Query, JDBC Template 비교하기 (1) | 2025.01.02 |
[Spring/SpringBoot] SpringSecurity없이 OAuth 구글 소셜로그인 직접 구현하기 (0) | 2024.12.23 |
[Spring/SpringBoot] .env 파일 플러그인 없이 읽기 (0) | 2024.12.17 |
Comments