← 문서 목록

데이터베이스 테이블·컬럼 정의서

NestPay 선불 지갑 플랫폼 · 실 DB(information_schema) + schema.dbml 컬럼 주석 기준

근거 본 정의서는 로컬 실 DB nestpay(MariaDB, docker nestpay-mariadb)의 information_schema 실측값과 설계 원본 db/schema.dbml의 컬럼 주석을 대조하여 작성하였습니다. 모든 수치(테이블·컬럼·인덱스·트리거·파티션·시스템 버저닝)는 조회 시점의 실제 DB 상태입니다.

공통 규약 — 금액은 DECIMAL(15,0) KRW 정수, 시각은 DATETIME(KST 단일), 문자셋 utf8mb4. 개인정보는 *_enc=AES-256-GCM 암호문, *_hash=검색·UNIQUE용 HMAC-SHA256(char(64)). 비밀번호·PIN·API시크릿은 Argon2id(varchar(255)).

1. 요약 — 테이블 구성 총계

69
전체 테이블 (도메인 68 + flyway_schema_history)
595
전체 컬럼
208
인덱스 (PK 포함, 중복 제거)
51
외래키(FK) 제약
52
BASE TABLE (일반 테이블, flyway 포함)
17
SYSTEM VERSIONED (시스템 버저닝)
7
월 RANGE 파티션 테이블
14
append-only 방어 트리거

테이블 유형 구분

transactions·deposit_notices비파티션 확정 — MariaDB는 파티션 테이블의 모든 UNIQUE 키에 파티션 컬럼 포함을 강제하는데, 멱등성 UNIQUE(ux_txn_idem·ux_notice_ref)에 created_at을 넣으면 멱등 보장이 깨지므로 무결성을 우선함(실 DB 검증으로 확정).

외부연동 스텁 상태(계약 전) 확인필요/미구현

펌뱅킹(출금이체·잔액조회), 본인인증(CI/DI), 은행 실명조회·1원인증, 발주사 PG 가상계좌 입금통지는 계약·규격서 확정 전으로 스키마만 완비된 스텁 상태입니다. 관련 컬럼(deposit_identifiers.kind/value, deposit_notices.source, bank_tran_ref, ci_hash·di_hash 등)의 최종 규격은 규격서 회신 후 고정됩니다. 포인트 전환(exchange_providers, EXCHANGE_*)은 설계 유지·구현 보류 상태입니다.

2. 도메인 그룹별 테이블 목록

68개 도메인 테이블을 업무 도메인 12개 그룹으로 분류. 유형: BASE VERSIONED PART · ★ = 아래 3장에 컬럼 전체 수록(핵심 20개 테이블).

2.1 회원·인증 (10)

테이블유형용도
users ★VERSIONED회원 마스터. 본인인증 실명·CI·전화(암호화), 1인 1활성계정 강제(active_ci UNIQUE), 탈퇴 후 법정보존·파기 일정.
account_closure_requestsBASE회원 탈퇴 신청·승인 대장. 승인 시 WITHDRAWN+포인트 소멸, 소멸금액 기록.
auth_pinsBASE간편로그인+거래인증 PIN(Argon2id). 계정 3종 공용(principal_type), 5회 초과 잠금.
auth_passkeysBASEFIDO2/WebAuthn 패스키(자격증명·공개키). 계정 3종 공용.
used_challengesBASE패스키 챌린지 1회용 소진 기록 — 등록·로그인·거래서명 replay 방지.
auth_devicesBASE기기 등록(설치 식별자). 동시 1기기(새 기기 등록 시 기존 REVOKED), FDS 다계정기기 역조회.
login_historiesPART로그인 이력(성공·실패·차단). 사용자 화면+보안감사, 월 파티션·5년 보존·방어 트리거.
bank_accounts ★VERSIONED은행 계좌(사용자·매장 공용). 계좌번호 암호화, 실명+1원인증, 변경 시 REMOVED 이력보존·24h 냉각.
rate_limit_rulesBASE동작별 호출 빈도 제한 규칙(관리자 조정). 창(초)·최대횟수·기준(IP/USER).
rate_limit_countersBASE고정창 카운터(초과 시 429). 오래된 창은 배치 정리.

2.2 카드·지갑·포인트 (3)

테이블유형용도
cards ★VERSIONED앱 카드. 카드번호=지갑 식별자, number_hash UNIQUE로 재사용 영구차단, 발급+5년 만료, 재발행 체인.
wallets ★BASE지갑(USER_CARD·MERCHANT·SYSTEM). 잔액 캐시. 사용자·매장=FOR UPDATE 잠금, SYSTEM=일 배치 파생.
point_lots ★BASE포인트 로트(유상 DEPOSIT/무상 REWARD). 유효기간 FIFO 소진, 감소만 허용(방어 트리거).

2.3 원장·거래 (3)

