1. 왜 이 글을 쓰게 되었는가
처음에는 공과금 기능도 비교적 단순하게 생각했다. 각 방마다 전기요금이나 공과금 금액을 입력하고, 그 값을 보여주면 되는 것처럼 보였기 때문이다. 하지만 실제 운영 흐름을 들어보니 공과금, 그중에서도 한전(전기) 정산은 단순히 금액 하나를 기록하는 문제로 보기 어려웠다.
이유는 퇴실자와 신규 입실자 사이에 공실 기간이 생길 수 있기 때문이다. 이 경우 전체 전기요금을 그대로 신규 입실자에게 넘길 수는 없고, 공실 기간 동안 발생한 사용분은 고시원에서 부담해야 했다. 즉 같은 한 달의 전기요금 안에서도
- 퇴실자 사용 구간
- 공실 구간
- 신규 입실자 사용 구간
이 섞여 있을 수 있었고, 실제 정산에서는 이 구간을 나누어 계산해야 했다. 즉 공과금 기능은 단순히 “이번 달 전기요금이 얼마인가”를 저장하는 기능이 아니라, 어느 기간의 사용량이 누구 책임인지 나누고, 그 결과를 시스템 안에서 어떻게 표현할 것인가의 문제에 더 가까웠다.
이번 글에서는 그 후속편으로, 공과금(한전) 공실 기간 정산 기능을 실제로 어떤 기준으로 해석했고, 공실 구간의 사용량을 시스템 안에서 어떻게 표현하려고 했는지, 그리고 이 데이터를 화면과 조회 로직에서 어떤 방식으로 풀어가려고 했는지를 정리해보려고 한다.
2. 처음 받은 요구사항
https://wo-dbs.tistory.com/370
[외주] 미팅 이후, 운영에 맞게 화면을 더 구체화했다 및 좀 더 어려운 요구사항.. - 3/24
저번에 미팅했던 요구사항에 대해 개선 작업을 하였고 크게 다음과 같이 진행하였다.입실자 장부 리스트 보완연간 캘린더 축소 버전 추가도면 상세 정보 강화 및 신규 입실자 등록 흐름 추가 3/1
wo-dbs.tistory.com

- 위 블로그에서 3/24일 미팅을 진행하였을 때 클라이언트의 요구사항은 도시가스, 전기요금 같은 게 들어가면 좋겠다고 하셨다.
https://wo-dbs.tistory.com/379
[외주] 업데이트 후 미팅 - 4/1(수)
https://wo-dbs.tistory.com/377 [외주] 고시원 관리 프로그램 요구사항 명세서 - v0.2문서 개요문서명 : 고시원 관리 프로그램 요구사항 명세서작성일 : 2026년 3월 26일작성자 : 정재윤프로젝트 목적 : 고시
wo-dbs.tistory.com

- 4/1에는 도시가스는 필요없고 전기 요금에 대한 부분만 필요하다고 하셨다. 그래서 전기 요금의 현금 승계 부분이 필요하다고 이야기 하셨다.
https://wo-dbs.tistory.com/381
[외주] 기획적으로 풀기 어려운 요구사항 정리 및 기능별 화면명세서 - 4/3 작성 - 3
이번에는 기획적으로 풀기 어려운 요구사항을 정리하고 각 시나리오에 대해 작성해서 사장님과 미팅을 진행해보려고 한다. 4.2 입실자 관리4.2.1 입실자 목록 조회 → 예정 입실 기능사용자는 입
wo-dbs.tistory.com


그 후 나는 위 블로그에서 이 현금 승계가 정확히 어떻게 처리하고 있는지 궁금하게 되어 총무님께 물어보게 되었는다 위와 같이 시나리오를 설명해주셨다.
https://wo-dbs.tistory.com/392
[외주] 클라이언트 앞에서 PT를 진행하다! - 4/8
오늘은 지금까지 정리한 요구사항과 그에 맞춰 개발한 결과물을 직접 보여드리는 날이었다. 평소와 다르게 이번에는 사장님뿐 아니라 총무님, 원장님 앞에서도 시연과 개발 현황을 함께 설명해
wo-dbs.tistory.com

