DPS (Design Plug Shop)
개요
DPS는 판매자와 제조사를 연결하는 B2B 주문형 굿즈·인쇄 제작 플랫폼입니다. 주문, 디자인, 제작, 배송까지의 전 과정을 클라우드로 자동화하여 소상공인의 제작 비용 절감과 효율적인 운영을 지원합니다.
관리자(Admin), 파트너/판매자(Partner), 스토어/크리에이터(Store/Creator) 3가지 역할 기반의 멀티 테넌트 아키텍처로 설계되었습니다. 현재 202개 페이지·276개 API 라우트·77개 Prisma 모델 규모로 운영 중인 사내 주력 서비스입니다.
주요 기능
멀티 테넌트 역할 시스템
- 관리자(20개 모듈): 상품/SKU·상품군 관리, 판매사·공급사 정산, 회원·고객사 관리, 플랫폼 운영(배너, 팝업, 게시판), 주문 동기화 추적, PDF 복원 검수, 통계 대시보드
- 파트너(판매자, 13개 모듈): 상품 등록·관리, 재고 관리, 주문 처리·배송, 정산 조회, 그룹·멤버 관리
- 스토어(16개 모듈): 상품 카탈로그, 자체 상품 관리, 주문 접수, 결제 관리, 외부 채널 연결
- 크리에이터(6개 모듈): 카탈로그, 상품·주문 조회, 문의
주문 상태 머신
주문은 14단계 상태 코드(ORDER_STATUS_00~99)로 관리되며, 자동 승인이 켜진 판매사는 사람 손을 거치지 않고 발주까지 진행됩니다.
승인대기(00) ─APPROVAL─▶ 결제대기(10) ─PAYMENT─▶ 발주대기(15)
│ EXTERNAL
┌─────────────────────┴──────────────┐
▼ ▼
상품준비중(30) 발주실패(25)
│ │ 최대 4회 재시도
▼
배송중(60) → 배송완료(70) → 구매확정(80)취소·결제·동기화 가능 여부는 상태 그룹(AVALIABLE_FOR_CANCEL_PRODUCT, IMMUTABLE_STATUS 등)으로 역할별 권한과 함께 판정합니다.
배치 스케줄러 (17종)
batch.cron.mjs(node-cron)를 PM2 전용 프로세스로 띄워 운영/개발 환경별로 다른 주기를 적용합니다.
| 작업 | 운영 주기 | 목적 |
|---|---|---|
| APPROVAL / PAYMENT / MAIL | 매 1분 | 자동 승인, Innopay 자동 결제, 메일 발송 |
| EXTERNAL | 매 10분 | 외부 제조사(레드프린팅·와우프레스) 발주 |
| DELIVERY | 매 10분 | 배송 정보 동기화 |
| DELIVERY_TRACKING | 매시 30분 | 운송장 추적 (정각 부하 분산) |
| SMARTSTORE | 매 5분 | 스마트스토어 주문 동기화 |
| ORDER_SYNC | 매시 30분 | 외부 채널 주문 수집 |
| CONFIRM | 매시 정각 | 구매확정 처리 |
| SELLER_SETTLE / SUPPLIER_SETTLE | 매 1시간 | 판매사·공급사 정산 집계 |
| RATINGS / STATISTICS / TOKEN_REFRESH | 매일 01시 | 평점 산출, 통계 집계, 외부 토큰 갱신 |
| PRIVACY_PURGE | 매일 01시 | 개인정보 보유기간 만료 데이터 파기 |
| ORDER_NOTIFICATION | 판매사 14시 / 공급사 10시 | 일일 주문 알림톡·메일 |
| ORDER_SYNC_CLEANUP | 매일 14시 | 동기화 이력 정리 |
외부 서비스 연동
- 네이버 스마트스토어: OAuth·커머스 ID 인증, 주문 동기화
- Cafe24: 앱 설치·토큰 갱신, 멀티샵(
shop_no)·멀티디자인 주문 인입, ScriptTag 주입 - 고도몰: 배송 정보 연동
- 레드프린팅 / 와우프레스: 외부 제조사 자동 발주 API (EXTERNAL 스케줄러)
- Jarvis(CIPOD): 디자인 에디터 연동 + Jarvis 계정 기반 SSO 로그인·토큰 갱신, 고정 템플릿 디자인 동결(freeze)·해제, 삭제된 에디터 템플릿을 참조하는 상품의 자동 재매핑. 에디터가 PHP 판에서 Next.js 신규 판으로 교체되면서 롤백 대비 origin을 유지한 채 카테고리·옵션 계약을 새로 맞췄습니다
- 파일봇: PDF 메타 추출·옵션별 가이드 파일 처리
- 카카오 알림톡: 주문·승인·배송 알림 발송 (Lunasoft 연동)
- Innopay: PG 결제·자동 결제 처리
- AWS S3 / NHN: 파일·이미지 업로드 및 관리
공급사 오픈 API
외부 공급사가 자사 시스템에서 DPS 주문을 처리할 수 있도록 별도 API 세트(/api/v1/supplier)와 연동 가이드 문서를 제공합니다. 주문 조회·상태 변경, 상품·카테고리 조회, 정산 조회, 거래 요청을 포함하며 API Key 기반으로 인증합니다.
SKU 비종속 옵션(표현축)
색상·인쇄면처럼 재고 SKU를 늘리지 않고 디자인에만 영향을 주는 축을 별도 옵션 체계로 분리했습니다. 쇼핑몰 상세페이지는 SKU 옵션만 렌더하고, 나머지 축은 에디터가 자기 화면에서 렌더하도록 경계를 나눈 설계입니다.
[쇼핑몰 상세] optionSetCode 1개만 들고 에디터 진입
▼
[에디터] GET /api/v2/editor/option-set/{optionSetCode}
│ → 표현축 그룹·항목·판매가능 조합 수신, 지원 못 하는 값은 건너뜀
▼
[쇼핑몰 상세] POST .../resolve-sku → { sku, variantCode, skuOptions }- 경계 원칙: 에디터는 "무엇을 고를 수 있고 무엇을 골랐나"까지만 알고, "그 선택이 어느 SKU이고 팔 수 있는가"는 DPS가 판정합니다. 가격·판매상태 로직이 에디터로 새지 않도록 한 분리입니다.
- 조회 토큰:
optionSetCode를 식별자 평문 조합에서 판매사·몰 컨텍스트를 담은 암호화 해시로 재설계해, 코드 열거로 타 판매사 옵션을 훑는 경로를 막았습니다. - 조합 판정: 판매가능 조합 화이트리스트를
matchKey에서comboHash기준으로 전환해 키가 같은 다른 조합이 통과하던 결함을 잡고, "조합 미정의"와 "전부 껐다"를 구분해 전부 끄면 제한이 없어지던 반전 동작을 수정했습니다. - 공급사 설정 화면: JSON 직접 입력에서 축 기본정보·구분·항목·제약을 다루는 폼 화면으로 전환하고, 구분 코드·조합 키 자동 생성, 조합 미리보기, 규칙 뼈대 자동 채우기를 붙였습니다.
- 조합 확정가(
comboPrices)와 과금 키를 응답에 동봉해 에디터가 키 포맷을 재현하지 않도록 했고, 사이즈처럼 캔버스를 가르는 축은 항목에 에디터 템플릿을 함께 실었습니다.
에디터 카테고리 연동
신규 에디터의 카테고리를 관리자 모듈로 편입해, 상품이 어떤 에디터 템플릿·색상·인쇄면 위에서 편집되는지를 DPS에서 관리합니다.
- 대·중·소 3단 계층을 스키마 변경 없이
parentSeqno만으로 처리 - 카테고리 옵션 조회를 실제 Jarvis 엔드포인트로 연결하고, 폴백이 발생하면 로그·응답에 표시
- 판매중 상품이 걸린 카테고리는 연결 해제를 차단하고 실패 사유를 노출
- 대표 템플릿 교체 시 판매사 시작 템플릿 번호를 함께 동기화하고, 삭제 표시된 템플릿은 Jarvis 실재 여부를 대조해 해제
발주서·작업지시서 생산 정보
외부 공급사와 자체 생산 양쪽에서 "출력물만 보고 제작이 가능한" 수준까지 지면 정보를 끌어올렸습니다.
- 편집 XML을 해석해 인쇄영역·레이어별 실제 mm 치수를 산출하고, 면별 인쇄영역(
pcFace)까지 발주서에 표기 - 발주서에 고객 편집 목업과 생산 파일을 함께 배치, 미리보기 확대·상단 표 축소로 지면 예산 재배분
- 발주서 PDF 생성을 공용 모듈로 분리하고 페이지 단위 조립으로 전환
- 작업지시서 PDF 용량 급증을 페이지 캡처 포맷 교체(PNG → JPEG q0.85)로 해소하고, 일괄 다운로드 시 주문 단위 한 PDF로 합본
- 생산파일 수집·ZIP 분할 다운로드 유틸과 CORS 프록시를 추가해, 상품 준비중 목록에서 건별·일괄 다운로드를 지원
주문 인입 정합성
외부 채널 주문이 상세까지 생성되지 않고 고착되던 문제를 원인별로 추적해 닫았습니다.
- Cafe24 주문 수집의 10건 제한을 해소하고 조회 기간을 반영, 웹훅에서 주문 상세를 직접 생성
- 상세 미생성 주문을 승인대기·발주대기·전체 목록에 그대로 노출하고 미생성 사유를 저장·표시, 건별 갱신과 일괄 판정 경로 제공(기본 3개월 이내)
- 주문 건별 상세 동기화 상태 컬럼과 미입금(UNPAID) 상태를 추가해, 어떤 주문이 왜 비어 있는지를 화면에서 판정 가능하게 변경
보안·개인정보
운영 중 발견한 노출 경로를 일괄 점검해 닫고, 개인정보 처리 절차를 정비했습니다.
- 인증이 없던 HTML 에디터·파일 엔드포인트에 권한 검사 추가
- 업로드 파일 확장자 검증으로 실행파일 공개 서빙 차단
- 퍼블릭 카탈로그 상세에서 비로그인 원가·재고 노출 차단, 로그인 실패 문구의 계정 열거 대응
- 개인정보 보유기간 만료 파기 배치(
PRIVACY_PURGE) 신설 - 문의의 개인정보 수집·이용 동의를 분리하고 동의 이력을 저장, 비회원 문의 접수·답변 통보 경로 추가
검색 노출
sitemap.xml/robots.txt신설- 소식 본문을 크롤러가 읽도록 저장 HTML 해석 모듈을 추가하고, 메타데이터·JSON-LD·시맨틱 마크업 적용
관리자 대시보드
KPI 요약, 일별 매출, 채널 분류·채널별 상세, 베스트셀러, 신규 상품, 콘텐츠 등록 추이, 처리 대기 건수(To-do)를 한 화면에서 집계합니다.

