Appearance
NextMarket API 아키텍처 설계서
1. 프로젝트 개요
NextMarket API는 StepPay 결제 플랫폼을 연동한 쇼핑몰 백엔드 API 서비스입니다.
1.1 기술 스택
| 구분 | 기술 |
|---|---|
| Runtime | Node.js 20+ |
| Language | TypeScript 5.x |
| Framework | NestJS 10.x |
| Database | MySQL 8.x |
| Cache | Redis |
| DB Access | mysql2 + Stored Procedure |
| 결제 연동 | StepPay API v1 |
| 인증 | 세션 기반 (Redis, SessionAuthGuard) |
| API 문서 | Swagger (OpenAPI 3.0) |
| 컨테이너 | Docker (Alpine) |
| CI/CD | Bitbucket Pipelines → AWS ECR |
1.2 주요 기능
- ✅ 회원 관리 (가입, 로그인, 인증)
- ✅ 상품/카테고리 관리
- ✅ 주문/결제 (StepPay 연동)
- ✅ 구독 서비스 관리
- ✅ 웹훅 처리
2. 시스템 아키텍처
┌─────────────────────────────────────────────────────────────────┐
│ Client (Web/App) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ API Gateway / Load Balancer │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ NextMarket API Server │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ NestJS Application │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────────────┐ │ │
│ │ │ Auth │ │ Users │ │Products │ │ Orders │ │ │
│ │ │ Module │ │ Module │ │ Module │ │ Module │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────────────┘ │ │
│ │ ┌─────────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │
│ │ │ Subscriptions │ │ StepPay │ │ Webhook │ │ │
│ │ │ Module │ │ Module │ │ Module │ │ │
│ │ └─────────────────┘ └─────────────┘ └─────────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌──────────────────┐ ┌─────────────────────┐
│ MySQL Database │ │ StepPay API │
│ (Stored Proc) │ │ api.steppay.kr │
└──────────────────┘ └─────────────────────┘3. 디렉토리 구조
nextmarket-api/
├── src/
│ ├── main.ts # 앱 진입점
│ ├── app.module.ts # 루트 모듈
│ │
│ ├── config/ # 환경 설정
│ │ ├── config.module.ts # 설정 모듈
│ │ └── index.ts # JSON 설정 로더
│ │
│ ├── common/ # 공통 모듈
│ │ ├── constants/ # 상태값 상수 (status.constants.ts)
│ │ ├── decorators/ # 커스텀 데코레이터 (@Public 등)
│ │ ├── filters/ # HttpExceptionFilter
│ │ ├── interceptors/ # TransformInterceptor
│ │ ├── interfaces/ # ApiResult, AuthenticatedRequest
│ │ ├── logger/ # Winston 로거 서비스
│ │ ├── middleware/ # HTTP 로깅 미들웨어
│ │ ├── pipes/ # ValidationPipe
│ │ └── redis/ # Redis 세션/토큰 관리
│ │
│ ├── database/ # 데이터베이스
│ │ ├── database.module.ts
│ │ └── database.service.ts # MySQL 연결 및 Procedure 호출
│ │
│ └── modules/ # 비즈니스 모듈
│ ├── auth/ # 인증
│ │ ├── auth.module.ts
│ │ ├── auth.controller.ts
│ │ ├── auth.service.ts
│ │ ├── guards/ # SessionAuthGuard
│ │ └── dto/
│ │
│ ├── users/ # 회원
│ │ ├── users.module.ts
│ │ ├── users.controller.ts
│ │ ├── users.service.ts
│ │ └── dto/
│ │
│ ├── products/ # 상품
│ │ ├── products.module.ts
│ │ ├── products.controller.ts
│ │ ├── products.service.ts
│ │ └── dto/
│ │
│ ├── orders/ # 주문
│ │ ├── orders.module.ts
│ │ ├── orders.controller.ts
│ │ ├── orders.service.ts
│ │ └── dto/
│ │
│ ├── subscriptions/ # 구독
│ │ ├── subscriptions.module.ts
│ │ ├── subscriptions.controller.ts
│ │ ├── subscriptions.service.ts
│ │ └── dto/
│ │
│ ├── steppay/ # StepPay 연동
│ │ ├── steppay.module.ts
│ │ ├── steppay.service.ts # Facade 서비스
│ │ ├── steppay.client.ts # HTTP 클라이언트
│ │ ├── steppay.controller.ts # 테스트/관리 API
│ │ ├── services/ # 개별 API 서비스
│ │ │ ├── steppay-customer.service.ts
│ │ │ ├── steppay-product.service.ts
│ │ │ ├── steppay-order.service.ts
│ │ │ └── steppay-subscription.service.ts
│ │ ├── dto/ # DTO 정의
│ │ ├── interfaces/ # 타입 정의
│ │ └── exceptions/ # StepPay 예외 처리
│ │
│ ├── webhooks/ # 웹훅 처리
│ │ ├── webhooks.module.ts
│ │ ├── webhooks.controller.ts
│ │ └── webhooks.service.ts
│ │
│ ├── sync/ # StepPay ↔ 로컬 동기화
│ │ ├── sync.module.ts
│ │ ├── sync.controller.ts
│ │ └── sync.service.ts
│ │
│ └── docs/ # 문서 뷰어
│ ├── docs.module.ts
│ └── docs.controller.ts
│
├── conf/ # 설정 파일
│ ├── config.json # 환경 설정 (Git 제외)
│ └── config.example.json # 설정 예시 (Git 포함)
│
├── docs/ # 문서
│ ├── Architecture.md
│ ├── API_Endpoints.md
│ ├── Database_Schema.md
│ ├── Multi_Service_Member_Architecture.md
│ ├── StepPay_Integration.md
│ ├── StepPay_API_Reference.md
│ ├── Stored_Procedures.md
│ ├── Subscription_Integration.md
│ └── docs-order.json
│
├── public/ # 정적 파일
│ └── swagger-nav.js # Swagger 네비게이션
│
├── dist/ # 빌드 출력
├── logs/ # 로그 파일
├── Dockerfile # Docker 이미지 빌드
├── .dockerignore # Docker 빌드 제외 파일
├── bitbucket-pipelines.yml # CI/CD 파이프라인
├── package.json
├── tsconfig.json
└── nest-cli.json참고: SQL 스키마 및 Stored Procedure는 별도 프로젝트
nextmarket-db에서 관리됩니다.
4. 모듈 설계
4.1 Auth Module (인증)
| 기능 | 설명 |
|---|---|
| 회원가입 | StepPay Customer 먼저 생성 → 로컬 DB 동기화 |
| 로그인 | username으로 인증, 세션 토큰 발급 (Redis 저장) |
| 로그아웃 | 세션 토큰 무효화 (Redis 삭제) |
| 아이디 중복 체크 | username 사용 가능 여부 확인 |
| 비밀번호 재설정 | 이메일 인증 기반 (예정) |
회원가입 플로우:
- StepPay Customer API로 고객 생성
- NMP_SYNC_USER로 로컬 DB에 동기화
- 비밀번호는 로컬에만 저장 (PASSWORD_HASH)
4.2 Users Module (회원)
| 기능 | 설명 | 상태 |
|---|---|---|
| 프로필 조회/수정 | 회원 정보 관리 | ✅ 구현 |
| 비밀번호 변경 | 현재 비밀번호 확인 후 변경 | ✅ 구현 |
| 회원 탈퇴 | 소프트 삭제 | ✅ 구현 |
| 배송지 관리 | 다중 배송지 CRUD | 📋 예정 |
| StepPay 고객 동기화 | StepPay Customer 생성/연동 | ✅ 구현 |
4.3 Products Module (상품)
| 기능 | 설명 | 상태 |
|---|---|---|
| 상품 CRUD | 상품 등록, 수정, 삭제, 조회 | ✅ 구현 |
| 카테고리 조회 | 카테고리 목록 (Products API 내 통합) | ✅ 구현 |
| 상품 상태 관리 | SALE, SOLDOUT, HIDDEN 등 | ✅ 구현 |
| 상품 옵션 | 조합형 옵션 (색상, 사이즈 등) | 📋 예정 |
| 재고 관리 | 재고 수량 추적 | 📋 예정 |
| StepPay 상품 동기화 | StepPay Product/Price 생성 | ✅ 구현 |
4.4 Orders Module (주문)
| 기능 | 설명 | 상태 |
|---|---|---|
| 주문 생성 | 상품 직접 주문, StepPay 연동 | ✅ 구현 |
| 결제 요청 | StepPay 주문 생성 → 결제 링크 반환 | ✅ 구현 |
| 주문 조회 | 주문 내역, 상세 조회 | ✅ 구현 |
| 결제 상태 확인 | StepPay 결제 상태 조회 | ✅ 구현 |
| 주문 취소 | StepPay 주문 취소 연동 | ✅ 구현 |
| 장바구니 | 상품 추가, 수량 변경, 삭제 | 📋 예정 |
| 배송 상태 | 배송 정보 업데이트 | 📋 예정 |
4.5 Subscriptions Module (구독)
| 기능 | 설명 | 상태 |
|---|---|---|
| 구독 신청 | StepPay 구독 주문 생성 | ✅ 구현 |
| 구독 조회 | 내 구독 목록, 상세 정보 | ✅ 구현 |
| 구독 일시정지 | StepPay 구독 일시정지 | ✅ 구현 |
| 구독 재개 | 일시정지된 구독 재개 | ✅ 구현 |
| 구독 취소 | StepPay 구독 취소 | ✅ 구현 |
| 결제수단 변경 | StepPay 결제수단 변경 URL 반환 | ✅ 구현 |
| 구독 플랜 변경 | 플랜 업/다운그레이드 | 📋 예정 |
4.6 StepPay Module (결제 연동)
StepPay API를 호출하는 Facade 패턴의 공통 서비스 모듈
| 서비스 | 설명 | 상태 |
|---|---|---|
| SteppayCustomerService | 고객 CRUD | ✅ 구현 |
| SteppayProductService | 상품/가격플랜 CRUD | ✅ 구현 |
| SteppayOrderService | 주문 생성/조회/취소 | ✅ 구현 |
| SteppaySubscriptionService | 구독 관리 | ✅ 구현 |
4.7 Webhooks Module (웹훅)
StepPay에서 발생한 이벤트를 수신하여 처리
| 이벤트 | 처리 내용 |
|---|---|
| order.created | 주문 생성 동기화 (STP 코드 → 로컬 IDX 변환) |
| order.paid | 주문 상태 업데이트, 재고 차감 |
| order.cancelled | 주문 취소 상태 업데이트, 재고 복원 |
| subscription.created | 구독 활성화 |
| subscription.renewed | 구독 기간 연장, 주문 생성 |
| subscription.paused | 구독 일시중지 |
| subscription.cancelled | 구독 취소 상태 업데이트 |
| subscription.expired | 구독 만료 처리 |
| payment.completed | 결제 완료 처리 |
| payment.failed | 구독 UNPAID 처리, 알림 발송 |
4.8 Docs Module (문서 뷰어)
마크다운 문서를 웹에서 조회하는 기능
| 기능 | 설명 |
|---|---|
| 문서 목록 조회 | /docs-api/list - docs/ 폴더 내 .md 파일 목록 |
| 문서 내용 조회 | /docs-api/:filename - 마크다운 파일 내용 반환 |
| 문서 뷰어 | /docs-viewer - 웹 기반 문서 뷰어 UI |
4.9 Sync Module (동기화)
StepPay 데이터를 로컬 DB에 동기화
| 기능 | 설명 | 상태 |
|---|---|---|
| 계정 연동 | StepPay 고객을 로컬 계정으로 등록 | ✅ 구현 |
| 전체 동기화 | 고객/상품/주문/구독 일괄 동기화 | ✅ 구현 |
| 고객 동기화 | StepPay 고객 데이터 동기화 | ✅ 구현 |
| 상품 동기화 | 상품 + 가격 플랜 동기화 | ✅ 구현 |
| 주문 동기화 | 주문 + 항목 동기화 | ✅ 구현 |
| 구독 동기화 | 구독 데이터 동기화 | ✅ 구현 |
5. 데이터 흐름
5.1 주문 결제 흐름
원칙: StepPay API 먼저 호출 → 성공 시 로컬 DB 저장 → STP 매핑 저장
1. 클라이언트 → [POST /orders] → 주문 생성 요청
│
2. StepPay API → [POST /orders] → StepPay 주문 생성 (API 먼저)
│
3. NextMarket DB에 주문 + 항목 저장
│
4. STP_ORDERS에 매핑 저장 (NMP_ORDER_CREATE_STEPPAY)
│
5. 결제 링크 반환 ← 클라이언트
│
6. 고객이 결제 페이지에서 결제 진행
│
7. StepPay → [Webhook] → NextMarket
│
8. 주문 상태 업데이트 (PAID), 재고 차감5.2 구독 흐름
1. 클라이언트 → [POST /subscriptions] → 구독 신청
│
2. StepPay API → 구독 생성 (API 먼저)
│
3. NextMarket DB에 구독 저장 + STP 매핑 저장
│
4. 결제 링크 반환 → 고객 결제
│
5. [Webhook: 구독 활성화] → DB 상태 업데이트
│
6. 매 결제 주기마다:
[Webhook: 구독 갱신] → 주문 생성, 기간 연장6. 인증/인가 설계
6.1 세션 토큰 구조
세션 토큰 (유효기간: 15분, 자동 연장)
crypto.randomBytes(32).toString('hex')로 생성- Redis에 세션 데이터 저장
- Bearer 토큰으로 전달
- 요청 시 TTL 자동 연장
세션 데이터 (Redis)
json
{
"sub": 12345,
"username": "user@example.com",
"role": "USER"
}| 필드 | 설명 |
|---|---|
sub | 로컬 회원 IDX (number) |
username | 로그인 아이디 |
role | 사용자 권한 (USER/ADMIN) |
6.2 역할 (Role)
| 역할 | 권한 |
|---|---|
ADMIN | 전체 관리자 권한 |
USER | 일반 사용자 권한 |
GUEST | 비로그인 사용자 |
7. 에러 처리
7.1 에러 응답 형식
json
{
"statusCode": 400,
"error": "Bad Request",
"message": "유효성 검증 실패",
"details": [
{
"field": "email",
"message": "올바른 이메일 형식이 아닙니다"
}
],
"timestamp": "2025-01-07T12:00:00.000Z",
"path": "/api/v1/users"
}7.2 에러 코드 체계
| 코드 범위 | 설명 |
|---|---|
| 400-499 | 클라이언트 오류 |
| 500-599 | 서버 오류 |
| 1000-1999 | 인증 관련 |
| 2000-2999 | 주문/결제 관련 |
| 3000-3999 | 구독 관련 |
| 9000-9999 | StepPay 연동 오류 |
8. 환경 설정
8.1 설정 파일 (conf/config.json)
.env대신 JSON 파일로 설정을 관리합니다.
json
{
"serviceEnv": "LOCAL",
"port": 3003,
"apiPrefix": "api/v1",
"mysql": {
"host": "localhost",
"port": 3306,
"user": "your-db-user",
"password": "your-db-password",
"database": "nextmarket",
"charset": "utf8mb4",
"waitForConnections": true,
"connectionLimit": 20
},
"redis": {
"url": "redis://localhost:6379"
},
"jwt": {
"accessSecret": "your-access-secret-key",
"accessExpiresIn": "15m",
"refreshSecret": "your-refresh-secret-key",
"refreshExpiresIn": "7d"
},
"steppay": {
"apiUrl": "https://api.steppay.kr",
"secretToken": "your-steppay-secret-token",
"paymentKey": "your-steppay-payment-key",
"webhookSecret": "your-steppay-webhook-secret"
},
"log": {
"level": "debug",
"maxSize": "20m",
"maxFiles": "14d"
},
"docs": true
}8.2 환경별 설정 파일
| 파일 | 용도 |
|---|---|
conf/config.json | 실제 설정 (Git 제외) |
conf/config.example.json | 설정 템플릿 (Git 포함) |
설정 로드:
src/config/index.ts에서conf/config.json을 로드합니다. 운영 환경에서는 Docker 볼륨 마운트로 설정 파일을 교체합니다.
9. 보안 고려사항
- Secret Token 관리: 환경변수로 관리, 코드에 하드코딩 금지
- HTTPS 강제: 프로덕션 환경에서 HTTPS 필수
- Rate Limiting: API 요청 제한 적용
- Input Validation: 모든 입력값 유효성 검증
- SQL Injection 방지: Stored Procedure 파라미터 바인딩
- 웹훅 검증: Signature 검증으로 위변조 방지
- 민감 정보 로깅 금지: 비밀번호, 토큰 등 로그 제외
10. 배포 전략
10.1 환경 구성
| 환경 | 용도 |
|---|---|
| Development | 로컬 개발 |
| Staging | QA/테스트 |
| Production | 운영 |
10.2 Docker 구성
Dockerfile (멀티스테이지 빌드):
dockerfile
# Build Stage
FROM node:20-alpine AS builder
WORKDIR /app
RUN apk add --no-cache python3 make g++ # bcrypt 빌드
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
RUN npm ci --only=production && npm cache clean --force
# Production Stage
FROM node:20-alpine AS production
WORKDIR /app
RUN addgroup -g 1001 -S nodejs && adduser -S nestjs -u 1001
COPY --from=builder --chown=nestjs:nodejs /app/dist ./dist
COPY --from=builder --chown=nestjs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nestjs:nodejs /app/package.json ./
COPY --chown=nestjs:nodejs conf ./conf
USER nestjs
EXPOSE 3003
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:3003/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
CMD ["node", "dist/main"]Docker 실행:
bash
# 빌드
docker build -t nextmarket-api .
# 실행
docker run -d -p 3003:3003 --name nextmarket-api nextmarket-api
# 설정 파일 마운트
docker run -d -p 3003:3003 \
-v /path/to/config.json:/app/conf/config.json:ro \
nextmarket-api10.3 CI/CD 파이프라인 (Bitbucket Pipelines)
파이프라인 흐름:
태그 푸시 (예: 1.0.0)
│
▼
┌─────────────────────────────────┐
│ Build & Push to ECR │
│ - version.json 생성 │
│ - Docker 이미지 빌드 │
│ - AWS ECR에 푸시 │
│ - 태그: {version}, latest │
└─────────────────────────────────┘참고: K8s 배포 트리거 단계는 현재 비활성화 상태입니다 (주석 처리). 향후 K8S 배포 파이프라인 연동 시 활성화 예정입니다.
필요한 Repository Variables:
| 변수명 | 설명 |
|---|---|
AWS_ACCESS_KEY_ID | AWS 액세스 키 |
AWS_SECRET_ACCESS_KEY | AWS 시크릿 키 |
AWS_DEFAULT_REGION | AWS 리전 (ap-northeast-2) |
배포 트리거:
bash
# 태그 생성 및 푸시
git tag 1.0.0
git push origin 1.0.0최종 업데이트: 2026년 3월 16일 - 인증 방식 JWT→세션 기반 변경, sync 모듈 추가