[외주] 기획 요구사항에서 데이터 모델과 조회 로직까지 정리한 과정 - 보증금 차감과 반환을 하나의 흐름으로 볼지 분리할지

1. 왜 이 글을 쓰게 되었는가

이전 글에서는 예정 입실 기능을 예시로, 기획 요구사항을 실제 데이터 모델과 조회 로직으로 어떻게 풀어갈 수 있을지를 정리해보았다. 그런데 고시원 프로젝트를 진행하면서 느낀 점은, 예정 입실처럼 상태 해석이 중요한 기능만 있는 것이 아니라 보증금처럼 금전 흐름 자체를 어떻게 구조화할 것인가가 더 중요한 기능도 있다는 점이었다.

 

처음에는 보증금도 비교적 단순한 기능처럼 보였다. 계약할 때 계약금을 입력하고, 현재 남아 있는 보증금 금액만 보여주면 될 것 같았다. 하지만 실제 운영 흐름을 들어보니 보증금은 그렇게 단순한 값이 아니었다. 거주 중에도 차임이나 미납금 때문에 차감될 수 있었고 퇴실 시에는 공과금 정산이나 시설 손상 비용이 추가로 반영될 수 있었다. 마지막에는 남은 금액이 반환되기도 했다.

 

즉 보증금은 단순히 “현재 얼마가 남아 있는가”만 보여주는 값이 아니라, 차감과 반환이 누적되면서 최종 정산으로 이어지는 흐름에 더 가까웠다. 이번 글에서는 그 후속편으로 보증금 기능을 실제로 어떤 기준으로 해석했고, 차감과 반환을 하나의 흐름으로 볼지 아니면 분리해서 관리할지 그리고 이 데이터를 화면과 조회 로직에서 어떻게 사용할지를 정

리해보려고 한다.

 

2. 처음 받은 요구사항

https://wo-dbs.tistory.com/377

 

[외주] 고시원 관리 프로그램 요구사항 명세서 - v0.2

문서 개요문서명 : 고시원 관리 프로그램 요구사항 명세서작성일 : 2026년 3월 26일작성자 : 정재윤프로젝트 목적 : 고시원의 입실 현황, 장부, 연간 캘린더, 방 상세 정보 등을 관리할 수 있는 웹

wo-dbs.tistory.com

 

위 블로그는 고시원 관리 프로그램 요구사항 명세서 - v0.2이다. 블로그의 나와있는 내용을 다음과 같이 간단하게 생각하였다.

그런데 다음과 같은 블로그에서 보증금 관리에 대한 내용이 상세화 되다가

https://wo-dbs.tistory.com/378

 

[외주] 고시원의 자료를 받은 미팅 - 3/29

https://wo-dbs.tistory.com/376 [외주] 카톡으로 받은 요구사항 정리해보기(겹치는 요구사항 발생) - 3/28다음 글에서 요구사항 명세서를 전달해드리고 카톡으로 받은 요구사항을 정리해보려고 한다.https:

wo-dbs.tistory.com

 

다음 블로그에서 좀 상세화가 되었다.

https://wo-dbs.tistory.com/381

 

[외주] 기획적으로 풀기 어려운 요구사항 정리 및 기능별 화면명세서 - 4/3 작성 - 3

이번에는 기획적으로 풀기 어려운 요구사항을 정리하고 각 시나리오에 대해 작성해서 사장님과 미팅을 진행해보려고 한다. 4.2 입실자 관리4.2.1 입실자 목록 조회 → 예정 입실 기능사용자는 입

wo-dbs.tistory.com

 

 

위는 직접 정리를 한 것인데 사장님께서 보증금이 위와 같은 시나리오에 있을 때 보증금이 차감되는 것까지 추가적으로 필요하다고 하셨다

즉, 보증금은 단순히 퇴실할 때 반환하는 것도 있지만 입실자가 거주하고 있을 때 보증금에서 깎일 수 있는 부분까지 추가적으로 처리할 수 있게 만들어야했다.

 

처음에는 “보증금 이력 테이블 하나 있으면 되지 않을까?”라는 생각이 들 수도 있다. 실제로 화면 관점에서 보면 필요한 것은 꽤 명확했다. 얼마가 남아 있는지, 왜 얼마가 빠졌는지, 언제 빠졌는지를 보여주면 되기 때문이다.