- 이후 클라이언트 앞에서 PT를 진행하게 되었을 때 총무님께서 위 사진과 같이 직접 프린트를 해서 손으로 작성해주신다고 하셨는데 이것처럼 프린트를 할 수 있으면 좋겠다고 해주셨다. 그래서 다음 블로그에서 프로그램에서 PDF로 만들기 위해 어떻게 했는지 작성했다.
https://wo-dbs.tistory.com/393
[외주] 현금 승계 PDF로 만들기 - 4/8
https://wo-dbs.tistory.com/392 [외주] 클라이언트 앞에서 PT를 진행하다! - 4/8오늘은 지금까지 정리한 요구사항과 그에 맞춰 개발한 결과물을 직접 보여드리는 날이었다. 평소와 다르게 이번에는 사장님
wo-dbs.tistory.com
2.1 결론
이 기능은 요구사항을 듣는 것만으로 바로 화면이나 데이터 구조를 떠올리기 어려웠다. 처음에는 도시가스와 전기요금처럼 공과금 전반에 대한 이야기로 시작했다가, 이후에는 전기요금만 필요하다고 정리되었고, 다시 그 안에서도 단순 금액 입력이 아니라 현금 승계라는 형태의 정산이 중요하다는 쪽으로 구체화되었기 때문이다.
나에게는 이 현금 승계라는 개념이 익숙하지 않았다. 직접 경험해본 업무가 아니기도 했고, 처음에는 단순히 “전기요금을 넘겨주는 과정” 정도로만 생각했다. 하지만 이야기를 듣다 보니 실제로는 퇴실자, 공실 기간, 신규 입실자 사이에서 사용량 구간을 나누고, 그중 어떤 부분을 고시원이 부담해야 하는지를 계산하는 흐름이 들어 있었다.
그래서 이 기능은 다른 기능들보다도 먼저 운영 시나리오 자체를 이해하는 과정이 필요하다고 느꼈다. 단순히 화면에 어떤 입력칸을 둘지 고민하는 것보다, 실제 총무님이 어떤 순서로 확인하고 어떤 기준으로 정산하는지를 아는 것이 더 중요했다. 그래서 나도 이 부분은 총무님께 여러 번 질문하면서, 먼저 업무 흐름을 정확히 이해하려고 했던 기능이었다.
결국 공과금(한전) 공실 기간 정산 기능은 처음부터 명확하게 정의된 기능이라기보다, 여러 요구사항을 지나오면서 조금씩 구체화된 기능에 가까웠다. 그리고 그 과정에서 느낀 것은, 이런 기능일수록 바로 구현을 생각하기보다 먼저 실제 운영이 어떻게 돌아가는지부터 정리해야 한다는 점이었다.
3. 운영에서는 실제로 어떤 일이 일어나는가
2번에서 했던 형태로 다시 시나리오를 정리하면 다음과 같다.
실제 시나리오 - 총무님께 직접 물어보니 다음과 같다.
- 3월 16일에 사용자가 퇴실 후 총무님은 전기 사용량을 확인한다 예를 들어 1060kWh
- 다음 입실자가 3월 18일에 들어온다. 총무님은 3월 17일에서 1060kWh에서 1062kWh를 확인하고 이력을 남겨놓는다.
- 입실자는 3월 동안 고시원을 이용한다.
- 3월에 대한 지로가 고시원에 오며 총무님께서는 16일~17일에 있던 0에서 2만큼 오른 값을 측정하기 위해 네이버에서 전기요금계산기로 들어간다.
전기요금계산기 : 네이버 검색
'전기요금계산기'의 네이버 검색 결과입니다.
search.naver.com
5. 다음과 같이 진행
6. 총무님은 지로에서 받은 값에서 1330원을 뺀 금액을 수기로 다시 만들어서 입실자에게 전달한다.
7. 총 금액은 고시원 사장님께서 계산하신다.
4. 기획 요구사항을 구현으로 옮기려 하니 생긴 질문들
실제 운영 시나리오를 바탕으로 공과금(한전) 요구사항을 다시 보니 구현 단계에서는 생각보다 많은 질문이 생겼다.
- 공과금 정산에서 기준이 되는 날짜는 계약일인가, 실제 입실일/퇴실일인가
- 전기요금 전체 금액만 저장하면 되는가, 아니면 사용량(kWh)도 함께 저장해야 하는가
- 공실 기간 동안의 사용량은 별도 데이터로 남겨야 하는가
- 네이버 전기요금 계산기처럼 외부 계산 결과를 그대로 입력할 것인가, 아니면 시스템 안에서 계산 로직까지 가져갈 것인가
- 총무님이 직접 확인한 계량기 값은 어떤 형태로 저장해야 하는가
- 신규 입실자에게 전달할 최종 금액만 보여주면 되는가, 아니면 공실 구간에서 얼마나 제외되었는지도 함께 보여줘야 하는가
- 공실 기간 정산은 계약 단위로 봐야 하는가, 방 단위로 봐야 하는가
- PDF 출력이 잘못된 형태로 되지는 않을까
이 기능은 한 달 전기요금 하나를 저장하는 문제가 아니라, 퇴실자 사용 구간 / 공실 구간 / 신규 입실자 사용 구간을 어떻게 나누고, 그중 어떤 부분을 고시원 부담으로 볼 것인지를 시스템 안에서 표현해야 하는 문제였다.
특히 실제 운영에서는 총무님이 계량기 값을 확인하고, 공실 기간 동안 오른 사용량을 따로 계산한 뒤, 지로 금액에서 해당 금액을 빼서 신규 입실자에게 전달하고 있었다. 따라서 이 기능을 구현하려면 단순 금액 입력이 아니라, 정산 근거가 되는 원본값과 최종 전달 금액 사이의 흐름을 함께 정리해야 했다.
이 시점부터 공과금(한전) 기능은 단순한 공과금 입력 기능이 아니라, 공실 기간의 책임 구간을 어떤 데이터로 나누고 어떤 방식으로 정산 결과를 보여줄 것인가가 큰 문제였다.
5. 처음에는 이렇게 생각하고 화면을 만들었다.
- 처음에는 밑과 같이 도시가스와 한전 현금 승계 모두, 각 월마다 금액만 입력하고 관리하면 되는 기능처럼 보였기 때문이다. 그래서 초기 화면도 아래처럼 월별 금액을 등록하는 형태로 먼저 만들었다.
- 만들었다가 요구사항을 듣고 도시가스 기능은 제외했다.