테이블유형용도
transactions ★BASE거래 헤더(단일 테이블, type/subtype 분기). append-only, 사용자스코프 멱등키 UNIQUE, 각종 스냅샷.
ledger_entries ★PART복식 원장(DR/CR). 거래별 ΣDR=ΣCR, 잔액 체인, append-only 절대(월 파티션·방어 트리거).
lot_allocations ★BASE차감:로트 배분(N:M). FIFO 소진·취소 복원 근거.

2.4 충전·입금 (4)

테이블유형용도
deposit_identifiersVERSIONED회원별 입금 식별자(가상계좌/입금자코드). 펌뱅킹 계약 확정 후 단일화 (규격 확인필요).
deposit_notices ★BASE입금통지(PG 웹훅·펌뱅킹·SMS). 소스별 결정적 중복키 UNIQUE, 원문 증거보존(비파티션·방어 트리거).
unmatched_deposits ★BASE미매칭 입금 — 즉시 UNMATCHED 시스템 지갑 계상(장부 밖 돈 없음). 관리자 재량 처리·반환.
deposit_accountsBASE회사 수납 입금통장(관리자 등록·앱 충전화면 안내).

2.5 선물 (1)

테이블유형용도
gift_links ★BASE선물 링크. 선차감(GIFT_ESCROW 계상)·1회용 클레임 토큰(해시)·TTL 24h 만료 자동반환.

2.6 매장·QR·PG결제 (8)

테이블유형용도
merchants ★VERSIONED매장 마스터. 사업자번호(진위확인)·대표자 본인인증·부가세 모드/율. 심사 상태머신(대표자 변경=재심사).
merchant_accounts ★VERSIONED매장 로그인 계정(매장 1계정, 하위계정 미도입).
merchant_qrs ★BASE매장 QR(정적·동적·주문형). CPM/수취 QR은 Redis 단명 토큰(DB 미저장).
merchant_api_credentials ★VERSIONED매장 open API 자격증명. 시크릿 해시·키 롤 유예·웹훅 URL(암호화 시크릿)·LIVE 전환 체크리스트.
merchant_api_allowed_ipsBASE매장 open API 화이트 IP(매장 신청·관리자 승인). 승인분만 호출 허용.
merchant_documentsBASE매장 필수 서류(사업자등록증 등). 전부 제출되어야 승인 가능(중앙 파일 대장 참조).
pg_orders ★BASEPG 온라인 결제 주문. (merchant_id, order_no) 멱등, 공급가/부가세, 샌드박스 원장 분리.
webhook_deliveriesBASE매장 발신 웹훅. 지수 백오프 재시도, 클레임 토큰으로 2대 서버 중복발송 방지.

2.7 정산·명세 (3)

테이블유형용도
monthly_statementsBASE카드 월 명세(충전·출금·결제·선물·소멸·수수료·월말잔액). 월 단위 대사 겸용.
merchant_monthly_statementsBASE매장 월 정산서(카드사 동일 수준). 매출·취소·공급가·부가세·수수료·정산·월말잔액.
merchant_daily_summariesBASE매장 일 차트 집계(멱등 재계산). 과거=본 테이블, 당일=실시간, 접합은 UNION.

2.8 정책 (8)