위와 같이 이 기능은 단순히 “차감 내역을 보여주는 기능”이라고만 보는 것이 아니었다. 또한, 보증금은 차감만 있는 것이 아니라 마지막에는 반환도 함께 일어나기 때문이다. 즉 이 기능은 단순 이력 조회가 아니라, 보증금이 계약 시점부터 퇴실 정산까지 어떻게 변해왔는가를 보여주는 기능에 더 가까웠다.

 

이 지점부터 보증금 기능은 단순한 숫자 표시 기능이 아니라, 금전 정산 흐름을 어떻게 모델링할 것인가의 문제로 보이기 시작했다.

 

3. 운영에서는 실제로 어떤 일이 일어나는가

실제 운영 시나리오는 2번에서 나온 것처럼

https://wo-dbs.tistory.com/381

 

[외주] 기획적으로 풀기 어려운 요구사항 정리 및 기능별 화면명세서 - 4/3 작성 - 3

이번에는 기획적으로 풀기 어려운 요구사항을 정리하고 각 시나리오에 대해 작성해서 사장님과 미팅을 진행해보려고 한다. 4.2 입실자 관리4.2.1 입실자 목록 조회 → 예정 입실 기능사용자는 입

wo-dbs.tistory.com

 

위와 같은 시나리오가 있다. 이걸 순서대로 한 번 정리해보겠다.

 

[실제 운영 시나리오]

  1. 입실자가 계약을 진행하였고 계약금(보증금)을 낸다.
  2. 거주 중에 문제가 생기면 중간에 차감이 될 수 있다.
  3. 이후 퇴실 시점이 되면 방 상태를 점검한다.
  4. 점검 결과에 따라 도배, 타일, 시설 손상 같은 수리 비용이 추가적으로 차감될 수 있다.
  5. 최종적으로 남은 금액은 입실자에게 반환한다.

입실자가 아직 거주 중인데 월세 일부를 내지 못한 경우, 총무님은 보증금에서 먼저 그 금액을 차감할 수 있다. 이때는 아직 반환이 일어나지 않았지만 보증금은 이미 줄어든 상태가 된다. 반대로 퇴실 시점에는 지금까지의 차감 내역을 모두 반영한 뒤, 마지막으로 남은 금액을 반환하게 된다.

즉 보증금은 단순히 현재 잔액 하나로 설명되지 않았다. 계약금 → 중간 차감 → 퇴실 시 추가 차감 → 최종 반환 이라는 흐름 속에서 계속 의미가 달라지는 값에 가까웠다.

 

4. 기획 요구사항을 구현으로 옮기려 하니 생긴 질문들

운영 시나리오를 바탕으로 보증금 요구사항을 다시 보니, 구현 단계에서는 생각보다 많은 질문이 생겼다.

  • 보증금은 현재 잔액만 저장하면 되는가
  • 차감 내역은 별도 이력으로 관리해야 하는가
  • 차감과 반환은 같은 성격의 이벤트로 볼 수 있는가
  • 거주 중 차감과 퇴실 시 정산을 같은 흐름으로 처리해도 되는가
  • 반환 여부는 별도 상태값으로 관리해야 하는가
  • 차감 사유는 고정된 항목으로 둘 것인가, 자유 입력도 허용할 것인가
  • 차감 이력과 반환 이력을 하나의 테이블에 넣을 것인가, 분리할 것인가
  • 사용자가 보고 싶은 것은 “현재 남은 금액”인가, 아니면 “어떻게 줄어들었는지의 근거”까지 포함한 흐름인가

처음에는 잔액 컬럼 하나와 차감 이력 테이블 하나 정도면 충분할 것처럼 보였다. 하지만 실제로는 그렇지 않았다. 보증금은 단순한 현재값이 아니라, 언제 어떤 이유로 줄었는지, 그리고 최종적으로 언제 어떻게 반환되었는지까지 이어지는 흐름을 가진다. 따라서 단순히 숫자만 저장해서는 이 기능을 제대로 설명하기 어려웠다.

 