- 하지만 이후 요구사항을 다시 듣는 과정에서, 도시가스 기능은 우선 제외하고 전기요금(한전) 현금 승계 기능만 집중해서 다루면 된다고 정리되었다. 이 시점부터 단순히 월별 금액을 적는 화면으로는 부족하다는 거이었다.
왜냐하면 실제 운영에서는 단순히 “이번 달 전기요금이 얼마인가”만 중요한 것이 아니라,
- 퇴실 시점의 계량기 값이 얼마였는지
- 공실 기간 동안 얼마나 사용되었는지
- 그 사용분 중 얼마를 고시원이 부담해야 하는지
- 신규 입실자에게는 최종적으로 얼마를 전달해야 하는지
같은 흐름이 함께 필요했기 때문이다.
그래서 총무님께 실제 시나리오를 다시 듣고 나서는, 화면을 아래처럼 정산 흐름을 더 잘 반영하는 형태로 바꾸게 되었다.

- 이후에는 여기서 한 단계 더 나아가, 단순히 화면에서 입력하고 끝나는 것이 아니라 실제 업무에서 바로 출력해 사용할 수 있도록 해야겠다고 생각했다. 그 과정에서 PDF 형태로 정리하기 쉽도록 임대인 / 임차인 구분까지 포함한 형태로 다시 화면을 나누어 입력하도록 변경했다.
그런데 여기서 또 문제가 있었다. 시나리오 형태로 했을 때 총무님이 원래 있던 입실자가 퇴실 한 후 그때 계량기 값을 측정을 해서 새로운 입실자가 들어오는 날인 전날에 계량기를 측정해서 얼마나 사용했는지를 기입을 해야하는데 이게 없었다.
예를 들어 3월 16일날 원래 있던 입실자가 퇴실을 해서 총무님은 3월 17일날 계량기 값을 기입 그후 새로운 입실자가 3월 22일날 들어온다고 하면 총무님은 3월 21일에 적혀있는 계량기 값을 기입해서 3월 21일 계량기값 - 3월 17일 계량기 값 전기요금 계산기로 해서 금액으로 바꾼 후에 지로에서 뺀 값을 임차인에게 보내주어야함
그런데 여기서 그 임차인이 들어오기전 계량기 값을 적을 수 있는 게 없었음

그래서 다음과 같이 추가.

테이블은 원래 다음과 같이 작성되어있었다. 바뀐 테이블에 대해서는 6번에서 더 설명해보겠다.

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가 들어간다
6.2 한전 승계
- 이 테이블은 contracts와 1:N 관계를 가진다.
- 밑 테이블을 보면 생성시간을 제외하고 전부 NULL이 가능하다 왜냐하면 시나리오 대로 한다고 했을 때 각각 들어가는 데이터가 들어기 때문이다.

