Data Architecture
한국과 일본을 한 시스템에서 운영할 수 있게 설계했습니다. 지금 실제로 돌고 있는 것은 일본 7물건 98실이고, 한국 트랙은 정책 23항목 중 다수가 미정이라 아직 열지 않았습니다. 물건 프로파일이 규칙을 갖고, 청구액은 확정 규칙을 넣은 엔진이 계산합니다.
Principle
나라별 차이는 조건문이 아니라 물건 프로파일에 담깁니다. 물건마다 아래를 지정하면 규칙이 따라옵니다. 지금 채워져 돌고 있는 것은 일본 쪽이고, 한국 트랙은 운영 정책 23항목 중 다수가 미정이라 아직 값을 넣지 않았습니다.
| 프로파일 | 한국 | 일본 |
|---|---|---|
| 청구 주기 | 미정 — 정책 협의 중 | 캘린더월 — 매월 1일~말일이 1개월. 첫·마지막 달만 그 달 실일수를 분모로 일할 (JC-01) |
| 일할 분모 | 미정 — 정책 협의 중 | 첫 달과 마지막 달만 그 달 실일수. 중간 달은 온전한 1개월 (JC-01) |
| 금액 반올림 | 미정 — 정책 협의 중 | 100엔 단위 올림 (JC-02) |
| 장기/단기 판정 | 미정 — 정책 협의 중 | 총 일수 31~180일 = 단기 / 181일 이상 = 장기. 30일 이하는 취급하지 않습니다 (JC-03) |
| 연장 처리 | 미정 — 정책 협의 중 | 모든 연장은 신규 계약으로 다시 판정합니다 (JC-04) |
| 보증금 | 미정 — 정책 협의 중 | 장기 = 월세 1개월분 / 단기 = 없음 (JC-05) |
| 청구 시점 | 미정 — 정책 협의 중 | 입주월 = 당월 일할 + 익월분 동시 청구. 이후 매월 첫 영업일에 익월분 (JC-06) |
| 갱신료 | 미정 — 정책 협의 중 | 직전 계약과 신규 계약이 둘 다 장기일 때만 신규 임대료의 10% (JC-07) |
| 관리수수료 | 미정 — 정책 협의 중 | 위탁운영 = 월임대료 × 5% × 1.1 / 마스터리스 = 월수입 − 원가(고정비) |
| 원상회복 | 미정 — 정책 협의 중 | 청소 2,000엔/㎡ + 에어컨 25,000엔/대 |
| 중도퇴거 | 미정 — 정책 협의 중 | 계약 화면에서 중도퇴거로 표시합니다. 위약금 계산 규칙은 아직 확정되지 않았습니다 |
규칙은 문서로 확정한 뒤 엔진에 박았습니다. 위 일본 규칙은 JC-01~JC-07로 번호를 붙여 고정했고, 청구 엔진 회귀 테스트 47건이 이 규칙들을 잠그고 있습니다. 한국 값은 아직 비어 있습니다 — 채우기 전에 열면 두 나라 중 하나가 반드시 틀립니다.
Tables
마스터 · 원장 · 기록을 구분합니다. 원장은 사실을 쌓고, 기록은 그 사실이 언제 왜 바뀌었는지를 남깁니다.
Pricing
요금은 호실의 «컬럼»이 아니라 «행»으로 섭니다. 구간을 컬럼으로 두면 구간이 하나 늘 때마다 컬럼을 추가해야 하고, 물건마다 다른 개수를 담을 수 없습니다. 일본 구간은 단기·장기 둘이고, 판정 기준은 개월수가 아니라 총 일수입니다.
| 구간 | 기간 | 보증금 | 납부 |
|---|---|---|---|
| 단기 | 총 31 ~ 180일 | 없음 (JC-05) | 입주월 = 당월 일할 + 익월분 동시. 이후 매월 첫 영업일에 익월분 (JC-06) |
| 장기 | 총 181일 이상 | 월세 1개월분 (JC-05) | 입주월 = 당월 일할 + 익월분 동시. 이후 매월 첫 영업일에 익월분 (JC-06) |
일본 기준입니다. 30일 이하는 취급하지 않습니다(JC-03). 모든 연장은 신규 계약으로 다시 판정하므로(JC-04) 구간도 그때 다시 결정됩니다. 금액은 100엔 단위로 올립니다(JC-02). 갱신료는 직전·신규가 둘 다 장기일 때만 신규 임대료의 10%입니다(JC-07).
호실 테이블에 요금 컬럼을 만들지 않습니다. 만들면 물건이 늘 때마다 마이그레이션이 필요합니다. 다만 요금·면적·원가·에어컨 마스터는 아직 앱에서 편집할 수 없습니다 — 현재는 시트에서 수정하고 있고, 마스터 편집 화면은 아직 없습니다.
Ledger
PostgreSQL 마이그레이션 20개로 서 있습니다. 모든 쓰기는 audit_log 트리거를 지나 같은 원장에 남습니다. 이 원장은 운영 콘솔(freymadmin.llnpco.dev, 사이트 전체 인증)에만 붙어 있고, 지금 보고 계신 소개 사이트(freym.llnpco.dev)는 공개면이라 실데이터를 담지 않습니다.
Policies
스키마만으로는 장부가 되지 않습니다. 아래가 구현에 들어간 설계 원칙입니다.
superseded_by로 덧쓰고 물리 삭제하지 않습니다. 퇴거한 계약도 목록에서 사라지지 않습니다(현재 퇴거 6건).audit_log에 트리거로 기록됩니다. 시트에는 변경 이력이 아예 없었습니다.TODAY()에 의존해 열 때마다 값이 달라지던 문제의 반대편입니다.통화는 법인에서 따라옵니다. 물건과 거래가 각자 정하면 반드시 어긋납니다. 금액은 통화 코드를 함께 들고 다니고, 통화가 다르면 합계를 합치지 않습니다 — 환산해서 한 줄로 만들면 그 환율이 곧 근거 없는 숫자가 됩니다.
Verification
구글 스프레드시트 1개(18탭 · 77,000셀 · 49,400수식)로 운영하던 것을 이 원장으로 이관했습니다. 시트는 아직 정본이고 전환 시점은 협의 중입니다. 금액은 화면에서 계산하지 않고, 확정 규칙을 넣은 엔진이 산출합니다 — 시트 값을 옮겨 적지 않습니다.
청구 엔진 회귀 테스트 47건. 시트 대조 — 월별 발생 533개월 중 완전일치 494건(93%) · 단수차 36건 · 실제 차이 3건. 청구 이벤트 337건 중 완전일치 303건(90%). 대조에 쓴 시트 사본 원장행 31,920.
그래서 원장을 이렇게 세웠습니다. 시트에서 실측으로 확인한 문제는 넷이었습니다 — ①청구한 사실이 기록되지 않고 계산이 TODAY()에 의존해 열 때마다 값이 달라짐 ②수납을 입주자 «이름 문자열»로 조인해 실제 ¥58,777,660 중 14.2%만 매칭 ③「호실 정보」를 참조하는 수식이 워크북 전체에 0개(요금 마스터 미연결) ④변경 이력 없음. append-only 원장 · audit_log 트리거 · 청구서 스냅샷 · 확정 규칙 엔진은 각각 이 넷에 대응합니다.
Accounting
원상회복비(청소 2,000엔/㎡ + 에어컨 25,000엔/대) · 갱신료 · 관리수수료 · 공과금… 항목은 계속 늘어납니다. 그때마다 개발하지 않도록 항목을 데이터로 정의합니다. 조정금 처리(JX-03)는 이번 범위에서 제외했습니다 — 아직 없습니다.
구분은 청구 · 수납 · 지출이고, 청구 − 수납 = 미수금입니다. 청구 회차는 이미 테이블로 서 있고, 확정 규칙이 활성 계약 44건 전부를 계산합니다(차단 0). 시트에서는 수납이 입주자 이름 문자열로 조인돼 ¥58,777,660 중 14.2%만 매칭됐고, 그래서 나오던 「차액」 ¥72,758,400은 미수금이 아니라 허수였습니다. 온라인 결제는 아직 없습니다.