5. 처음에는 보증금 총액과 잔액만 있으면 된다고 생각했다

처음에는 보증금 기능도 비교적 단순하게 생각했다. 계약할 때 받은 보증금 금액을 하나의 테이블에 저장하고 이후 차감이 일어나면 현재 남은 잔액만 갱신해주면 된다고 본 것이다. 즉 처음에는 “현재 보증금이 얼마 남아 있는가”만 알 수 있으면 충분하지 않을까 생각했다.

 

하지만 실제로 테이블을 설계하려고 보니 이 방식만으로는 부족하다는 점이 보이기 시작했다. 보증금은 단순히 숫자가 줄어드는 것으로 끝나는 값이 아니었다. 왜 줄어들었는지, 언제 줄어들었는지, 어떤 사유로 차감되었는지가 함께 남아 있어야 했다.

 

이 부분이 중요하다고 느낀 이유는 관리자 입장에서도 차감 근거를 다시 확인해야 하는 상황이 생길 수 있기 때문이다. 예를 들어 차임 미납으로 얼마가 빠졌는지, 공과금 정산으로 얼마가 차감되었는지, 퇴실 점검 후 시설 손상 때문에 얼마나 차감되었는지를 다시 확인해야 할 수 있다. 단순히 현재 잔액만 남아 있다면, “왜 이 금액이 되었는가”를 설명할 근거가 사라지게 된다.

 

또한 나중에는 입실자 역시 자신의 보증금이 어디에서 빠져나갔는지 관리자에게 물어볼 수 있다고 생각했다. 이때 관리자는 단순히 “현재 얼마 남았다”는 결과만 말하는 것이 아니라, 어떤 항목 때문에 얼마가 차감되었는지를 근거와 함께 설명할 수 있어야 한다. 결국 보증금은 현재값만 중요한 것이 아니라, 그 값이 만들어진 과정까지 함께 관리되어야 했다.

 

그래서 보증금은 하나의 테이블에 총액과 잔액만 두는 방식으로는 충분하지 않다고 판단했다. 현재 보증금 값과 별도로, 차감 과정을 설명할 수 있는 이력 데이터가 필요하다는 생각이 들었고, 이 시점부터 단순 금액 저장이 아니라 정산 흐름을 남기는 방향으로 설계를 다시 보게 되었다.

 

6. 데이터는 이렇게 나누어 보기로 했다

6.1 방 데이터

  • id값은 TEXT 형태로 101 값이 들어간다
  • floor는 1층인지 2층인지 들어가게 되는데 101면 → 1, 201면 → 2 이렇게 들어간다.
  • name은 101이면 → 1층 01호 이렇게 들어가게 된다.
  • room_type은 총무님이 주신 값을 기반으로 들어간다. 이것에 대한 값은 다음 블로그에서 확인할 수 있다.

https://wo-dbs.tistory.com/370

 

[외주] 미팅 이후, 운영에 맞게 화면을 더 구체화했다 및 좀 더 어려운 요구사항.. - 3/24

저번에 미팅했던 요구사항에 대해 개선 작업을 하였고 크게 다음과 같이 진행하였다.입실자 장부 리스트 보완연간 캘린더 축소 버전 추가도면 상세 정보 강화 및 신규 입실자 등록 흐름 추가 3/1

wo-dbs.tistory.com

 

  • created_at은 값의 생성 날짜라 now 시간 값이 들어간다.

 

6.2 현재 입실자 데이터 및 예약 데이터

  • 이 데이터 컬럼은 밑에 있는 블로그에 설명되어있는 원장님께 받은 자료에서 컬럼을 구성하기도 하였고 필요한 컬럼도 추가하였다.

https://wo-dbs.tistory.com/378

 

[외주] 고시원의 자료를 받은 미팅 - 3/29

https://wo-dbs.tistory.com/376 [외주] 카톡으로 받은 요구사항 정리해보기(겹치는 요구사항 발생) - 3/28다음 글에서 요구사항 명세서를 전달해드리고 카톡으로 받은 요구사항을 정리해보려고 한다.https:

wo-dbs.tistory.com