테이블유형용도
fee_policies ★VERSIONED수수료 정책(유형·범위). 정률+정액 합산, 거래에 스냅샷 저장.
limit_policiesVERSIONED한도 정책(충전·보유·출금·선물·결제 × 건당/일/월/보유). 사용자 전 카드 합산 집행.
payout_policies ★VERSIONED정산/출금 대기(+N일 HH시). 매장 기본 delay=0(즉시 정산), 값만 바꾸면 대기 적용.
cancel_policiesVERSIONED결제 취소 가능기간(N일). 거래에 cancelable_until 스냅샷.
card_quota_policiesVERSIONED카드 발급 수량 상한(ACTIVE 카드 기준). 전역·사용자별.
point_expiry_policiesVERSIONED포인트 유효기간(DEPOSIT/REWARD 개월). 충전성 값은 법무 확인 후 설정.
global_settingsVERSIONED단일값 전역 설정(재가입 대기·점검 모드·앱 최소버전·냉각시간 등). 변경 이력 자동 보존.
exchange_providersBASE포인트 전환 공급자·환율. 설계 유지·구현 보류(#49).

2.9 FDS(이상거래 탐지) (2)

테이블유형용도
fds_rulesVERSIONED탐지 룰 8종(통과·선물집중·자가결제·취소남용 등). 임계값 JSON, 배포 없이 관리자 조정.
fds_alertsBASE탐지 경보. 근거 JSON(증거보존), 처리 상태(OPEN→REVIEWED→ACTIONED/DISMISSED).

2.10 콘텐츠·고객지원·약관 (7)

테이블유형용도
noticesBASE공지·이벤트(대상 앱·강제팝업·이미지·링크·게시기간).
bannersBASE앱 배너(노출 위치·이미지·링크·정렬·게시기간). 중앙 파일 대장 참조.
faqsBASEFAQ(카테고리·질문·답변·정렬·게시 상태).
inquiriesBASE1:1 문의(사용자·매장). 답변 시 푸시 통지, 미답변 큐.
inquiry_attachmentsBASE문의 첨부 이미지(최대 5장/장당 10MB). 중앙 파일 대장 참조.
policy_documentsBASE약관·개인정보·탈퇴안내 문서(버전·시행일·재동의 여부). 과거 버전 영구보존.
policy_agreementsBASE약관 동의 이력(분쟁 대비 증빙). 주체×문서 UNIQUE.

2.11 알림·푸시 (5)

테이블유형용도
notification_settingsBASE이벤트별 알림 발송 설정(채널 INBOX/PUSH/BOTH·심각도). 관리자 조정, OutboxWorker 참조.
notification_inboxPART앱 알림함. 푸시 발송과 동일 outbox 작업에서 원자적 기록, 월 파티션·30일 보존.
push_tokensBASEFCM 토큰(계정 3종 공용·플랫폼별).
push_campaignsBASE푸시 캠페인(대상·광고성·예약·발송/실패 집계). 광고성=동의자만+야간 차단.
push_campaign_targetsBASE지정 발송 대상+개별 발송 결과(도달 분석). JSON 금지 원칙의 연결 테이블.

2.12 관리자·감사·운영·로그·대사 (14)

테이블유형용도
admin_accountsVERSIONED관리자 계정(OTP 의무·잠금). 관리자 전원 동등, 변경 이력 보존.
admin_allowed_ipsVERSIONED관리자 접근 허용 IP/CIDR(공통·개인 규칙). 규칙 관리·이력 보존.
filesBASE중앙 파일 대장 — 모든 업로드는 이 한 테이블로만, 타 테이블은 file_id 참조. 실물은 오브젝트 스토리지.
audit_logsBASE관리자 행위 감사(변경 전후 JSON·사유 필수). append-only(방어 트리거).
pii_access_logsPART개인신용정보 접근기록(감독규정). *_enc 복호화 표시 API 전부에 기록, 월 파티션·5년 보존·방어 트리거.
outbox_jobs ★BASE비동기 작업 아웃박스 — 원장 트랜잭션과 같은 커밋에 INSERT(후속작업 유실 불가). 클레임 토큰 방식.
external_api_logsPART대외 호출 전건(요청·응답 마스킹 보존). 리컨실러·분쟁 판정 근거, 월 파티션·방어 트리거.
reject_logsPART거래 생성 전 거절 시도 기록(CS 즉답·FDS 열거 탐지). 월 파티션·방어 트리거.
app_error_logsPART서버 예외 요약(운영자 화면·알림). 전체 스택은 파일 로그, trace_id 연결. 월 파티션.
integrity_check_runsBASE무결성 검증 실행 이력(복식·잔액체인·격리 등 9종). 모니터링 대시보드 원천.
integrity_findingsBASE이상 건 개별 추적(발견→역분개 조정 해소). 기대값 vs 실제값.
daily_wallet_snapshotsBASE희소 일 잔액 스냅샷(감사 확정). 체인 검증 재개점, ODKU 멱등 적재.
daily_summariesBASE전역 일 지표(충전·결제·신규회원 등). 대시보드·추이 그래프 원천.
hourly_summariesBASE전역 당일 시간대 추이(시간 배치·90일 보존).

※ 위 68개 외 flyway_schema_history(BASE)는 Flyway 마이그레이션 적용 이력 관리용 시스템 테이블입니다.

3. 핵심 테이블 컬럼 정의 (20개)

NULL 열: N=NOT NULL(필수), Y=NULL 허용. 키 열: PK기본키 UQ유니크 IX인덱스/FK. 설명은 실 DB 컬럼 코멘트 및 schema.dbml 주석 기준.

3.1 users — 회원 마스터 VERSIONED

컬럼타입NULL설명
idbigintNPK회원 고유번호(auto_increment)
login_idvarchar(20)NUQ영숫자 4~20, 소문자 정규화 저장
password_hashvarchar(255)NArgon2id 해시
namevarchar(100)N본인인증 실명
name_normvarchar(100)N이름 비교용 정규화(공백·특수문자 제거, 로마자화)
ci_hashchar(64)NIX본인인증 CI HMAC. 재가입 대기 판정
active_cichar(64)YUQACTIVE일 때만 ci_hash 복사 — UNIQUE로 1인 1활성계정 강제
di_hashchar(64)Y본인인증 DI HMAC
phone_encvarbinary(64)N전화번호 AES-256 암호문
phone_hashchar(64)NIX선물 대상 검색용 HMAC
birth_datedateY본인인증 결과. 성인 전용 검증
gendervarchar(1)Y성별 M|F (본인인증 결과)
avatar_file_idbigintYIX프로필 사진(files.id 참조). NULL=기본 아이콘
marketing_agreetinyint(1)N광고성 푸시 수신동의(기본 0)
statusvarchar(20)NIXACTIVE|SUSPENDED|WITHDRAWN (기본 ACTIVE)
kyc_statusvarchar(20)NVERIFIED|PENDING(관리자 사전생성 - 앱서 본인인증 대기)
withdrawn_atdatetimeY탈퇴 시각 - 재가입 대기 판정 기준
destroy_due_atdateY개인정보 파기 예정일 = 탈퇴+법정보존
anonymized_atdatetimeY파기(익명화) 완료 시각 - phone_enc·name·birth_date 무효화
created_atdatetimeN가입 일시

3.2 cards — 앱 카드 VERSIONED

컬럼타입NULL설명
idbigintNPK카드 고유번호
user_idbigintNIX소유 회원(users.id)
number_hashchar(64)NUQ재사용 영구 차단의 단일 진실. 삭제 금지
number_encvarbinary(64)N카드번호 암호문. BIN 972963 + 랜덤9 + Luhn, 16자리
cvc_encvarbinary(32)N고정 CVC. 표시용, 서버 암호화 보관
issued_atdatetimeN발급 일시
expires_ondateN발급+5년 그 달 말일. 만료 시 재발행 절차
design_codevarchar(20)N카드 디자인 코드(OCEAN|MIDNIGHT|SUNSET 등)
color_codevarchar(20)Y사용자 선택 색상
is_primarytinyint(1)N대표 카드 = 기본 수취(기본 0)
statusvarchar(20)NACTIVE|SUSPENDED|REISSUED|EXPIRED (기본 ACTIVE)
reissued_tobigintYIX재발행 체인 참조(cards.id)
created_atdatetimeN생성 일시

3.3 wallets — 지갑 BASE

컬럼타입NULL설명
idbigintNPK지갑 고유번호
owner_typevarchar(12)NIXUSER_CARD|MERCHANT|SYSTEM
card_idbigintYUQUSER_CARD일 때만, 카드 1:1
merchant_idbigintYUQMERCHANT일 때만. 정산 출금·취소 반환 전용
system_codevarchar(30)YUQSYSTEM일 때만: FEE_REVENUE|EXPIRED|GIFT_ESCROW|UNMATCHED|SETTLEMENT_CLEARING|FORFEITED|EXCHANGE_{제휴사}
balancedecimal(15,0)N잔액. CHECK: SYSTEM 제외 balance≥0. 사용자·매장=FOR UPDATE 잠금 지점, SYSTEM=일 배치 파생(기본 0)
created_atdatetimeN생성 일시

CHECK: owner_type별 해당 참조 컬럼만 NOT NULL(마이그레이션 정의).

3.4 point_lots — 포인트 로트 BASE

컬럼타입NULL설명
idbigintNPK로트 고유번호
wallet_idbigintNIX소속 지갑(wallets.id)
lot_typevarchar(10)NIXDEPOSIT(유상: 결제·선물·출금·환급 가능)|REWARD(무상: 결제만). 환급은 소스 무관 전체 DEPOSIT 잔액 기준
sourcevarchar(30)NDEPOSIT|GIFT|REISSUE|EVENT|EXCHANGE:{code}(구현보류) - 이력 메타(환급 판정 미사용)
amount_initdecimal(15,0)N최초 적립 금액
amount_remainingdecimal(15,0)N잔여. CHECK(0≤remaining≤init). 감소만 허용(방어 트리거)
expires_atdatetimeNIX유효기간(필수). 재발행 이관은 승계, 선물 수취는 리셋
origin_lot_idbigintYIX재발행 승계 시 원 로트 참조(point_lots.id)
created_atdatetimeN생성 일시

3.5 transactions — 거래 헤더 BASE (비파티션·멱등 우선)

컬럼타입NULL설명
idbigintNPK거래 고유번호
txn_uidchar(26)NUQ대외 노출용 ULID
typevarchar(12)NIXDEPOSIT|WITHDRAW|GIFT|PAYMENT|CANCEL|ADJUST|EXPIRE
subtypevarchar(20)NVACCT|FIRMBANK|REISSUE|GIFT_LINK|GIFT_PHONE|GIFT_QR|QR_STORE|QR_ORDER|CPM|PG_ONLINE|SETTLEMENT|FORFEIT 등
statusvarchar(12)NIXPENDING|HOLD|UNKNOWN|CONFIRMED|FAILED|REVERSED|CANCELED - 선차감·리컨실러 상태머신
initiator_typevarchar(10)NIXUSER|MERCHANT|ADMIN|SYSTEM
initiator_idbigintN주체 식별자(기본 0)
idempotency_keyvarchar(100)YUQUNIQUE(initiator_type, initiator_id, idempotency_key) - 사용자 스코프 멱등
card_idbigintYIX거래 카드(cards.id)
counterparty_card_idbigintYIX선물 수신 카드 - 받은선물·gift_recv 집계·FDS 선물집중 키
merchant_idbigintYIX매장(merchants.id)
amountdecimal(15,0)N거래 금액
fee_amountdecimal(15,0)N수수료 금액(기본 0)
fee_rate_snapdecimal(7,4)Y적용 정률 스냅샷
fee_fixed_snapdecimal(15,0)Y적용 정액 스냅샷
vat_amountdecimal(15,0)Y결제 시점 부가세 스냅샷
cancelable_untildatetimeY결제 시점 취소기한 스냅샷
scheduled_atdatetimeY출금·정산 실행 예정 시각 - payout_policies 스냅샷(정책 변경 소급 방지)
related_txn_idbigintYIX역분개·이관·취소의 원거래 참조
bank_tran_refvarchar(64)YIX펌뱅킹 거래 식별자 - 리컨실러 조회 키
bank_account_idbigintYIX출금·정산 대상 계좌 스냅샷(이후 변경돼도 불변)
detail_idbigintY거래상세 PK 참조 - (type,subtype)이 상세 테이블 결정(재논의 예정)
pg_order_idbigintYPG 온라인 결제 주문 참조(detail_id의 PG 사례)
fail_reasonvarchar(30)YMERCHANT_INSUFFICIENT_BALANCE|CANCEL_WINDOW_EXPIRED 등 코드
memovarchar(200)Y선물 메시지(50자·금칙어 필터) 등
created_atdatetimeNIX생성 일시
confirmed_atdatetimeY확정 일시

3.6 ledger_entries — 복식 원장 PART (월 파티션·append-only)

컬럼타입NULL설명
idbigintNPK실PK는 (id, created_at) - 월 파티셔닝
txn_idbigintNIX거래(transactions) - 파티션 간 FK는 논리 참조(앱 강제)
wallet_idbigintNIX대상 지갑(wallets.id)
directionchar(2)NDR|CR. 거래별 ΣDR=ΣCR (복식·Java 검증+일 대사)
amountdecimal(15,0)N금액. CHECK(amount > 0)
balance_afterdecimal(15,0)Y사용자·매장 지갑=NOT NULL 체인. SYSTEM 지갑 leg=NULL(핫로우 규약, 일 배치 SUM 검증)
created_atdatetimeNPK생성 일시(파티션 키)

3.7 lot_allocations — 차감·로트 배분 BASE

컬럼타입NULL설명
idbigintNPK배분 고유번호
ledger_entry_idbigintNIX차감(DR) 엔트리. 취소 시 원 소진 로트 역추적
lot_idbigintNIX소진 로트(point_lots.id)
amountdecimal(15,0)N이 로트에서 차감한 금액

3.8 bank_accounts — 은행 계좌 VERSIONED

컬럼타입NULL설명
idbigintNPK계좌 고유번호
owner_typevarchar(10)NIXUSER|MERCHANT
owner_idbigintN소유자 식별자
bank_codevarchar(10)N은행 코드
account_encvarbinary(128)N계좌번호 AES-256 암호문(법적 암호화 의무)
account_hashchar(64)N중복 등록 검사용 HMAC
holder_namevarchar(100)N실명인증 예금주
holder_name_normvarchar(100)N정규화 prefix 비교
verified_atdatetimeY실명+1원인증 완료 시각(순서: 실명일치→1원인증) 외부연동 스텁
statusvarchar(20)NACTIVE|REMOVED - 변경 시 REMOVED 처리, 이력 보존(기본 ACTIVE)
cooldown_untildatetimeY계좌 변경 후 출금 냉각 24h
created_atdatetimeN등록 일시

출금은 ACTIVE 계좌 1건으로만. ACTIVE 1건 보장은 앱 트랜잭션.

3.9 merchants — 매장 마스터 VERSIONED

컬럼타입NULL설명
idbigintNPK매장 고유번호
biz_novarchar(10)NUQ사업자등록번호(국세청 진위확인) 외부연동 스텁
biz_namevarchar(200)N상호
ceo_namevarchar(100)N대표자명
ceo_name_normvarchar(100)N대표자명 정규화
ceo_ci_hashchar(64)N대표자 본인인증 CI
biz_typevarchar(20)NCORP(법인)|SOLE(개인사업자)
categoryvarchar(50)Y업종
addressvarchar(300)Y주소
vat_modevarchar(10)NTAXED|EXEMPT - 매장이 설정(기본 TAXED)
vat_ratedecimal(5,2)N부가세율(기본 10.00). 결제 시점 스냅샷의 원천
statusvarchar(20)NIXPENDING|SUPPLEMENT|ACTIVE|REJECTED|SUSPENDED|CLOSED (기본 PENDING)
reject_reasonvarchar(500)Y반려 사유
supplement_notevarchar(500)Y자료 보충 요청 사유(SUPPLEMENT 상태 표시)
approved_bybigintYIX승인 관리자(admin_accounts.id)
approved_atdatetimeY승인 일시
created_atdatetimeN신청 일시

3.10 merchant_accounts — 매장 로그인 계정 VERSIONED

컬럼타입NULL설명
idbigintNPK계정 고유번호
merchant_idbigintNUQ소속 매장(매장 1계정, 하위계정 미도입)
login_idvarchar(20)NUQ로그인 아이디
password_hashvarchar(255)NArgon2id 해시
statusvarchar(20)N계정 상태(기본 ACTIVE)
created_atdatetimeN생성 일시

3.11 deposit_notices — 입금통지 BASE (비파티션·멱등 우선·방어 트리거)

컬럼타입NULL설명
idbigintNPK통지 고유번호
sourcevarchar(10)NUQPGVACCT(PG 가상계좌 웹훅)|FIRMBANK(펌뱅킹 조회)|SMS(보조) 외부연동 스텁
raw_texttextYSMS 원문 보존(증거 보존 - 절단 방지 TEXT)
dedup_keychar(64)NUQ소스별 결정적 중복키. SMS=HMAC, 펌뱅킹=bank_tran_ref 사본
bank_tran_refvarchar(64)Y펌뱅킹 거래 식별자
parsed_amountdecimal(15,0)Y파싱 금액
parsed_namevarchar(100)Y파싱 입금자명
parsed_name_normvarchar(100)Y정규화 prefix 매칭용
identifier_valuevarchar(64)Y가상계좌/입금자코드 파싱값
statusvarchar(20)NIXNEW|MATCHED|UNMATCHED|IGNORED (기본 NEW)
matched_txn_idbigintY매칭 성사 시 DEPOSIT 거래 참조
received_atdatetimeN수신 일시

3.12 unmatched_deposits — 미매칭 입금 BASE

컬럼타입NULL설명
idbigintNPK고유번호
notice_idbigintNIX원 입금통지(deposit_notices.id)
amountdecimal(15,0)N입금 금액
statusvarchar(20)NPENDING|MATCHED|RETURNED|HOLD - 관리자 재량 처리(기본 PENDING)
resolved_bybigintYIX처리 관리자(admin_accounts.id)
resolved_atdatetimeY처리 일시
resolutionvarchar(20)YMANUAL_MATCH|RETURN|HOLD
resolution_notevarchar(500)Y사유 필수 - 원장 역분개와 이중 기록
return_methodvarchar(30)Y반환 방법(펌뱅킹 이체 등)
return_bank_codevarchar(10)Y반환 은행 코드
return_account_encvarbinary(128)Y반환 계좌 AES-256(암호화 의무)
created_atdatetimeN생성 일시

입금 즉시 UNMATCHED 시스템 지갑에 원장 계상 - 장부 밖 돈 없음.

3.13 gift_links — 선물 링크 BASE

컬럼타입NULL설명
idbigintNPK선물 고유번호
sender_card_idbigintNIX보낸 카드(cards.id)
hold_txn_idbigintN선차감(GIFT_ESCROW 계상) 거래
token_hashchar(64)NUQ클레임 토큰(1회용) - 원문 미저장
amountdecimal(15,0)N선물 금액
messagevarchar(50)Y선물 메시지(금칙어 필터)
expires_atdatetimeNIXTTL 24시간 - 만료 시 자동 반환
statusvarchar(20)NCREATED|CLAIMED|EXPIRED|CANCELED(송금인 회수) (기본 CREATED)
claimed_card_idbigintYIX수령 카드(수령자 대표 카드)
claimed_atdatetimeY수령 일시

3.14 pg_orders — PG 온라인 결제 주문 BASE

컬럼타입NULL설명
idbigintNPK주문 고유번호
merchant_idbigintNUQ매장(merchants.id)
order_novarchar(64)NUQ쇼핑몰 주문번호 - UNIQUE(merchant_id, order_no) 멱등
amountdecimal(15,0)N결제 금액
supply_amountdecimal(15,0)Y공급가액
vat_amountdecimal(15,0)N부가세(PG API로 수신·보관)
item_namevarchar(200)Y상품명
qr_idbigintYIX연결 QR(merchant_qrs.id)
txn_idbigintY결제 성사 시 거래 참조
statusvarchar(20)NIXCREATED|PAID|CANCELED|EXPIRED (기본 CREATED)
expires_atdatetimeY주문 만료 시각 - 만료 스위퍼 기준
paid_atdatetimeY결제 완료 시각
canceled_atdatetimeY취소·환불 시각
is_sandboxtinyint(1)N테스트 주문 실원장 완전 분리(기본 0)
created_atdatetimeN생성 일시

3.15 merchant_qrs — 매장 QR BASE

컬럼타입NULL설명
idbigintNPKQR 고유번호
merchant_idbigintNIX매장(merchants.id)
qr_typevarchar(15)NSTORE_STATIC|STORE_DYNAMIC|ORDER (CPM·수취는 Redis 단명 토큰)
labelvarchar(50)Y카운터1 등 - 매장당 복수 QR
amountdecimal(15,0)YORDER형만
key_versionint(11)NAES-GCM 키 버전(기본 1)
statusvarchar(20)NACTIVE|REVOKED|USED(ORDER 1회용) (기본 ACTIVE)
expires_atdatetimeYDYNAMIC/ORDER TTL
created_atdatetimeN생성 일시

3.16 merchant_api_credentials — 매장 API 자격증명 VERSIONED

컬럼타입NULL설명
idbigintNPK고유번호
merchant_idbigintNUQ매장(merchants.id)
client_idvarchar(32)NUQAPI 클라이언트 ID
api_key_hashvarchar(255)N시크릿 해시만 보관(발급 시 1회 표시)
prev_key_hashvarchar(255)Y키 롤 유예(24h 신구 동시 유효)
prev_key_expires_atdatetimeY구 키 만료 시각
webhook_urlvarchar(500)Y매장앱에서 입력하는 웹훅 수신 URL
webhook_secret_encvarbinary(512)YAES-256-GCM - 발신 웹훅 HMAC 서명 생성에 원문 필요
statusvarchar(15)NIXREQUESTED|APPROVED|REJECTED|REVOKED - admin 승인 큐(기본 REQUESTED)
requested_atdatetimeN신청 일시
approved_bybigintYIX승인 관리자(admin_accounts.id)
modevarchar(10)NSANDBOX|LIVE - 테스트 통과 후 매장이 전환(기본 SANDBOX)
test_create_ok_atdatetimeY체크리스트: 결제 생성
test_webhook_ok_atdatetimeY체크리스트: 웹훅 2xx
test_query_ok_atdatetimeY체크리스트: 상태조회
created_atdatetimeN생성 일시

LIVE 전환 조건 = status=APPROVED + 3개 test_*_ok_at 모두 존재(앱 강제).

3.17 fee_policies — 수수료 정책 VERSIONED

컬럼타입NULL설명
idbigintNPK정책 고유번호
fee_typevarchar(20)NUQMERCHANT_PAYMENT|MERCHANT_PAYOUT|USER_DEPOSIT|USER_WITHDRAW|USER_GIFT|USER_EXCHANGE(구현보류)
scopevarchar(15)NUQGLOBAL|USER|MERCHANT
target_idbigintYUQ개별 오버라이드 대상(GLOBAL이면 NULL)
ratedecimal(7,4)N정률% - 정액과 합산 조합(기본 0.0000)
fixed_amountdecimal(15,0)N정액 수수료(기본 0)

3.18 payout_policies — 정산/출금 대기 정책 VERSIONED

컬럼타입NULL설명
idbigintNPK정책 고유번호
scopevarchar(20)NUQGLOBAL_USER|GLOBAL_MERCHANT|USER|MERCHANT
target_idbigintYUQ개별 오버라이드 대상
delay_daysint(11)N신청 +N일. 매장(GLOBAL_MERCHANT) 기본 0=즉시 정산. 사용자 출금만 대기 가능
execute_timetimeN실행 시각 HH:mm(KST). delay_days=0이면 무시(즉시)

3.19 audit_logs — 관리자 행위 감사 BASE (append-only)

컬럼타입NULL설명
idbigintNPK고유번호
actor_typevarchar(10)NIXADMIN|SYSTEM
actor_idbigintY행위 주체 식별자
actionvarchar(50)NMERCHANT_APPROVE|FORCE_SUSPEND|POLICY_CHANGE|MANUAL_MATCH|OTP_RESET|IP_ADD 등
target_typevarchar(30)YIX대상 유형
target_idbigintY대상 식별자
detailtextY변경 전후 값 JSON(개인정보 원문 금지)
reasonvarchar(500)Y강제 조치·조정은 사유 필수
ipvarchar(45)Y행위 IP
created_atdatetimeN기록 일시

3.20 outbox_jobs — 비동기 작업 아웃박스 BASE

컬럼타입NULL설명
idbigintNPK작업 고유번호
job_typevarchar(30)NPUSH|WEBHOOK|RECONCILE|GIFT_EXPIRE|LOT_EXPIRE|SETTLEMENT|STATEMENT|PARTITION 등 - 큐 미사용 단일 패턴
payloadtextN작업 인자 JSON
run_afterdatetimeNIX실행 예정 시각(폴링 기준)
attemptsint(11)N시도 횟수(기본 0)
max_attemptsint(11)N최대 시도(기본 10)
statusvarchar(10)NIXPENDING|RUNNING|DONE|EXHAUSTED (기본 PENDING)
claimed_atdatetimeY워커가 RUNNING으로 집어간 시각 - 고아 스위퍼 기준
claim_tokenchar(36)YIX집기 표(UPDATE로 붙이고 자기 것만 SELECT - 10.3 호환 클레임)
last_errorvarchar(500)Y마지막 오류
created_atdatetimeN생성 일시

원장 트랜잭션과 같은 커밋에 INSERT - 후속작업 유실 불가.

4. 무결성·보존 장치 요약

4.1 append-only 방어 트리거 (14개)

비즈니스 로직은 전부 Java, DB에는 "로직 없는 방어 트리거"만 둡니다. 아래 트리거는 append-only 테이블의 UPDATE/DELETE(또는 불변 컬럼 변경·잔여 증가)를 물리적으로 차단합니다. 앱 DB 계정에 UPDATE/DELETE 권한 미부여와 병행됩니다.

대상 테이블트리거시점·이벤트차단 대상
transactionstrg_txn_no_deleteBEFORE DELETE거래 행 삭제(취소=CANCEL 신규 행)
transactionstrg_txn_immutable_columnsBEFORE UPDATE거래 불변 컬럼 변경
ledger_entriestrg_ledger_no_deleteBEFORE DELETE원장 행 삭제
ledger_entriestrg_ledger_no_updateBEFORE UPDATE원장 행 수정
point_lotstrg_lot_decrease_onlyBEFORE UPDATE로트 잔여 증가(감소만 허용)
audit_logstrg_audit_no_deleteBEFORE DELETE감사 로그 삭제
audit_logstrg_audit_no_updateBEFORE UPDATE감사 로그 수정
pii_access_logstrg_pii_no_deleteBEFORE DELETE개인정보 접근기록 삭제
pii_access_logstrg_pii_no_updateBEFORE UPDATE개인정보 접근기록 수정
deposit_noticestrg_notice_no_deleteBEFORE DELETE입금통지 삭제
deposit_noticestrg_notice_immutableBEFORE UPDATE입금통지 불변 컬럼 변경
external_api_logstrg_extapi_no_updateBEFORE UPDATE대외 호출 기록 수정
reject_logstrg_reject_no_updateBEFORE UPDATE거절 기록 수정
login_historiestrg_login_no_updateBEFORE UPDATE로그인 이력 수정

4.2 시스템 버저닝 (17개)

가변 마스터·정책 테이블에 WITH SYSTEM VERSIONING을 적용하여 변경 이력을 DB가 자동 보존합니다("그 시점 정책"의 법적 증빙). 현재 테이블은 최신 행만, 과거 이력은 히스토리 파티션에 자동 축적됩니다.

구분테이블
마스터users · merchants · merchant_accounts · cards · bank_accounts
정책류fee_policies · limit_policies · payout_policies · cancel_policies · card_quota_policies · point_expiry_policies · global_settings · fds_rules
인증·연동admin_accounts · admin_allowed_ips · deposit_identifiers · merchant_api_credentials

4.3 유니크 멱등키·핵심 UNIQUE 제약

테이블UNIQUE 인덱스컬럼목적
transactionsux_txn_ideminitiator_type, initiator_id, idempotency_key사용자 스코프 거래 멱등(중복 처리·replay 방지). 비파티션 확정의 결정적 근거
deposit_noticesux_notice_refsource, dedup_key입금통지 소스별 결정적 중복키(1062만 앱에서 멱등 처리)
usersux_users_active_ciactive_ci1인 1활성계정 강제(본인인증 CI 기준)
cardsnumber_hashnumber_hash카드번호 재사용 영구 차단
pg_ordersux_pg_ordermerchant_id, order_no매장 주문번호 멱등(중복 결제 방지)
gift_linkstoken_hashtoken_hash선물 클레임 토큰 1회용
used_challengesPRIMARYchallenge패스키 챌린지 재사용(replay) 방지
policy_agreementsux_agreementprincipal_type, principal_id, policy_id약관 동의 중복 방지

4.4 원장 무결성 규약(복식·잔액 체인)

4.5 보존 매트릭스(요약)

보존 등급대상삭제 수단
영구/법정 5년+transactions, ledger_entries, lot_allocations, point_lots, audit_logs, policy_agreements, users·cards·merchants(+버전 이력), unmatched_deposits미삭제(연 단위 아카이브)
5년 후 파티션 DROPexternal_api_logs, reject_logs, app_error_logs, login_histories, pii_access_logs, deposit_notices(아카이브), daily_wallet_snapshotsDROP PARTITION(O(1))
단기notification_inbox 30일(파티션 DROP), outbox_jobs DONE/EXHAUSTED 90일(DELETE), webhook_deliveries DELIVERED 180일(DELETE), hourly_summaries 90일(DELETE)배치 DELETE / DROP

NestPay 산출물 · (주)페이네스트 · 작성일 2026-07-27 · 실제 코드/DB 기준 · 외부연동(펌뱅킹·본인인증·은행 실명조회)은 계약 전 스텁 상태임을 명시