일별 매출·신규가입 추세와 외부 유입 경로별 주간 실적을 한 화면에 집계합니다. (연락처는 모자이크 처리)

기술 스택
| 분류 | 기술 |
|---|---|
| Framework | Next.js 16 (App Router) |
| Language | TypeScript 6 (strict mode) |
| UI | React 19, Tailwind CSS 4, clsx + tailwind-merge |
| 상태 관리 | Zustand 5, TanStack Query 5 |
| 폼 처리 | React Hook Form 7 + Zod 4 |
| ORM | Prisma 7 (MySQL/MariaDB, 멀티 DB) |
| 인증 | NextAuth 5 (Credentials, 3역할 분리) |
| 에디터 | Tiptap 3 (리치 텍스트), Monaco (코드/HTML) |
| 차트 | Recharts 3 |
| 국제화 | next-intl 4 (ko-KR, en-US, ja-JP) |
| 파일 처리 | ExcelJS 4, jsPDF 4 |
| 로깅 | Winston 3 (Daily Rotate) |
| 프로세스·스케줄링 | PM2, node-cron (배치 전용 프로세스 분리) |
| 배포 | PM2 Blue-Green 무중단 배포 (deploy.sh / rollback.sh) |
아키텍처
프로젝트 구조
app/
├── admin/ # 관리자 (20개 모듈)
├── partner/ # 파트너/판매자 (13개 모듈)
├── store/ # 스토어 (16개 모듈)
├── creator/ # 크리에이터 (6개 모듈)
├── api/ # REST API (276개 route)
│ ├── v1/ # 도메인 API (admin, seller, supplier, creator, jarvis, cafe24, smartstore 등 24개)
│ ├── schedule/ # 배치 스케줄러 (17개 작업)
│ ├── auth/ # NextAuth 인증
│ └── upload/ # 파일 업로드
├── editor/ # 디자인 에디터 연동
├── html-editor/ # Monaco 기반 HTML 편집
└── auth/ # 외부 인증 (Innopay, NHN, 스마트스토어, Cafe24)
components/ # 재사용 컴포넌트
services/ # 비즈니스 로직 (31개 도메인: order, seller-settle, jarvis, filebot, external, editor-template, option-set 등)
lib/
├── repositories/ # Prisma 데이터 레포지토리
├── providers/ # React Context Providers
├── tanstack-query/ # 데이터 페칭 설정
└── zod/ # 스키마 검증
i18n/ # next-intl 설정 + 번역 키 동기화 스크립트
message/ # 로케일 메시지 (ko-kr, en-us, ja-jp)
prisma/ # DB 스키마 (메인 77 모델 + EC 3 모델)
batch.cron.mjs # node-cron 배치 진입점 (PM2 전용 프로세스)레이어 구조
역할별 페이지(app/) → 컴포넌트(components/) → 서비스(services/) → 레포지토리(lib/repositories/) → Prisma ORM → MySQL/MariaDB 구조로, 관심사가 명확히 분리되어 있습니다.
멀티 데이터베이스
메인 DB(dps, 77개 모델)와 전자상거래 DB(make-status, 3개 모델)를 각각 별도의 Prisma 설정(prisma.config.ts / prisma-ec.config.ts)으로 생성·관리합니다.
무중단 배포
PM2로 Blue(:3010)·Green(:3011) 두 인스턴스를 독립 빌드 디렉토리(.next-blue, .next-green)로 운영하고, 배포 스크립트가 비활성 인스턴스에 빌드 후 트래픽을 전환합니다. 배치 프로세스(dps-batch)는 별도 PM2 앱으로 분리해 웹 인스턴스 재기동과 무관하게 유지됩니다.
담당 역할
24년 정부지원사업 프로토타입에서 출발해 실서비스·매출 단계까지 확장한 플랫폼으로, 총 개발 리더를 맡아 개발 기여 약 60%로 참여했습니다. 팀 규모는 2~7명을 오갔고, 2026년 6월부터는 단독으로 개발·운영하고 있습니다.
- 프론트엔드: 관리자·파트너·스토어 페이지 UI/UX 개발, 상태 관리 설계, 폼 검증 체계 구축
- 백엔드: REST API 설계·구현, Prisma ORM 기반 DB 설계, NextAuth 인증 시스템 구축
- 외부 연동: 스마트스토어·Cafe24 OAuth 및 주문 동기화, 외부 제조사 자동 발주, Jarvis SSO, 알림톡·Innopay 결제 연동
- 자동화: 배치 스케줄러 설계·구현 (주문 승인, 결제, 배송 추적, 정산, 통계, 개인정보 파기 등)
- 옵션 체계 확장: SKU 비종속 옵션(표현축) 데이터 모델·조회 토큰·조합 판정 로직과 에디터 연동 API 계약 설계, 신규 Next.js 에디터로의 카테고리·옵션 계약 이관
- 인프라: PM2 Blue-Green 무중단 배포, Winston 로깅 체계 구축, 프레임워크 메이저 업그레이드 주도
- 팀 리딩: 2~7명 규모 팀의 개발 리더로 역할군별 백오피스(200+ 페이지 · 400+ 컴포넌트) 설계·분배
성과
- 관리자·판매자·스토어·크리에이터 4개 역할 통합 플랫폼 구축 (202개 페이지 / 276개 API / 77개 모델)
- 17개 배치 작업 자동화로 승인·결제·발주·정산 흐름의 수작업 운영 비용 절감
- 스마트스토어·Cafe24·고도몰 등 외부 채널과 외부 제조사 발주까지 주문 파이프라인 통합
- 공급사 오픈 API·연동 가이드를 제공해 외부 제조사 자체 시스템 연동 지원
- Next.js 16, Prisma 7, Tailwind CSS 4 등 메이저 마이그레이션을 운영 중단 없이 완료
- 재고 SKU를 늘리지 않는 표현축 옵션 체계를 도입해, 색상·인쇄면 같은 디자인 축을 SKU 폭증 없이 판매 가능한 조합으로 관리
- 상세 미생성 주문의 사유를 저장·노출하는 구조로 바꿔, 외부 채널 주문이 조용히 누락되던 구간을 화면에서 판정 가능하게 전환