NestPay 산출물 · 저장소·서버·환경변수·관리자·외부계정·배포 접근권한 인계 (실제 코드/설정 기준)
문서 목적 — 발주사(페이네스트) 또는 인수 개발자가 NestPay 시스템을 넘겨받아 개발·운영을 이어가기 위해 필요한 모든 접근권한의 위치·발급방법·절차를 한 곳에 정리한 인계서입니다.
근거: docker-compose.yml, application.yml, SecretsGuard.java/StubGuard.java, 마이그레이션 V3/V31, build.js, 각 저장소 git remote (실제 파일 조회).
소스코드는 자체 호스팅 Git 서버 git.madeitup.kr 에 3개 저장소로 나뉘어 있습니다. HTTPS 프로토콜로 접근합니다.
| 저장소 | 내용 | 클론 주소 (git remote 실측) |
|---|---|---|
| paynest-v1 | API 서버(Spring Boot)·관리자 웹(admin)·소개 사이트(www)·nginx 설정·DB(마이그레이션·스키마·쿼리) | https://git.madeitup.kr/paynest/paynest-v1.git |
| paynest-app | Flutter 앱 (회원앱 user_app·매장앱 store_app·공용 packages/nestpay_shared) | https://git.madeitup.kr/paynest/paynest-app.git |
| paynest-docs | 발주사 공유용 산출물 문서 포털(이 문서 포함) | https://git.madeitup.kr/paynest/paynest-docs.git |
| 항목 | 내용 / 받는 방법 |
|---|---|
| Git 호스트 | git.madeitup.kr (개발사 운영 Git 서버) |
| 인증 수단 | Git 계정(ID/비밀번호) 또는 개인 액세스 토큰(PAT) — 값은 별도 안전채널로 전달. 인수 시 발주사 명의 계정으로 소유권 이전 권장. |
| 브랜치 | 기본 브랜치 main (실측) |
발주사 제공 서버 2대를 L4 로드밸런서 뒤에 동일 구성으로 두고, DB·파일 스토리지를 공유하는 무상태(stateless) 구조입니다. 각 서버는 아래 도커 스택을 동일하게 올립니다.
| 서비스(컨테이너) | 이미지 (실측) | 역할 | 인터넷 노출 |
|---|---|---|---|
db (nestpay-db) | mariadb:10.3 | 데이터베이스 — 발주사와 동일 버전 | 미노출(사설망) |
storage (nestpay-storage) | minio/minio (S3 호환) | 파일·이미지 실물 저장 — 운영은 외부 오브젝트 스토리지로 대체 | 미노출(사설망) |
was (nestpay-was) | 멀티스테이지 빌드(Temurin JDK17→JRE17) | Spring Boot API — Flyway 자동 마이그레이션 | nginx 경유 |
web (nestpay-web) | nginx:1.27-alpine | https 입구 — www/api/pg/admin 서브도메인 경로 분리 | 노출(443) |
| 구분 | 포트 | 용도 |
|---|---|---|
| 운영 | 443 | 하나의 서버(nginx)가 server_name 으로 www·api·pg·admin 서브도메인을 동시 서비스 (L4 뒤 2대 동일) |
| 운영 | /health | L4 헬스체크 경로 (api 서버 상태 점검) |
| 로컬 개발 | 8443 | api. 입구 — 앱 API(/app·/store) |
| 로컬 개발 | 9443 | admin. 입구 — 관리자 웹(정적 + /api) |
| 로컬 개발 | 7443 | pg. 입구 — 외부 PG 연동(/pg, HMAC) |
| 로컬 개발 | 6443 | www. 입구 — 회사·서비스 소개 정적 |
| 로컬 개발 | 3307→3306 | DB (로컬 확인용, 운영은 사설망만) |
| 로컬 개발 | 9000 / 9001 | 스토리지 S3 API / 웹 콘솔 (로컬 확인용) |
nestpay.co.kr 로 가정(SERVICE_DOMAIN 환경변수 1곳 변경으로 전체 반영).운영(NESTPAY_ENV가 dev가 아닐 때)에서 아래 값들이 개발 기본값 그대로거나 미설정이면, 서버가 켜지기 전에 부팅 자체를 차단합니다(fail-fast). 개발용 시크릿이 운영에 남아 토큰·개인정보가 위조되는 사고를 원천 차단하기 위함입니다. 아래는 환경변수 "이름"만 표기하며, 실제 값은 별도 안전채널로 전달합니다.
SecretsGuard.java 실측)| 환경변수 이름 | 매핑 설정키 | 역할 | 미교체 시 |
|---|---|---|---|
APP_CRYPTO_KEY | security.crypto-key | 민감값(카드·CVC·계좌·OTP 씨앗 등) 암호화 열쇠 | 부팅 차단 |
ADMIN_TOKEN_SECRET | security.admin-token-secret | 관리자 출입증(토큰) 서명 비밀키 | 부팅 차단 |
INTERNAL_API_KEY | security.internal-api-key | 내부 웹훅(입금 통지) 인증 열쇠 — 은행/PG 게이트웨이만 아는 값 | 부팅 차단 |
DB_PASSWORD | spring.datasource.password | DB 접속 비밀번호 | 부팅 차단 |
STORAGE_DIR | app.storage.dir | 파일·이미지 실물 폴더 경로 — 두 WAS 가 같은 폴더를 바라봐야 합니다. 열쇠가 필요 없습니다(오브젝트 스토리지를 쓰지 않으므로). | 폴더 접근 권한 |
SWAGGER_ENABLED=false | springdoc.api-docs.enabled | 내부 API 문서 비공개 — false 아니면(기본 true) 차단 | 부팅 차단 |
| 환경변수 이름 | 용도 | 운영 값 |
|---|---|---|
NESTPAY_ENV | 실행 환경 — 이 값이 dev가 아니면 SecretsGuard·StubGuard 작동 | live |
DB_HOST / DB_PORT / DB_NAME / DB_USER | DB 접속 주소·포트·DB명·계정 (비번은 위 DB_PASSWORD) | 운영 DB 값(별도) |
SERVICE_DOMAIN | 서비스 도메인 — api/admin/www 서브도메인이 자동 파생 (단일 변경지점) | 도메인 확정 후 |
TRUSTED_PROXIES | X-Forwarded-For(진짜 IP)를 신뢰할 중계자(nginx) 대역 | 운영 프록시 대역 |
ADMIN_BOOTSTRAP_ALLOW | 관리자 IP 미등록(설치 직후)에만 쓰는 초기 허용 목록 | 운영은 미설정 권장(기본 127.0.0.1,::1) |
application.yml)가 읽는 환경변수 이름은 NESTPAY_ENV 입니다. 운영 설정 시 NESTPAY_ENV=live 를 사용해야 부팅 보안검사(SecretsGuard·StubGuard)가 정상 작동합니다. (과거 docker-compose.yml·README 주석에 APP_ENV 로 잘못 적혀 있던 표기는 정정 완료)StubGuard.java 실측)NestPay 는 실제 외부기관 계약 전까지 아래를 개발용 스텁으로 대신 동작시킵니다. 운영(NESTPAY_ENV≠dev)에서 스텁이 그대로 물려 있으면 부팅을 차단합니다 — 돈·신원 무검증 오픈 방지.
| 스텁 대상 | 현재 구현 | 운영 오픈 조건 |
|---|---|---|
은행 실명조회·1원인증 (BankVerifier) | StubBankVerifier (계약 전) | 실연동 구현 교체 필요 |
본인인증 (IdentityVerifier) | StubIdentityVerifier (계약 전) | 실연동 구현 교체 필요 |
관리자는 전원 동등 구조입니다(V31 마이그레이션에서 root/admin 권한 구분 폐지 — "관리자는 전부 동등"이 발주사 확정). 로그인은 2단계(아이디+비밀번호 → OTP)이며, 최초 1회는 OTP 등록 절차를 거칩니다.
V3 마이그레이션 실측)| 로그인 ID | 초기 비밀번호 | OTP 상태 | 비고 |
|---|---|---|---|
root | 123456 (초기값) | 미등록(첫 로그인 시 등록) | V31 이후 일반 관리자와 동등 |
admin | 123456 (초기값) | 미등록(첫 로그인 시 등록) | V32 에서 표시이름 중립화 |
AdminAuthController 실측)| 순서 | API | 동작 |
|---|---|---|
| 1 | POST /admin/auth/login | 아이디+비밀번호 확인 → 다음 단계(OTP 등록/입력) 안내 + 임시토큰 |
| 2 (최초 1회) | POST /admin/auth/otp/setup | OTP 앱 등록 후 6자리 코드 확인 → 정식 출입증(토큰) 발급 |
| 2 (평상시) | POST /admin/auth/otp/verify | OTP 6자리 확인 → 정식 출입증 발급 |
보안: 로그인은 아이디 기준 무차별 대입 차단(RateLimit), OTP 검증은 IP 기준 차단이 적용됩니다. 관리자 API(/admin/*)는 화이트 IP 제한이 걸려 있으며, 각 관리자별 허용 IP 를 admin_allowed_ips 로 관리합니다.
둘 다 인터넷 미노출(사설망)이며 앱 서버에서만 접속합니다. 아래는 계정 이름·경로만 표기하며, 운영 실제 값은 3장의 환경변수(DB_PASSWORD 등)로 주입하고 별도 안전채널로 전달합니다.
| 항목 | 로컬 개발 기본값 | 운영 |
|---|---|---|
| DB 이름 | nestpay | DB_NAME 로 지정 |
| 애플리케이션 계정 | nestpay / (로컬 비번) | DB_USER / DB_PASSWORD (별도) |
| 관리 계정(root) | root / (로컬 비번) | 운영 정책값(별도) |
| 접속 | localhost:3307 → 컨테이너 3306 | 사설망 내부 DB_HOST:DB_PORT |
| 항목 | 로컬 개발 기본값 | 운영 |
|---|---|---|
| 웹 콘솔 | localhost:9001 (로컬만) | 운영 콘솔 접근은 인프라 정책 |
파일 정보(이름·크기·형식)는 DB files 테이블, 실물 바이트는 스토리지 버킷에 보관합니다. L4 뒤 2대 서버가 같은 스토리지를 공유하므로 어느 서버로 업로드해도 다른 서버에서 그대로 읽고 지웁니다.
| 서비스 | 소유(제공) | 용도 / 인계 방법 | 현재 상태 |
|---|---|---|---|
| 애플 개발자 계정 | 발주사 제공 | iOS 앱 App Store 배포·서명 인증서·프로비저닝 | 발주사 명의 계정 필요 |
| 구글 Play 개발자 계정 | 발주사 제공 | Android 앱 Play Store 배포 | 발주사 명의 계정 필요 |
| Firebase (FCM 푸시) | 발주사 제공 | 폰 화면 푸시. Firebase 프로젝트 ID + 서비스계정 키(JSON) 를 관리자 화면에서 업로드(중앙 files 보관) | 실발송 스텁 — 푸시 키 발급 후 연동 |
| Cloudflare | 개발사 | 문서 포털(nestpay.madeitup.kr, Cloudflare Pages) 배포. 서비스 운영과 무관 | 운영 중 |
| 은행 실명조회·1원인증 | 발주사 계약 | 실계좌 검증 — 계약 후 BankVerifier 실연동 교체 | 계약 전 스텁 |
| 본인인증(PASS 등) | 발주사 계약 | 가입자 신원확인 — 계약 후 IdentityVerifier 실연동 교체 | 계약 전 스텁 |
| PG(매장 결제 연동) | 발주사 계약 | /pg Open API(HMAC 서명 검증) — 서버측 검증부는 구현 완료 | 연동처별 키 교환 필요 |
PushDispatchService/OutboxWorker)에서 마무리하는 스텁 상태입니다.apps/api)| 단계 | 명령 / 내용 |
|---|---|
| 전체 한 번에 | docker compose up -d --build — DB healthy 대기 → API 빌드 → Flyway 마이그레이션 자동 적용 → nginx 기동 |
| 빌드 | 멀티스테이지 Dockerfile(컨테이너 안에서 JDK17 빌드) — 로컬에 Java·Gradle 불필요 |
| 마이그레이션 선행 | Flyway 가 기동 시 V1~V70(70단계)을 순서대로 자동 적용 — 스키마+기본데이터. 새 서버는 DB·계정 생성(01)과 표별 권한(02)만 사람이 실행합니다 — db/deploy/ 참고 |
| 분리 제어 | docker compose up -d 한 줄로 전부(순서는 자동). 하나만 다시 만들 때는 docker compose up -d --build was.실서버와 같은 3계층(web·was·db)이며 망이 공개/폐쇄로 나뉩니다. WAS 2대 시험은 -f docker-compose.ha.yml 추가. |
| 인증서 | ./tls.sh — nginx 인증서 준비까지 포함해 web 입구 기동 |
| 운영 전제 | 기동 전 3장의 운영 환경변수 주입 필수(미설정 시 SecretsGuard/StubGuard 가 부팅 차단) |
| 단계 | 명령 / 내용 |
|---|---|
| 재생성 | node build.js — 원본(paynest-app·paynest-v1)에서 산출물·코드 뷰어 site/ 갱신 |
| 배포 | wrangler pages deploy site --project-name nestpay (Cloudflare Pages). Git 연동 시 main push 자동 배포 |
| 버전 | 제출 버전은 git 태그 v0.x + CHANGELOG.md 이력 |
Flutter 회원앱·매장앱은 각각 애플/구글 개발자 계정으로 스토어 배포합니다. 앱 업데이트 정책은 강제 업데이트(스토어 최소버전 게이트) 확정입니다. API 주소는 NESTPAY_API_BASE 빌드 환경변수 또는 SERVICE_DOMAIN 파생값을 사용합니다.
root·admin = 123456) 즉시 변경 + 개인 OTP 등록NESTPAY_ENV=live · SWAGGER_ENABLED=false 설정 확인(미설정 시 부팅 차단)NestPay 산출물 · (주)페이네스트 · 작성일 2026-07-27 · 실제 코드/DB 기준 · 외부연동(펌뱅킹·본인인증·은행 실명조회)은 계약 전 스텁 상태임을 명시