- billing_start → 지로에서 온 청구 시작 기간
- billing_end → 지로에서 온 청구 끝 기간
- landlord_start → 임대인 부담 시작 기간 즉, 사장님께서 내야하는 금액
- landlord_end → 임대인 부담 끝 기간 즉, 사장님께서 내야하는 금액
- landload_start_meter → 임대인 기간 시작일 계량기 검침값
- landload_end_meter → 임대인 기간 종료일 계량기 검침값
- tenant_start → 임차인 부담 시작 기간 즉, 입실자가 내야하는 금액
- tenant_end → 임차인 부담 끝 기간 즉, 입실자가 내야하는 금액
- total_amount → 지로에 적힌 총 전기 요금
- total_kwh → 지로에 적힌 총 사용량 kwh 단위
- landlord_amount → 임대인이 내야하는 금액
- landlord_kwh → 임대인이 쓴 량 kwh 단위
- tenant_amount → 임차인이 내야하는 금액
- tenant_kwh → 임차인이 쓴 량 kwh 단위
- bank_name → 임차인이 임대인에게 송금해야할 계좌 정보 - 은행명
- account_holder → 임차인이 임대인에게 송금해야할 계좌 정보 - 예금주
- account_number → 임차인이 임대인에게 송금해야할 계좌 정보 - 계좌번호
- payment_date → 임차인이 임대인에게 송금 - 납부 일자
- notes - 비고
- created_at - 컬럼 생성 날짜
위를 이제 시나리오 대로 풀어나가 보자
6.2.1 [시나리오랑 맵핑 → 컬럼 연결]
1. 3월 16일에 사용자가 퇴실 총무님은 3월 17일에 전기 사용량을 확인한다 예를 들어 1060kWh
- landlord_start → 총무님은 해당 날짜를 기입한다.
- landload_start_meter → 총무님은 해당 날짜의 계량기 값을 기입한다.
2. 다음 입실자가 3월 20일에 들어온다. 총무님은 3월 19일에서 1060kWh에서 1062kWh를 확인하고 이력을 남겨놓는다.
- landlord_end → 총무님은 해당 날짜를 기입한다.
- landload_end_meter → 총무님은 해당 날짜의 계량기 값을 기입한다.
- landlord_kwh → 임대인이 쓴 량 kwh 단위
- landload_end_meter - landload_start_meter으로 자동 계산

3. 입실자는 3월 동안 고시원을 이용한다.
4. 3월에 대한 지로가 고시원에 오며 총무님께서는 17일~20일에 있던 0에서 2만큼 오른 값을 측정하기 위해 네이버에서 전기요금계산기로 들어간다.
전기요금계산기 : 네이버 검색
'전기요금계산기'의 네이버 검색 결과입니다.
search.naver.com
5. 다음과 같이 진행


- landlord_amount → 임대인이 내야하는 금액
6. 총무님은 지로에서 받은 값에서 1330원을 뺀 금액을 수기로 다시 만들어서 입실자에게 전달한다.
7. 총 금액은 고시원 사장님께서 계산하신다.

- billing_start → 지로에서 온 청구 시작 기간
- billing_end → 지로에서 온 청구 끝 기간
- tenant_start → 임차인 부담 시작 기간 즉, 입실자가 내야하는 금액
- tenant_end → 임차인 부담 끝 기간 즉, 입실자가 내야하는 금액
- total_amount → 지로에 적힌 총 전기 요금
- tenant_amount → 임차인이 내야하는 금액
- total_amount - landlord_amount 으로 자동 계산 값이 들어감
- tenant_kwh → 임차인이 쓴 량 kwh 단위
- total_kwh - landlord_kwh 으로 자동 계산 값이 들어감
- bank_name → 임차인이 임대인에게 송금해야할 계좌 정보 - 은행명
- account_holder → 임차인이 임대인에게 송금해야할 계좌 정보 - 예금주
- account_number → 임차인이 임대인에게 송금해야할 계좌 정보 - 계좌번호
- payment_date → 임차인이 임대인에게 송금 - 납부 일자