contracts이 테이블은 → 계약 테이블 (과거 + 현재 통합) + 이력이 되며 현재 입실중 사람들도 여기서 볼 수 있다.

  • rooms와 1:N 관계로 진행된다. 왜냐하면 한 방에 1명만 입실이 가능하지만 여러명의 이력을 남길 수 있기 때문이다.
  • name → 이름
  • phone → 010-0000-0000 이런 형태로 저장된다. 프론트엔드에서 무조건 이렇게 저장되게 만들었다.
  • age → 나이
  • purpose와 real_state_agency는 입주 목적과 부동산인데 값은 원장님께 다음과 같이 받았다. 또한, 이 값을 직접 화면에서 값을 추가할 수 있도록 만들었다.

https://wo-dbs.tistory.com/375

 

[외주] 요구사항 명세서 작성 및 사용자에게 전달 - 3/26

밑 개발 일지 이후로 요구사항 명세서를 작성해야 겠다는 결심이 섰다.. 개발을 하면 할 수록 어려운 기능들이 붙기 시작했기 때문이다.https://wo-dbs.tistory.com/370 [외주] 미팅 이후, 운영에 맞게 화

wo-dbs.tistory.com

 

  • contract_start_date, contract_end_date, contract_months
    • contract_start_date는 계약서의 계약일(시작)이다. 시나리오에서 총무님이 계약서를 토대로 넣는 값이다.
    • contract_end_date는 계약서의 계약일(끝)이다. 시나리오에서 총무님이 계약서를 토대로 넣는 값이다.
    • contract_months는 개월 수인데 입실자가 3개월 살 것이다. 하면 3개월을 넣어주면 되는데 이때 contract_start_date값을 넣고 3개월을 넣으면 자동으로 계산되고 contract_end_date에 값이 들어감.
  • monthly_rent는 입실자가 직접 내야하는 월세이다. 이것을 따로 둔 이유는 방에 월세가 적혀있지만 할인이 들어갈 수 있기 때문이다 == 나처럼
  • contract_deposit는 계약금(원)이다. 총무님께서 직접 계약서에 있는 보증금을 넣는 자리이다.
    • deposit_total는 처음에 contract_deposit값이 들어가면 이 값도 초기화되는데 이건 보증금 관리 이력에서 차감 부분에서 쓰이게 된다. contract_deposit에 값을 넣었을 때 deposit_total에 값이 들어감
  • deposit_returned, deposit_returned_at는 보증금 반환이다. deposit_returned는 처음에 false값이 저장된다.
    • 보증금 관리 이력에서 보증금 반환을 하면 deposit_returned는 true로 바뀌고 deposit_returned_at은 보증금 반환 버튼을 누른 날짜 값이 들어간다.
  • created_at는 값 생성 날짜이다. → Default로 now가 들어간다.
  • updated_at는 컬럼 값이 업데이트 된 날짜이다. → Default로 now가 들어간다

 

→ 여기서 중요한 것은 contract_deposit, deposit_returned, deposit_total, deposit_returned_at는 보증금에 대한 데이터를 의미한다.

  • contract_deposit == 전체 보증금
  • deposit_total == 보증금 잔금
  • deposit_returned == 보증금 반환 유무
  • deposit_returned_at == 보증금 반환되었을 시에 반환 날짜

contract_deposit와 deposit_total를 따로 둔 이유는 나중에 입실자의 전체 보증금 금액이 얼마인지 알아야하기 때문이다.

 

 

6.3 보증금 반환 이력 테이블

  • 위 테이블은 contract table과 1:N 관계를 가진다.
  • 처음에 총무님께서 보증금을 입력하면 contract_deposit에 값을 넣으면 자동적으로 deposit_total 컬럼에 전체 보증금 값이 들어간다.
  • 그러면 이제 보증금 차감을 했을 때 다음과 같은 테이블에 값이 저장된다.

  • date → 차감된 날짜
  • amount → 차감 금액
  • reason → 차감 이유
    • 이는 ENUM 값을 통해 선택하게 만들었다.
  • 생성 날짜는 자동으로 들어간다.

 

위 상태에서 보증금 차감이 되면 contract table의 deposit_total가 금액이 amount 만큼 차감된다.

 

