선불전자지급수단(선불카드형 지갑) 플랫폼 · 실제 코드/DB 기준 · 오픈 전(외부연동 계약 대기) 상태 명시
paynest-v1(API·관리자·nginx·DB, 커밋 142) · paynest-app(Flutter 회원/매장앱, 커밋 60) · paynest-docs(문서) · 운영 스키마: MariaDB nestpayNestPay는 선불전자지급수단(선불카드형 지갑) 핀테크 서비스입니다. 회원이 자기 계좌에서 지갑으로 충전(입금)하고, 앱 결제코드·QR로 매장에서 결제하며, 회원 간 선물·본인 출금·매장 정산이 이루어집니다. 클라이언트는 앱 전용(회원앱·매장앱)이며, 운영자는 웹 관리자 콘솔로 통제합니다. 대외 온라인 결제는 PG 게이트웨이 API(가맹 쇼핑몰 서버 연동)로 제공합니다.
| 계층 | 내용 | 기술 스택 | 상태 |
|---|---|---|---|
| 회원앱 | 가입·인증·충전·결제·선물·출금·명세·고객센터 | Flutter (iOS/Android 단일 UI) | 구현 완료 |
| 매장앱 | 매장 온보딩·QR/결제 수취·매출·정산·API 키 | Flutter | 구현 완료 |
| 관리자 콘솔 | 회원/매장/거래/정산/정책/FDS/푸시/콘텐츠 운영 | 정적 HTML + Vanilla JS(빌드도구 無) | 구현 완료 |
| API 서버 | 230개 엔드포인트 · 7개 백그라운드 워커 | Java 21 · Spring Boot 3 · MyBatis · Flyway | 구현 완료 |
| 데이터베이스 | 68개 도메인 테이블 · 무결성 트리거 · 시스템버전드 이력 | MariaDB(시스템버전드 · 파티셔닝) | 구현 완료 |
회원앱·매장앱은 하나의 UI/UX로 통일(플랫폼 네이티브 분기 없음). 소개 웹(apps/www)·PG 연동 문서 등 부가 산출물 포함.
소스코드(3개 git 저장소) + 설계·요구사항·인터페이스·테스트·인수인계 문서(paynest-docs 웹 문서 세트) + 개발/유지관리 계약서. 상세 대응표는 6장 참조.
엔드포인트 집계 근거: 소스의 @GetMapping 92 · @PostMapping 120 · @DeleteMapping 16 · @PutMapping 2 = 230. 테이블 집계: 운영 스키마 information_schema 기준 총 69개 중 Flyway 관리테이블 1개 제외 → 도메인 68개(일반 51 + 시스템버전드 17).
| 대상 그룹 | 경로 접두 | 엔드포인트 | 주요 컨트롤러 |
|---|---|---|---|
| 관리자 콘솔 | /admin/* | 134 | 가맹점 25 · 정책 22 · 콘텐츠 18 · 회원 13 · FDS 5 · 푸시 5 · 계정/IP/정산/통계 등 |
| 회원앱 | /app/* | 64 | 마이페이지 16 · 패스키 8 · 선물 7 · 콘텐츠 7 · 가입/인증 6 · 카드 5 · 결제/PIN/출금 등 |
| 매장앱 | /store/* | 22 | 매장 13 · QR 3 · 인증 2 · 정산 2 · 대시보드 2 |
| PG 연동(대외) | /pg/* | 8 | 결제 7 · 헬스 1 (HMAC 서명 + 매장 화이트IP 인증) |
| 은행 입금 웹훅 | /webhooks/bank | 1 | 입금통지 수신·중복제거·자동매칭 |
| 헬스체크(L4) | /health | 1 | L4 로드밸런서 상태 확인 |
| 합계 | 230 | ||
| 영역 | 완료 기능 |
|---|---|
| 가입·인증 | 휴대폰 본인인증·계좌등록·KYC 상태관리 / 로그인(비밀번호·PIN·패스키(WebAuthn)) / 비밀번호 변경 / 회원 탈퇴 신청·처리 |
| 지갑·충전 | 지갑 발급 / 계좌 1원인증 등록 / 충전(입금자 코드 방식) / 은행 입금통지 자동매칭 / 미매칭 입금 관리·반환 |
| 결제 | 앱 결제코드·QR 발급 / 매장 결제 수취 / 결제 취소·부분취소 / PG 게이트웨이(대외 쇼핑몰) 주문 생명주기 |
| 선물 | 선물 링크 발급 / 받는사람 조회(전화·카드번호 노출 방지 위해 POST 본문 처리) / 수령·미수령 만료 회수 |
| 출금·정산 | 본인 출금 신청·실행(HOLD→PENDING 클레임→CONFIRMED) / 매장 정산 정책·명세 / 일·월 집계 스냅샷 |
| 포인트 회계 | 선입선출(FIFO) 포인트 로트 / 로트 할당(lot_allocations) / 유효기간 만료 정책 / 감소 전용 트리거 |
| 운영·리스크 | FDS 규칙(8건 시드)·알림 / Rate limit 규칙(14건 시드) / 감사로그 / 개인정보 접근기록 / 공지·FAQ·배너·문의 콘텐츠 관리 |
| 알림 | 푸시 토큰·캠페인·타깃 / 알림함(inbox)·수신설정 / 앱 강제 업데이트 게이트(스토어 최소버전) |
기능-계층 매핑 전수는 구현 현황 문서 참조. 앱 업데이트 정책은 강제 업데이트(스토어 최소버전 게이트) 방식으로 확정.
모든 잔액 변동은 ledger_entries에 차변(DR)/대변(CR) 복식부기로 기록되며, 원장·거래·감사성 테이블은 DB 트리거로 UPDATE·DELETE를 원천 차단합니다(위·변조·소급수정 불가). 운영 스키마에서 트리거 14개가 다음 9개 테이블을 보호하는 것을 확인했습니다.
| 보호 테이블 | 차단 | 의미 |
|---|---|---|
ledger_entries | UPDATE · DELETE | 원장 append-only(수정·삭제 불가) |
transactions | DELETE · 핵심컬럼 UPDATE | 거래 불변(금액·상태 등 소급수정 차단) |
audit_logs | UPDATE · DELETE | 감사로그 불변 |
pii_access_logs | UPDATE · DELETE | 개인정보 접근기록 불변 |
deposit_notices | UPDATE(불변) · DELETE | 은행 입금통지 원문 보존 |
login_histories | UPDATE | 로그인 이력 불변 |
external_api_logs | UPDATE | 외부 API 호출로그 불변 |
reject_logs | UPDATE | 거절 이력 불변 |
point_lots | 증가 방향 UPDATE | 포인트 로트 잔량 감소 전용 |
ledger_entries 전수 합계가 차변 합 = 대변 합 = 201,800 으로 정확히 일치(복식부기 균형 성립). 시스템 지갑을 포함한 폐쇄 회계 구조로, 어느 한 지갑의 증가는 반드시 다른 지갑의 감소와 짝을 이룹니다.돈이 두 번 빠지거나 두 번 충전되는 사고를 막기 위해 DB UNIQUE 제약 기반 멱등키를 사용합니다. 입금·출금·선물·결제·정산은 모두 transactions 행을 생성하므로, 거래 멱등키가 이 5개 흐름을 공통으로 보호합니다.
| 대상 | 제약(UNIQUE) | 방어 |
|---|---|---|
| 거래(입금·출금·선물·결제·정산) | transactions.idempotency_key (ux_txn_idem) | 동일 요청 재전송 시 중복 거래 차단 |
| 은행 입금통지 | deposit_notices.dedup_key (ux_notice_ref) | 펌뱅킹 거래식별자/SMS 지문 중복 수신 차단 |
| 패스키 인증 챌린지 | used_challenges.challenge (PK) | WebAuthn 서명 재사용(replay) 차단 |
| 아웃박스 워커 | outbox_jobs.claim_token | 2대 서버 동시처리 시 정확히 한 번 실행 |
| 웹훅 발송 | webhook_deliveries claim_token | 중복 웹훅 발송 차단(exactly-once) |
/pg/*는 HMAC 서명 검증 + 요청시각 오차(clock-skew) 제한 + 매장별 승인 화이트IP 재검증(HmacAuthFilter)./admin/*는 공통 화이트IP → 서명 토큰 → 관리자별 개인 허용IP 3단 검사(IpWhitelistFilter→AdminAuthFilter). 관리자는 전원 동등 권한.UserAuthFilter·StoreAuthFilter). 거래 인증표(pinPass) 서명.X-Forwarded-For만 신뢰(ClientIpResolver·trusted-proxies).로그인·인증·민감 API에 요청 빈도 제한을 적용합니다. 규칙은 DB(rate_limit_rules)에서 관리되며 운영 스키마에 14건 시드 확인, 카운터는 rate_limit_counters로 집계, 관리자 화면에서 규칙 조정 가능.
*_enc)에 저장 — 운영 스키마에 7개 확인(CryptoService·APP_CRYPTO_KEY).*_hash) 13개(전화·계좌 등, HMAC-SHA256).Masks 유틸로 마스킹. 선물 받는사람 조회는 전화·카드번호가 URL/로그에 남지 않도록 GET→POST 본문으로 전환.pii_access_logs에 남기며 append-only 트리거로 보호.| 헤더 | 값 | 상태 |
|---|---|---|
X-Content-Type-Options | nosniff | 적용 |
X-Frame-Options | SAMEORIGIN(클릭재킹 차단) | 적용 |
Referrer-Policy | no-referrer | 적용 |
Cache-Control(관리자) | no-store | 적용 |
Strict-Transport-Security(HSTS) | 운영 도메인 443 블록 전용 | 실인증서 적용 후 활성(현재 dev self-signed) |
운영(app.env=sandbox·live)에서 위험한 기본값이 남아 있으면 서버가 아예 기동되지 않도록 부팅 단계에서 차단합니다.
APP_CRYPTO_KEY · ADMIN_TOKEN_SECRET · INTERNAL_API_KEY · DB_PASSWORD · STORAGE_SECRET_KEY. 추가로 운영에서 Swagger(api-docs) 노출 시 기동 거부.BankVerifier), 본인인증(IdentityVerifier)이 개발 스텁 그대로면 기동 거부(무검증 운영 오픈 차단).현재 검증은 DB 계층 정밀 검증 리포트와 부정(negative) 테스트 중심으로 완료되어 있으며, 백엔드 자동화 테스트(JUnit) 스위트는 미보강 상태로 잔여 관문입니다(5장).
| 검증 유형 | 내용 · 규모 | 산출물 | 상태 |
|---|---|---|---|
| 조회계획(EXPLAIN) 검증 | 주요 조회 52종 전수 — 인덱스 사용(const/ref/range) 확인, 풀스캔 차단 | verification-report · verify | 완료 |
| 원장 무결성 부정 테스트 | append-only 방어장치 12종 — 위·변조·소급수정 시도가 실제로 거부되는지 검증 | verification-report | 완료 |
| 대용량 성능 실측 | 100만 건+ 적재 후 핵심 조회 응답 실측 | verification-report | 완료 |
| 인덱스 인벤토리 | 테이블별 인덱스 전수 정리 | verification-report | 완료 |
| 앱(Flutter) 단위 테스트 | 단위 테스트 파일 3건 | paynest-app test/ | 최소 · 보강 필요 |
| 백엔드 자동화 테스트(JUnit) | 서비스/컨트롤러 자동 테스트 | — | 미구현(잔여 관문) |
EXPLAIN·무결성 검증 SQL 원문은 db/verify_explain.sql. 별도 종합 테스트결과서(test-report)는 백엔드 자동화 테스트 보강과 함께 산출 예정.
기능·데이터·보안 골격은 구현 완료되어 로컬 실기동으로 검증되었습니다. 다만 실제 돈·신원이 오가는 대외 오픈(라이브)은 아래 관문을 반드시 통과한 뒤 열어야 합니다. 현재는 오픈 전 상태입니다.
아래 3종은 계약 전까지 교체형 개발 스텁으로 동작합니다(코드 주석에 연동 지점 명시). 스텁 상태로 운영을 열면 돈·신원이 무검증이 되므로 StubGuard가 기동을 막습니다.
| 연동 | 현재(스텁) 동작 | 실연동 시 |
|---|---|---|
| 펌뱅킹 | 입금=입금자 코드 방식 / 출금 이체=항상 성공 스텁(WithdrawWorker) / 미매칭 확정 보류 | 실입금·실이체·가상계좌 발급, 리컨실러 연결 |
| 본인인증 | 임의 이름·생일·전화 통과(StubIdentityVerifier) | 인증사 API로 실제 명의 검증 |
| 은행 실명조회·1원인증 | 아무 계좌나 본인 명의로 통과(StubBankVerifier) | 실명조회·1원 송금 실검증 |
참고: 푸시(FCM)도 계약/키 발급 전 스텁으로 동작합니다(라이브 시 실키 교체).
| 관문 | 현재 | 필요 조치 |
|---|---|---|
| HTTPS · HSTS | dev self-signed 인증서 | 운영 도메인 실인증서 적용 후 443 블록에 HSTS 활성 |
| 일 대사(정산) 배치 | append-only 원장·무결성 점검 테이블(integrity_check_runs/integrity_findings) 준비됨, 자동 대사 배치는 미연결 | 일 1회 원장↔은행/PG 대사 스케줄 배치 추가 |
| 백엔드 자동화 테스트 | DB 검증·부정 테스트 완료, JUnit 스위트 미구현 | 서비스/컨트롤러 자동 테스트 보강 |
| 운영 시크릿 | SecretsGuard가 5종 기본값 거부(부팅 차단) | 운영 환경변수로 강한 값 주입 후 기동 |
claim_token 원자 클레임으로 이중실행을 방지합니다. /health는 L4 상태확인 경로. 대사 배치 추가 시에도 동일 클레임 규약을 따라야 합니다.| # | 산출물 종류 | 실제 산출물 · 위치 |
|---|---|---|
| 1 | 소스코드 | git 저장소 3종 — paynest-v1(서버·관리자·DB, 커밋 142) · paynest-app(회원/매장앱 Flutter, 커밋 60) · paynest-docs(문서) |
| 2 | DB(설계·검증) | schema · erd · queries · routines · verification-report |
| 3 | 인터페이스(API) | api-endpoints(230개) · pg-integration(대외 PG 연동) |
| 4 | 설계(아키텍처) | architecture · prototype(앱 화면) |
| 5 | 요구사항 | vendor-requests(발주사 요청자료) · implementation-status · 계약서(개발구축·유지관리) |
| 6 | 테스트 | verification-report · verify (종합 test-report는 자동화 테스트 보강과 함께 산출 예정) |
| 7 | 인수인계 | operations-guide(운영·배포) · 각 저장소 README(Docker 한 번에 기동) |
NestPay 산출물 · (주)페이네스트 · 작성일 2026-07-27 · 실제 코드/DB 기준 · 외부연동(펌뱅킹·본인인증·은행 실명조회)은 계약 전 스텁 상태임을 명시