7. 입력한 값은 로직 안에서 이렇게 계산되고 사용되었다
7.1 임대인 구간 사용량은 어떻게 계산했는가
- landlord_start_meter
- landlord_end_meter
자동으로 다음과 같이 진행된다고 하였음
- landlord_kwh → 임대인이 쓴 량 kwh 단위
landlord_kwh = landlord_end_meter - landlord_start_meter
→ 둘 중 하나가 바뀔 때마다 개별적으로 재계산
<div>
<label className="mb-1 block text-xs text-gray-600">시작</label>
<input type="number" value={newCashForm.landlordStartMeter ?? ""} onChange={(e) => { const s = e.target.value === "" ? undefined : Number(e.target.value); setNewCashForm(p => { const kwh = s != null && p.landlordEndMeter != null ? Math.max(0, p.landlordEndMeter - s) : p.landlordKwh; return { ...p, landlordStartMeter: s, landlordKwh: kwh, tenantKwh: kwh != null ? (p.totalKwh ?? 0) - kwh : undefined }; }); }} placeholder="0.00" className={INPUT} />
</div>
<div>
<label className="mb-1 block text-xs text-gray-600">종료</label>
<input type="number" value={newCashForm.landlordEndMeter ?? ""} onChange={(e) => { const en = e.target.value === "" ? undefined : Number(e.target.value); setNewCashForm(p => { const kwh = en != null && p.landlordStartMeter != null ? Math.max(0, en - p.landlordStartMeter) : p.landlordKwh; return { ...p, landlordEndMeter: en, landlordKwh: kwh, tenantKwh: kwh != null ? (p.totalKwh ?? 0) - kwh : undefined }; }); }} placeholder="0.00" className={INPUT} />
</div>
- 시작값 입력 시
s 입력 → p.landlordEndMeter(이미 입력된 값)가 있으면 landlordKwh = endMeter - s 없으면 landlordKwh 그대로 유지
- 종료값 입력 시
en 입력 → p.landlordStartMeter(이미 입력된 값)가 있으면 landlordKwh = en - startMeter 없으면 landlordKwh 그대로 유지
즉, 둘 다 입력되어 있어야 자동계산이 되고, 한쪽만 입력되면 landlordKwh는 변하지 않는다. 실제 사용 흐름은:
- 시작 검침값 입력 → 종료값 없으므로 kWh 미계산
- 종료 검침값 입력 → 시작값 있으므로 종료 - 시작 = landlordKwh 자동계산
- 동시에 tenantKwh = totalKwh - landlordKwh 도 갱신
임대인 부담 구간은 시작일과 종료일의 계량기 검침값을 기준으로 계산하도록 했다. 총무님은 공실 구간 시작일과 종료일의 계량기 값만 입력하면 되고, 임대인 사용량(landlord_kwh)은 시스템에서 자동으로 계산되도록 했다. 이렇게 한 이유는 실제 운영에서 총무님이 직접 차이를 계산하는 부담을 줄이고, 입력 실수를 줄이기 위해서였다.
7.2 임차인 부담 금액은 어떻게 계산했는가
- tenant_amount = total_amount - landlord_amount
- tenant_kwh = total_kwh - landlord_kwh
- 왜 임차인 금액을 직접 입력받지 않고 계산값으로 뒀는지
- 원본 지로값과 공실 구간 부담분을 기준으로 자동 계산되게 한 이유
2개는 다음과 같다.
신규 입실자에게 전달할 금액은 총 전기요금에서 공실 기간 동안 고시원이 부담해야 하는 금액을 제외한 값으로 계산했다. 따라서 임차인 부담 금액(tenant_amount)은 total_amount - landlord_amount, 임차인 사용량(tenant_kwh)은 total_kwh - landlord_kwh로 자동 계산되도록 했다. 이렇게 하면 시스템 안에서 공실 구간 차감 근거와 최종 전달 금액이 하나의 흐름으로 연결된다
// 임대인 금액 변경 → tenant_amount = total - landlord
landlordAmount: v, tenantAmount: v != null ? (p.totalAmount ?? 0) - v : undefined
// 임대인 kWh 변경 → tenant_kwh = total - landlord
landlordKwh: v, tenantKwh: v != null ? (p.totalKwh ?? 0) - v : undefined
// 총 금액 변경 → tenant_amount = total - landlord
totalAmount: v, tenantAmount: v != null ? v - (p.landlordAmount ?? 0) : undefined
// 총 kWh 변경 → tenant_kwh = total - landlord
totalKwh: v, tenantKwh: v != null ? v - (p.landlordKwh ?? 0) : undefined
7.4 null 값은 어떤 상태를 의미하게 했는가
- landlord_start, landlord_end가 null이면 공실 구간 정산 전 상태
- landlord_amount가 null이면 아직 공실 기간 부담금이 확정되지 않은 상태
- tenant_amount가 null이면 최종 전달 금액이 아직 계산되지 않은 상태
- payment_date가 null이면 아직 임차인에게 납부 안내만 했거나 실제 송금 확인 전 상태
이렇게 쓰면 데이터가 단순히 빈 값이 아니라 업무 진행 상태를 나타내는 걸 보여줄 수 있다.
이 테이블에서 많은 컬럼을 nullable로 둔 이유는, 데이터를 한 번에 모두 입력하는 기능이 아니라 실제 업무 흐름에 맞춰 순차적으로 채워지는 기능으로 보았기 때문이다. 예를 들어 임대인 구간 검침값이 아직 입력되지 않았다면 landlord_kwh와 landlord_amount도 계산할 수 없으므로 null 상태를 유지한다. 즉 null은 단순 누락이 아니라, 아직 해당 정산 단계에 도달하지 않았음을 의미하도록 해석했다.
8. 마무리
이번 공과금(한전) 공실 기간 정산 기능은 개인적으로 꽤 어려운 기능이었다. 처음에는 단순히 전기요금 금액을 입력하고 보여주면 되는 기능처럼 보였지만, 실제로는 그렇지 않았다. 퇴실자, 공실 기간, 신규 입실자 사이에서 누가 어느 기간의 사용량을 부담해야 하는지를 나누어야 했고, 그 결과를 다시 임차인에게 전달할 수 있는 형태로 정리해야 했기 때문이다.
특히 이 기능은 내가 직접 경험해본 업무가 아니어서 더 어려웠다. 처음에는 “현금 승계”라는 말 자체도 익숙하지 않았고, 단순히 전기요금을 넘겨주는 과정 정도로만 생각했다. 하지만 총무님께 실제 시나리오를 여러 번 여쭤보고 나서야, 이 기능이 단순 금액 입력이 아니라 공실 구간을 분리해 책임 금액을 계산하는 정산 흐름이라는 점을 이해할 수 있었다.
이 과정을 통해 가장 크게 느낀 점은, 애매한 요구사항일수록 바로 화면부터 만들기보다 먼저 실제 운영이 어떤 순서로 이루어지는지 이해하는 과정이 필요하다는 점이었다. 이번 기능도 처음에는 월별 금액 입력 화면으로 시작했지만, 운영 흐름을 이해한 뒤에는 검침값, 공실 구간, 임대인 부담 금액, 임차인 부담 금액, PDF 출력까지 이어지는 구조로 다시 정리하게 되었다.
결국 이 기능은 “전기요금 입력 기능”이 아니라, 공실 기간 정산을 시스템 안에서 어떻게 표현할 것인가의 문제에 더 가까웠다. 그리고 그 과정을 정리하면서, 요구사항을 그대로 구현하는 것이 아니라 운영 시나리오를 데이터와 로직으로 번역하는 과정 자체가 개발에서 중요한 부분이라는 점을 다시 느끼게 되었다.
앞으로도 이런 기능들을 정리할 때 단순히 “무엇을 만들었는가”보다, 왜 어려웠고, 어떤 기준으로 해석했고, 결국 어떤 구조로 풀어냈는가를 함께 남겨보려고 한다. 그 과정이 있어야 실제 구현 과정에서 어떤 고민을 했는지가 더 잘 드러난다고 느꼈기 때문이다.
'외주 > 고시원 외주 개발 일지' 카테고리의 다른 글
| [외주] 클라이언트와의 첫 프리랜서 프로젝트에서 배운 것들 - 스코프 크리프와 커뮤니케이션 (0) | 2026.06.07 |
|---|---|
| [외주] 기능을 만든 후 배포하다! - 4/25 (0) | 2026.05.11 |
| [외주] 기획 요구사항에서 데이터 모델과 조회 로직까지 정리한 과정 - 보증금 차감과 반환을 하나의 흐름으로 볼지 분리할지 (1) | 2026.04.24 |
| [외주] 기획 요구사항에서 데이터 모델과 조회 로직까지 정리한 과정 - 예정 입실 기능을 어떻게 데이터로 분리했는가(기능 업데이트) - 4/19 (0) | 2026.04.19 |
| [외주] 배포하기 및 로그인 및 Supabase - 4/18 (1) | 2026.04.19 |