7. 이 데이터를 실제 화면과 로직에서 어떻게 사용했는가

  • 우선 가짜 데이터로 이렇게 20만원을 넣었다.

 

7.1 입실자의 거주 중에 문제가 생기면 중간에 차감

위와 같이 하였을 때 table의 움직임을 보자

 

  1. 보증금 관리 이력에서 새로운 보증금 관리 이력을 추가하고 “저장” 버튼을 누르면 다음과 같이 값이 들어간다.
  • 다음은 contract table이다. 보증금에 관련한 컬럼만 가져오겠다.
화면 필드 DB 컬럼 비고
계약금 contract_deposit   200,000
계약금 잔금 deposit_total contract_deposit의 값이 들어감 150,000
보증금 반환 유무 deposit_returned   false
보증금 반환되었을 시에 반환 날짜 deposit_returned_at    

 

  • 보증금 관리 이력 테이블은 다음과 같다.
화면 필드 DB 컬럼 비고
차감한 날짜 date   2026-04-22
차감 금액 amount   50000
차감 이유 reason   미납
생성 날짜 created_at   2026-04-22 18:02:20.504176+00

 

7.2 입실자의 퇴실

  • 입실자가 퇴실할 때가 되면 총무님은 그 방을 확인하고 보수가 필요한 게 있거나 하면 보증금 차감을 할 수 있다.
  • 다음과 같이 고시원이라는 입실자는 2027년 1월 18일에 퇴실하기로 되어있었다. 그래서 퇴실일인 2027년 1월 18일이 되었고 입실자는 퇴실 하기전 총무님께 검사를 받는다.

  • 그 후 총무님께서는 문제를 발견한다. 다음과 같이 이렇게 차감을 완료했다.(반환 이력 날짜는 오늘날로 되어있다. 가짜 데이터로 한 것이라 문제 되지 않는다.) 차감은 7.1과 같다.

  • 그 후 총무님은 이제 입실자에게 보증금을 반환을 해주어야한다. 그래서 보증금을 반환을 해주고 반환 완료 처리 버튼을 누른다.

 

반환 완료 후 테이블은 다음과 같이 된다.

화면 필드 DB 컬럼 비고
계약금 contract_deposit   200,000
계약금 잔금 deposit_total contract_deposit의 값이 들어감 120,000
보증금 반환 유무 deposit_returned   ture
보증금 반환되었을 시에 반환 날짜 deposit_returned_at   2027-01-18

 

 

8. 마무리

이번 보증금 기능을 정리하면서 가장 크게 느낀 점은, 보증금은 단순히 “현재 얼마가 남아 있는가”만 보여주는 값이 아니라는 점이었다.

 

처음에는 계약할 때 받은 보증금과 현재 잔액만 저장하면 충분하다고 생각했다. 하지만 실제 운영 흐름을 따라가다 보니, 보증금은 거주 중 차감이 일어날 수도 있고, 퇴실 시 추가 차감이 발생할 수도 있으며, 마지막에는 반환까지 이어지는 값이었다. 즉 하나의 숫자로 끝나는 데이터가 아니라, 차감과 반환이 누적되며 최종 정산으로 이어지는 흐름에 더 가까웠다.

 

그래서 이번 설계에서는 계약 테이블 안에 전체 보증금과 현재 잔액, 반환 여부를 두고, 별도의 보증금 관리 이력 테이블로 차감 근거를 남기는 방향으로 정리했다. 이렇게 나누고 나니 단순히 “남은 돈”만 보는 것이 아니라, 왜 이 금액이 되었는지를 함께 설명할 수 있는 구조가 되었다.

 

이 점은 관리자 입장에서도 중요하지만, 나중에 입실자가 자신의 보증금이 어떤 이유로 차감되었는지 물어봤을 때 근거를 보여줄 수 있다는 점에서도 필요하다고 느꼈다. 결국 보증금 기능은 단순한 금액 표시 기능이 아니라, 정산 과정을 기록하고 설명할 수 있어야 하는 기능이었다.

 

이번 글에서는 보증금 차감과 반환을 어떻게 해석했고, 이를 데이터와 화면에서 어떤 방식으로 풀어갔는지 정리해보았다.