Appearance
NextMarket Stored Procedures 가이드
Database: MySQL 8.x 설계 원칙: StepPay API 응답 구조 기반, NMT_* 테이블 + NMP_* 프로시저 체계 관련 문서: Database_Schema.md 소스 위치:
nextmarket-db/(각 도메인별__2_procedures/디렉토리)
1. 개요
NextMarket API는 ORM을 사용하지 않고 MySQL Stored Procedure를 직접 호출합니다.
1.1 호출 방식
DatabaseService.call() 메서드는 @nextpay/mysql 패턴을 적용하여 OUT 파라미터를 자동 처리합니다.
typescript
// IN 파라미터만 전달 → OUT(@code, @msg) 자동 추가
const result = await this.db.call<T>('NMP_NAME', param1, param2, ...);
// 내부 실행 SQL:
// CALL NMP_NAME(?, ?, @code, @msg); SELECT @code AS resultCode, @msg AS resultMessage;
const data = result[0]?.[0]; // 단일 결과
const list = result[0]; // 목록 결과동작 원리:
- IN 파라미터 뒤에
@code, @msg자동 추가 (SP의 OUT P_RESULT_CODE, P_RESULT_MSG에 바인딩) SELECT @code, @msg결과로 성공/실패 판단resultCode < 0이면DatabaseErrorthrow- 반환값에서 OkPacket과 상태 결과 자동 제거 → 순수 SELECT ResultSet 배열만 반환
에러 처리:
typescript
import { DatabaseError } from '../database/database.service';
try {
const result = await this.db.call('NMP_ORDER_CREATE', ...params);
} catch (error) {
if (error instanceof DatabaseError) {
// error.code: -1(이미존재), -2(미존재), -3(변경없음), -1000(예외)
// error.message: SP에서 반환한 메시지
}
}1.2 명명 규칙
| 접두사 | 용도 | 예시 |
|---|---|---|
| NMP_SYNC_* | StepPay 데이터 동기화 (Upsert) | NMP_SYNC_USER |
| NMP_GET_* | 단일/목록 조회 | NMP_GET_USER_BY_USERNAME |
| NMP_*_CREATE | 생성 | NMP_ORDER_CREATE |
| NMP_*_CREATE_STEPPAY | StepPay 매핑 테이블 저장 | NMP_ORDER_CREATE_STEPPAY |
| NMP__UPDATE | 수정 | NMP_ORDER_UPDATE_STATUS |
| NMP_*_DELETE | 삭제 | NMP_PRODUCT_DELETE |
| NMP_SYS_* | 시스템 공통 (열거형, 다국어) | NMP_SYS_ENUM_LIST |
1.3 에러 처리 패턴
모든 SP에 OUT 파라미터 + EXIT HANDLER 패턴이 적용되어 있습니다:
sql
CREATE PROCEDURE NMP_EXAMPLE(
IN P_PARAM1 ${TYPE},
OUT P_RESULT_CODE ${IDX},
OUT P_RESULT_MSG ${DESC}
)
PROC_BODY: BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
P_RESULT_CODE = MYSQL_ERRNO,
P_RESULT_MSG = MESSAGE_TEXT;
SET P_RESULT_MSG = CONCAT('[', P_RESULT_CODE, ']', P_RESULT_MSG);
SET P_RESULT_CODE = ${EXCEPTION_NO};
END;
SET P_RESULT_CODE = 0;
SET P_RESULT_MSG = 'succeed';
-- 비즈니스 로직
END| 코드 | 의미 |
|---|---|
| 0 | 성공 (Succeed) |
| -1 | 이미 존재 (Already exist) |
| -2 | 존재하지 않음 (Not exist) / 파라미터 오류 |
| -3 | 변경 없음 (No change) |
| -1000 | SQL 예외 (Exception) |
1.4 SP 전체 현황
| 도메인 | 합계 | 소스 위치 |
|---|---|---|
| 00.common (시스템 공통) | 8 | nextmarket-db/00.common/00__2_procedures/ |
| 02.users (고객+배송지) | 9 | nextmarket-db/02.users/02__2_procedures/ |
| 03.products (상품/카테고리/가격) | 19 | nextmarket-db/03.products/03__2_procedures/ |
| 04.orders (주문+구독) | 24 | nextmarket-db/04.orders/04__2_procedures/ |
| 06.webhooks (웹훅) | 2 | nextmarket-db/06.webhooks/06__2_procedures/ |
모든 SP에 OUT 파라미터 + 에러 처리 패턴 적용 완료 ✅
1.5 상태값 형식
모든 상태값은 GROUP:VALUE 형식으로 관리됩니다 (NMT_SYS_ENUM_GROUP/VALUE 테이블 기반):
USR_STAT:NORMAL, USR_STAT:DORMANT
ORD_TYPE:ONETIME, ORD_TYPE:RECURRING_INITIAL, ORD_TYPE:RECURRING, ORD_TYPE:PAID, ORD_TYPE:CANCELLED, ORD_TYPE:FAILED
SUB_STAT:PENDING, SUB_STAT:ACTIVE, SUB_STAT:PAUSED, SUB_STAT:CANCELLED, SUB_STAT:CANCEL_PENDING, SUB_STAT:EXPIRED, SUB_STAT:UNPAID, SUB_STAT:FAILED
PRD_STATUS:DRAFT, PRD_STATUS:SALE, PRD_STATUS:SOLDOUT, PRD_STATUS:HIDDEN, PRD_STATUS:DELETED
WHL_STAT:RECEIVED, WHL_STAT:PROCESSED, WHL_STAT:FAILEDAPI에서는 status.constants.ts의 상수를 사용합니다:
typescript
import { OrderType, SubStatus } from '@common/constants/status.constants';
// OrderType.PAID → 'ORD_TYPE:PAID'2. 고객(User) 관련
2.1 NMP_SYNC_USER
StepPay 고객 데이터 동기화 (Upsert) 호출:
users.service.ts
sql
CREATE PROCEDURE NMP_SYNC_USER(
IN P_ID bigint,
IN P_CODE varchar(100),
IN P_USERNAME varchar(200),
IN P_NAME varchar(50),
IN P_EMAIL varchar(200),
IN P_PHONE varchar(20),
IN P_STATUS varchar(20),
IN P_ROLE varchar(20),
IN P_MARKETING_SMS tinyint,
IN P_MARKETING_EMAIL tinyint,
IN P_MARKETING_KAKAO tinyint,
IN P_ATTRIBUTES JSON,
IN P_COUNTRY_CODE varchar(20),
IN P_DORMANT_TS timestamp,
IN P_PASSWORD_HASH varchar(200),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
-- EXIT HANDLER ...
INSERT INTO NMT_USERS (...) VALUES (...)
ON DUPLICATE KEY UPDATE ...;
-- STP_USERS 매핑도 SP 내부에서 관리
END2.2 NMP_GET_USER_BY_USERNAME
USERNAME으로 고객 조회 (로그인 시 사용) 호출:
users.service.ts
sql
CREATE PROCEDURE NMP_GET_USER_BY_USERNAME(
IN P_USERNAME varchar(200),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT * FROM NMT_USERS WHERE USR_ID = P_USERNAME;
END2.3 NMP_GET_USER_BY_IDX
IDX로 고객 조회 호출:
users.service.ts,orders.service.ts,subscriptions.service.ts
sql
CREATE PROCEDURE NMP_GET_USER_BY_IDX(
IN P_USR_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT * FROM NMT_USERS WHERE USR_IDX = P_USR_IDX;
END2.4 NMP_GET_USER_BY_EMAIL
이메일로 고객 조회 호출:
users.service.ts
sql
CREATE PROCEDURE NMP_GET_USER_BY_EMAIL(
IN P_EMAIL varchar(200),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT * FROM NMT_USERS WHERE USR_EMAIL = P_EMAIL;
END2.5 NMP_UPDATE_USER
고객 기본 정보 수정 호출:
users.service.ts
sql
CREATE PROCEDURE NMP_UPDATE_USER(
IN P_USR_IDX int,
IN P_NAME varchar(50),
IN P_PHONE varchar(20),
IN P_EMAIL varchar(200),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_USERS
SET USR_NM = COALESCE(P_NAME, USR_NM),
USR_PHONE = COALESCE(P_PHONE, USR_PHONE),
USR_EMAIL = COALESCE(P_EMAIL, USR_EMAIL)
WHERE USR_IDX = P_USR_IDX;
END2.6 NMP_UPDATE_USER_PASSWORD
비밀번호 변경 호출:
users.service.ts
sql
CREATE PROCEDURE NMP_UPDATE_USER_PASSWORD(
IN P_USR_IDX int,
IN P_PASSWORD_HASH varchar(200),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_USERS SET PASSWORD_HASH = P_PASSWORD_HASH WHERE USR_IDX = P_USR_IDX;
END2.7 NMP_UPDATE_USER_LAST_LOGIN
마지막 로그인 시간 갱신 호출:
users.service.ts
sql
CREATE PROCEDURE NMP_UPDATE_USER_LAST_LOGIN(
IN P_USR_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_USERS SET LAST_LOGIN_TS = NOW() WHERE USR_IDX = P_USR_IDX;
END2.8 NMP_SET_USER_DORMANT
회원 휴면 처리 (탈퇴) 호출:
users.service.ts
sql
CREATE PROCEDURE NMP_SET_USER_DORMANT(
IN P_USR_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_USERS
SET USR_STATUS = 'USR_STAT:DORMANT', DORMANT_TS = NOW()
WHERE USR_IDX = P_USR_IDX;
END2.9 NMP_GET_USER_BY_PHONE
전화번호로 사용자 조회 호출:
users.service.ts
sql
CREATE PROCEDURE NMP_GET_USER_BY_PHONE(
IN P_PHONE varchar(20),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT * FROM NMT_USERS WHERE USR_PHONE = P_PHONE;
END2.10 NMP_DELETE_USER
사용자 삭제 (STP_USERS 매핑 + NMT_USERS 데이터 삭제) 호출:
users.service.ts
sql
CREATE PROCEDURE NMP_DELETE_USER(
IN P_USR_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
DELETE FROM STP_USERS WHERE USR_IDX = P_USR_IDX;
DELETE FROM NMT_USERS WHERE USR_IDX = P_USR_IDX;
END3. 상품(Product) 관련
3.1 NMP_SYNC_PRODUCT
StepPay 상품 데이터 동기화 (Upsert)
sql
CREATE PROCEDURE NMP_SYNC_PRODUCT(
IN P_ID bigint,
IN P_CODE varchar(100),
IN P_TYPE varchar(20),
IN P_STATUS varchar(20),
IN P_NAME varchar(200),
IN P_SUB_TITLE varchar(200),
IN P_DESCRIPTION text,
IN P_SUMMARY text,
IN P_SKU varchar(50),
IN P_NOTICE text,
IN P_FEATURED_IMAGE_URL varchar(200),
IN P_IMAGE_URLS JSON,
IN P_QUANTITY int,
IN P_ENABLED_DEMO tinyint,
IN P_DEMO_PERIOD int,
IN P_DEMO_PERIOD_UNIT varchar(20),
IN P_USE_COMBINATION tinyint,
IN P_OPTION_GROUPS JSON,
IN P_OPTION_COMBINATIONS JSON,
IN P_COMBINED_PRODUCTS JSON,
IN P_CATEGORIES JSON,
IN P_IS_ONETIME_PURCHASABLE tinyint,
IN P_PRODUCT_ORDER smallint,
IN P_EVENT_BADGE JSON,
IN P_USE_WIDGET JSON,
IN P_COUNTRY_SETTING JSON,
IN P_AVAILABLE_REGIONS JSON,
IN P_VENDOR_UUID varchar(50),
IN P_GROUP_ID bigint,
IN P_REASON_OF_REJECT text,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
INSERT INTO NMT_PRODUCTS (...) VALUES (...)
ON DUPLICATE KEY UPDATE ...;
-- STP_PRODUCTS 매핑도 SP 내부에서 관리
END3.2 NMP_GET_PRODUCTS
상품 목록 조회 (페이지네이션, 필터링) 반환: ResultSet 1: 상품 목록, ResultSet 2: TOTAL 카운트 페이지네이션: page=1부터 시작 →
(P_PAGE - 1) * P_SIZE
sql
CREATE PROCEDURE NMP_GET_PRODUCTS(
IN P_TYPE varchar(20), -- 상품 유형 필터 (NULL: 전체)
IN P_STATUS varchar(20), -- 상태 필터 (NULL: 전체)
IN P_SEARCH varchar(200), -- 검색어 (상품명)
IN P_PAGE int, -- 페이지 번호 (1부터)
IN P_SIZE int, -- 페이지 크기
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
DECLARE V_OFFSET int;
SET V_OFFSET = (P_PAGE - 1) * P_SIZE;
SELECT * FROM NMT_PRODUCTS
WHERE (P_TYPE IS NULL OR TYPE = P_TYPE)
AND (P_STATUS IS NULL OR STATUS = P_STATUS)
AND (P_SEARCH IS NULL OR PRD_NM LIKE CONCAT('%', P_SEARCH, '%'))
ORDER BY PRODUCT_ORDER, CREATE_TS DESC
LIMIT V_OFFSET, P_SIZE;
SELECT COUNT(*) AS TOTAL FROM NMT_PRODUCTS
WHERE (P_TYPE IS NULL OR TYPE = P_TYPE)
AND (P_STATUS IS NULL OR STATUS = P_STATUS)
AND (P_SEARCH IS NULL OR PRD_NM LIKE CONCAT('%', P_SEARCH, '%'));
END3.3 NMP_PRODUCT_CREATE
상품 생성 호출:
products.service.ts
sql
CREATE PROCEDURE NMP_PRODUCT_CREATE(
IN P_NAME varchar(200),
IN P_DESCRIPTION text,
IN P_TYPE varchar(20),
IN P_QUANTITY int,
IN P_FEATURED_IMAGE_URL varchar(200),
IN P_STATUS varchar(20),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
-- P_NAME 빈값 검증 → resultCode = -2
INSERT INTO NMT_PRODUCTS (
PRD_NM, PRD_DESCRIPTION, TYPE, QUANTITY,
FEATURED_IMAGE_URL, STATUS
) VALUES (
P_NAME, P_DESCRIPTION,
COALESCE(P_TYPE, 'PRD_TYPE:SOFTWARE'),
P_QUANTITY, P_FEATURED_IMAGE_URL,
COALESCE(P_STATUS, 'PRD_STATUS:DRAFT')
);
SELECT LAST_INSERT_ID() AS PRD_IDX;
END3.4 NMP_PRODUCT_GET_DETAIL
상품 상세 조회 (가격플랜 포함) 호출:
products.service.ts반환: ResultSet 1: 상품 기본정보, ResultSet 2: 가격플랜
sql
CREATE PROCEDURE NMP_PRODUCT_GET_DETAIL(
IN P_PRD_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT * FROM NMT_PRODUCTS WHERE PRD_IDX = P_PRD_IDX;
SELECT * FROM NMT_PRICES WHERE PRD_IDX = P_PRD_IDX
ORDER BY SORT_ORDER;
END3.5 NMP_PRODUCT_GET_BY_IDX
IDX로 상품 기본 정보 조회 호출:
products.service.ts,subscriptions.service.ts
sql
CREATE PROCEDURE NMP_PRODUCT_GET_BY_IDX(
IN P_PRD_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT * FROM NMT_PRODUCTS WHERE PRD_IDX = P_PRD_IDX;
END3.6 NMP_PRODUCT_GET_BY_CODE
StepPay 상품 코드로 조회 (STP_PRODUCTS 매핑 테이블 JOIN) 호출:
products.service.ts
sql
CREATE PROCEDURE NMP_PRODUCT_GET_BY_CODE(
IN P_CODE varchar(100),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT p.* FROM NMT_PRODUCTS p
INNER JOIN STP_PRODUCTS sp ON sp.PRD_IDX = p.PRD_IDX
WHERE sp.STP_PRD_CODE = P_CODE;
END3.7 NMP_PRODUCT_GET_FOR_ORDER
주문 가능 상품 정보 조회 (재고 및 판매 상태 확인 포함) 호출:
orders.service.ts
sql
CREATE PROCEDURE NMP_PRODUCT_GET_FOR_ORDER(
IN P_PRD_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT * FROM NMT_PRODUCTS
WHERE PRD_IDX = P_PRD_IDX
AND STATUS = 'PRD_STATUS:SALE'
AND (QUANTITY IS NULL OR QUANTITY > 0);
END3.8 NMP_PRODUCT_UPDATE
상품 정보 수정 호출:
products.service.ts
sql
CREATE PROCEDURE NMP_PRODUCT_UPDATE(
IN P_PRD_IDX int,
IN P_NAME varchar(200),
IN P_DESCRIPTION text,
IN P_QUANTITY int,
IN P_FEATURED_IMAGE_URL varchar(200),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
-- NOT EXISTS 검증 → resultCode = -2
UPDATE NMT_PRODUCTS
SET PRD_NM = COALESCE(P_NAME, PRD_NM),
PRD_DESCRIPTION = COALESCE(P_DESCRIPTION, PRD_DESCRIPTION),
QUANTITY = COALESCE(P_QUANTITY, QUANTITY),
FEATURED_IMAGE_URL = COALESCE(P_FEATURED_IMAGE_URL, FEATURED_IMAGE_URL)
WHERE PRD_IDX = P_PRD_IDX;
END3.9 NMP_PRODUCT_UPDATE_STATUS
상품 상태 변경 (DRAFT/SALE/SOLDOUT/HIDDEN) 호출:
products.service.ts
sql
CREATE PROCEDURE NMP_PRODUCT_UPDATE_STATUS(
IN P_PRD_IDX int,
IN P_STATUS varchar(20),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_PRODUCTS SET STATUS = P_STATUS WHERE PRD_IDX = P_PRD_IDX;
END3.10 NMP_PRODUCT_DELETE
상품 삭제 (소프트 삭제) 호출:
products.service.ts
sql
CREATE PROCEDURE NMP_PRODUCT_DELETE(
IN P_PRD_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_PRODUCTS SET STATUS = 'PRD_STATUS:DELETED' WHERE PRD_IDX = P_PRD_IDX;
END3.11 NMP_PRODUCT_CREATE_STEPPAY
상품에 StepPay 연동 정보 저장 (STP_PRODUCTS 매핑 테이블) 호출:
products.service.ts
sql
CREATE PROCEDURE NMP_PRODUCT_CREATE_STEPPAY(
IN P_PRD_IDX int,
IN P_STP_PRD_IDX bigint,
IN P_STP_PRD_CODE varchar(100),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
INSERT INTO STP_PRODUCTS (PRD_IDX, STP_PRD_IDX, STP_PRD_CODE)
VALUES (P_PRD_IDX, P_STP_PRD_IDX, P_STP_PRD_CODE)
ON DUPLICATE KEY UPDATE
STP_PRD_IDX = P_STP_PRD_IDX,
STP_PRD_CODE = P_STP_PRD_CODE;
END3.12 NMP_PRODUCT_OPTION_CREATE
상품 옵션 그룹 생성 (OPTION_GROUPS JSON 배열에 추가) 호출:
products.service.ts
sql
CREATE PROCEDURE NMP_PRODUCT_OPTION_CREATE(
IN P_PRD_IDX int,
IN P_OPTION_NAME varchar(200),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_PRODUCTS
SET OPTION_GROUPS = JSON_ARRAY_APPEND(
COALESCE(OPTION_GROUPS, JSON_ARRAY()),
'$',
JSON_OBJECT('name', P_OPTION_NAME, 'values', JSON_ARRAY())
)
WHERE PRD_IDX = P_PRD_IDX;
END3.13 NMP_PRODUCT_OPTION_VALUE_CREATE
옵션 값 생성 (OPTION_GROUPS JSON 내부의 values 배열에 추가) 호출:
products.service.ts
sql
CREATE PROCEDURE NMP_PRODUCT_OPTION_VALUE_CREATE(
IN P_PRD_IDX int,
IN P_OPTION_INDEX int, -- OPTION_GROUPS 배열 내 인덱스 (0부터)
IN P_VALUE_NAME varchar(200),
IN P_ADDITIONAL_PRICE numeric(12,3),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
DECLARE V_PATH varchar(200);
SET V_PATH = CONCAT('$[', P_OPTION_INDEX, '].values');
UPDATE NMT_PRODUCTS
SET OPTION_GROUPS = JSON_ARRAY_APPEND(
OPTION_GROUPS, V_PATH,
JSON_OBJECT('name', P_VALUE_NAME, 'additionalPrice', P_ADDITIONAL_PRICE)
)
WHERE PRD_IDX = P_PRD_IDX;
END3.14 NMP_PRODUCT_IMAGE_CREATE
상품 이미지 추가 (IMAGE_URLS JSON 배열에 추가) 호출:
products.service.ts
sql
CREATE PROCEDURE NMP_PRODUCT_IMAGE_CREATE(
IN P_PRD_IDX int,
IN P_IMAGE_URL varchar(200),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_PRODUCTS
SET IMAGE_URLS = JSON_ARRAY_APPEND(
COALESCE(IMAGE_URLS, JSON_ARRAY()), '$', P_IMAGE_URL
)
WHERE PRD_IDX = P_PRD_IDX;
END4. 카테고리(Category) 관련
4.1 NMP_CATEGORY_LIST
카테고리 목록 조회 (NMT_PRODUCTS의 CATEGORIES JSON에서 고유 카테고리 추출) 호출:
products.service.ts
sql
CREATE PROCEDURE NMP_CATEGORY_LIST(
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT DISTINCT JT.CATEGORY_ID
FROM NMT_PRODUCTS P,
JSON_TABLE(P.CATEGORIES, '$[*]' COLUMNS (
CATEGORY_ID bigint PATH '$'
)) AS JT
WHERE P.STATUS != 'PRD_STATUS:DELETED'
ORDER BY JT.CATEGORY_ID;
END4.2 NMP_CATEGORY_GET_BY_IDX
카테고리별 상품 목록 조회 호출:
products.service.ts
sql
CREATE PROCEDURE NMP_CATEGORY_GET_BY_IDX(
IN P_CATEGORY_ID bigint,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT * FROM NMT_PRODUCTS
WHERE JSON_CONTAINS(CATEGORIES, CAST(P_CATEGORY_ID AS CHAR))
AND STATUS != 'PRD_STATUS:DELETED'
ORDER BY PRODUCT_ORDER, CREATE_TS DESC;
END5. 가격 플랜(Price) 관련
5.1 NMP_PRICE_PLAN_CREATE
가격 플랜 생성 호출:
products.service.ts
sql
CREATE PROCEDURE NMP_PRICE_PLAN_CREATE(
IN P_PRD_IDX int,
IN P_NAME varchar(200),
IN P_PRICE numeric(12,3),
IN P_RECURRING_INTERVAL varchar(20), -- DAY/WEEK/MONTH/YEAR
IN P_RECURRING_INTERVAL_COUNT int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
INSERT INTO NMT_PRICES (
PRD_IDX, TYPE, PRICE, PRC_NM, RECURRING
) VALUES (
P_PRD_IDX,
IF(P_RECURRING_INTERVAL IS NULL, 'PRC_TYPE:ONE_TIME', 'PRC_TYPE:FLAT'),
P_PRICE, P_NAME,
IF(P_RECURRING_INTERVAL IS NOT NULL,
JSON_OBJECT('interval', P_RECURRING_INTERVAL, 'intervalCount', P_RECURRING_INTERVAL_COUNT),
NULL)
);
SELECT LAST_INSERT_ID() AS PRC_IDX;
END5.2 NMP_PRICE_GET_BY_IDX
가격 플랜 단건 조회 호출:
subscriptions.service.ts
sql
CREATE PROCEDURE NMP_PRICE_GET_BY_IDX(
IN P_PRC_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT * FROM NMT_PRICES WHERE PRC_IDX = P_PRC_IDX;
END5.3 NMP_PRICE_CREATE_STEPPAY
가격 플랜에 StepPay 연동 정보 저장 (STP_PRICES 매핑 테이블) 호출:
products.service.ts
sql
CREATE PROCEDURE NMP_PRICE_CREATE_STEPPAY(
IN P_PRC_IDX int,
IN P_STP_PRC_IDX bigint,
IN P_STP_PRC_CODE varchar(100),
IN P_STP_PRD_IDX bigint,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
INSERT INTO STP_PRICES (PRC_IDX, STP_PRC_IDX, STP_PRC_CODE, STP_PRD_IDX)
VALUES (P_PRC_IDX, P_STP_PRC_IDX, P_STP_PRC_CODE, P_STP_PRD_IDX)
ON DUPLICATE KEY UPDATE
STP_PRC_IDX = P_STP_PRC_IDX,
STP_PRC_CODE = P_STP_PRC_CODE,
STP_PRD_IDX = P_STP_PRD_IDX;
END5.4 NMP_SYNC_PRICE_PLAN
StepPay 가격 플랜 데이터 동기화 (Upsert) NMT_PRICES + STP_PRICES 동시 저장 호출:
sync.service.ts
sql
CREATE PROCEDURE NMP_SYNC_PRICE_PLAN(
IN P_STP_PRC_IDX bigint,
IN P_STP_PRC_CODE varchar(100),
IN P_STP_PRD_IDX bigint,
IN P_TYPE varchar(30),
IN P_PRICE numeric(12,3),
IN P_NAME varchar(200),
IN P_RECURRING JSON,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
-- 1. STP_PRODUCTS에서 로컬 상품 IDX 조회
-- 2. STP_PRICES에서 기존 매핑 확인
-- 3A. 기존 → NMT_PRICES UPDATE
-- 3B. 신규 → NMT_PRICES INSERT + STP_PRICES INSERT
END6. 주문(Order) 관련
6.1 NMP_SYNC_ORDER
StepPay 주문 데이터 동기화 (Upsert)
sql
CREATE PROCEDURE NMP_SYNC_ORDER(
IN P_ID bigint,
IN P_CODE varchar(100),
IN P_USER_IDX int,
IN P_USER_NAME varchar(50),
IN P_TYPE varchar(20),
IN P_PRODUCT_NAME varchar(200),
IN P_PRICE numeric(12,3),
IN P_PAID_AMOUNT numeric(12,3),
IN P_CURRENCY varchar(20),
IN P_PAYMENT_METHOD varchar(50),
IN P_PAYMENT_DATE timestamp,
IN P_SHIPPING JSON,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
INSERT INTO NMT_ORDERS (
UNIX_ORD_DT, ORD_DT, ORD_TM,
USR_IDX, USR_NM,
ORD_TYPE, PRODUCT_NAME, PRICE, PAID_AMOUNT,
CURRENCY, PAYMENT_METHOD, PAYMENT_DATE, SHIPPING
) VALUES (
UNIX_TIMESTAMP(), DATE_FORMAT(NOW(), '%Y%m%d'), DATE_FORMAT(NOW(), '%H%i%S'),
P_USER_IDX, P_USER_NAME,
P_TYPE, P_PRODUCT_NAME, P_PRICE, P_PAID_AMOUNT,
P_CURRENCY, P_PAYMENT_METHOD, P_PAYMENT_DATE, P_SHIPPING
)
ON DUPLICATE KEY UPDATE ...;
-- STP_ORDERS 매핑도 SP 내부에서 관리
END참고: NMT_ORDERS는 파티션 테이블이므로
UNIX_ORD_DT,ORD_DT,ORD_TM반드시 설정 필요
6.2 NMP_ORDER_CREATE
주문 생성 호출:
orders.service.ts
sql
CREATE PROCEDURE NMP_ORDER_CREATE(
IN P_USR_IDX int,
IN P_TYPE varchar(20), -- ORD_TYPE:ONETIME 등
IN P_PRODUCT_NAME varchar(200),
IN P_PRICE numeric(12,3),
IN P_TOTAL_AMOUNT numeric(12,3),
IN P_RECIPIENT_NAME varchar(50),
IN P_PHONE varchar(20),
IN P_ZIPCODE varchar(10),
IN P_ADDRESS varchar(200),
IN P_ADDRESS_DETAIL varchar(200),
IN P_MEMO varchar(200),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
INSERT INTO NMT_ORDERS (
UNIX_ORD_DT, ORD_DT, ORD_TM,
USR_IDX, USR_NM,
ORD_TYPE, PRODUCT_NAME, PRICE, PAID_AMOUNT, CURRENCY,
SHIPPING
) VALUES (
UNIX_TIMESTAMP(), DATE_FORMAT(NOW(), '%Y%m%d'), DATE_FORMAT(NOW(), '%H%i%S'),
P_USR_IDX, '',
COALESCE(P_TYPE, 'ORD_TYPE:ONETIME'),
P_PRODUCT_NAME, P_PRICE, P_TOTAL_AMOUNT, 'CURRENCY:KRW',
JSON_OBJECT(
'recipientName', P_RECIPIENT_NAME,
'phone', P_PHONE,
'zipCode', P_ZIPCODE,
'address', P_ADDRESS,
'addressDetail', P_ADDRESS_DETAIL,
'memo', P_MEMO
)
);
SELECT LAST_INSERT_ID() AS ORD_IDX;
END6.3 NMP_ORDER_ITEM_CREATE
주문 항목 생성 호출:
orders.service.ts
sql
CREATE PROCEDURE NMP_ORDER_ITEM_CREATE(
IN P_ORD_IDX int,
IN P_PRD_IDX int,
IN P_PRC_IDX int,
IN P_PRD_NM varchar(200),
IN P_PRC_NM varchar(200),
IN P_QUANTITY int,
IN P_UNIT_PRICE numeric(12,3),
IN P_TOTAL_PRICE numeric(12,3),
IN P_SELECTED_OPTIONS JSON,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
INSERT INTO NMT_ORDER_ITEMS (
ORD_IDX, PRD_IDX, PRC_IDX,
PRD_NM, PRC_NM, QUANTITY, UNIT_PRICE, TOTAL_PRICE,
SELECTED_OPTIONS, UNIX_CREATE_DT
) VALUES (
P_ORD_IDX, P_PRD_IDX, P_PRC_IDX,
P_PRD_NM, P_PRC_NM, P_QUANTITY, P_UNIT_PRICE, P_TOTAL_PRICE,
P_SELECTED_OPTIONS, UNIX_TIMESTAMP()
);
SELECT LAST_INSERT_ID() AS ORI_IDX;
END참고: NMT_ORDER_ITEMS는 파티션 테이블이므로
UNIX_CREATE_DT반드시 설정 필요
6.4 NMP_ORDER_CREATE_STEPPAY
주문에 StepPay 연동 정보 저장 (STP_ORDERS 매핑 테이블) 호출:
orders.service.ts
sql
CREATE PROCEDURE NMP_ORDER_CREATE_STEPPAY(
IN P_ORD_IDX int,
IN P_STP_ORD_IDX bigint,
IN P_STP_ORD_CODE varchar(100),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
INSERT INTO STP_ORDERS (ORD_IDX, STP_ORD_IDX, STP_ORD_CODE)
VALUES (P_ORD_IDX, P_STP_ORD_IDX, P_STP_ORD_CODE)
ON DUPLICATE KEY UPDATE
STP_ORD_IDX = P_STP_ORD_IDX,
STP_ORD_CODE = P_STP_ORD_CODE;
END6.5 NMP_ORDER_UPDATE_STATUS
주문 상태 업데이트 호출:
orders.service.ts,webhooks.service.ts
sql
CREATE PROCEDURE NMP_ORDER_UPDATE_STATUS(
IN P_ORD_IDX int,
IN P_STATUS varchar(20), -- ORD_TYPE:PAID, ORD_TYPE:CANCELLED 등
IN P_PAYMENT_METHOD varchar(50),
IN P_PAYMENT_DATE timestamp,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
-- 존재 여부 확인
IF NOT EXISTS (SELECT 1 FROM NMT_ORDERS WHERE ORD_IDX = P_ORD_IDX) THEN
SET P_RESULT_CODE = -2;
SET P_RESULT_MSG = 'Order not found';
LEAVE PROC_BODY;
END IF;
UPDATE NMT_ORDERS
SET ORD_TYPE = P_STATUS,
PAYMENT_METHOD = COALESCE(P_PAYMENT_METHOD, PAYMENT_METHOD),
PAYMENT_DATE = COALESCE(P_PAYMENT_DATE, PAYMENT_DATE)
WHERE ORD_IDX = P_ORD_IDX;
END6.6 NMP_ORDER_LIST_BY_USER
사용자별 주문 목록 조회 (페이징, STP_ORDERS LEFT JOIN) 호출:
orders.service.ts반환: ResultSet 1: 주문 목록, ResultSet 2: TOTAL 페이지네이션: page=1부터 시작 →(P_PAGE - 1) * P_SIZE
sql
CREATE PROCEDURE NMP_ORDER_LIST_BY_USER(
IN P_USR_IDX int,
IN P_STATUS varchar(20), -- NULL이면 전체
IN P_PAGE int,
IN P_SIZE int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
DECLARE V_OFFSET int;
SET V_OFFSET = (P_PAGE - 1) * P_SIZE;
SELECT o.*, so.STP_ORD_IDX, so.STP_ORD_CODE
FROM NMT_ORDERS o
LEFT JOIN STP_ORDERS so ON so.ORD_IDX = o.ORD_IDX
WHERE o.USR_IDX = P_USR_IDX
AND (P_STATUS IS NULL OR o.ORD_TYPE = P_STATUS)
ORDER BY o.CREATE_TS DESC
LIMIT V_OFFSET, P_SIZE;
SELECT COUNT(*) AS TOTAL FROM NMT_ORDERS
WHERE USR_IDX = P_USR_IDX
AND (P_STATUS IS NULL OR ORD_TYPE = P_STATUS);
END6.7 NMP_ORDER_GET_BY_IDX
주문 상세 조회 (항목 포함, STP_ORDERS LEFT JOIN) 호출:
orders.service.ts반환: ResultSet 1: 주문 정보, ResultSet 2: 주문 항목
sql
CREATE PROCEDURE NMP_ORDER_GET_BY_IDX(
IN P_ORD_IDX int,
IN P_USR_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT o.*, so.STP_ORD_IDX, so.STP_ORD_CODE
FROM NMT_ORDERS o
LEFT JOIN STP_ORDERS so ON so.ORD_IDX = o.ORD_IDX
WHERE o.ORD_IDX = P_ORD_IDX AND o.USR_IDX = P_USR_IDX;
SELECT * FROM NMT_ORDER_ITEMS
WHERE ORD_IDX = P_ORD_IDX;
END6.8 NMP_ORDER_CANCEL
주문 취소 호출:
orders.service.ts
sql
CREATE PROCEDURE NMP_ORDER_CANCEL(
IN P_ORD_IDX int,
IN P_REASON varchar(200),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_ORDERS
SET ORD_TYPE = 'ORD_TYPE:CANCELLED'
WHERE ORD_IDX = P_ORD_IDX;
END6.9 NMP_ORDER_DECREASE_STOCK
결제 완료 시 재고 차감 호출:
webhooks.service.ts
sql
CREATE PROCEDURE NMP_ORDER_DECREASE_STOCK(
IN P_ORD_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_PRODUCTS P
INNER JOIN NMT_ORDER_ITEMS OI ON OI.PRD_IDX = P.PRD_IDX
SET P.QUANTITY = P.QUANTITY - OI.QUANTITY
WHERE OI.ORD_IDX = P_ORD_IDX
AND P.QUANTITY IS NOT NULL;
END6.10 NMP_ORDER_RESTORE_STOCK
주문 취소 시 재고 복원 호출:
orders.service.ts,webhooks.service.ts
sql
CREATE PROCEDURE NMP_ORDER_RESTORE_STOCK(
IN P_ORD_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_PRODUCTS P
INNER JOIN NMT_ORDER_ITEMS OI ON OI.PRD_IDX = P.PRD_IDX
SET P.QUANTITY = P.QUANTITY + OI.QUANTITY
WHERE OI.ORD_IDX = P_ORD_IDX
AND P.QUANTITY IS NOT NULL;
END6.11 NMP_ORDER_GET_BY_STP_CODE
StepPay 주문 코드로 로컬 주문 IDX 조회 호출:
webhooks.service.ts용도: 웹훅에서 StepPay 코드로 로컬 주문 IDX를 찾을 때 사용
sql
CREATE PROCEDURE NMP_ORDER_GET_BY_STP_CODE(
IN P_STP_ORD_CODE varchar(100),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT so.ORD_IDX, so.STP_ORD_IDX, so.STP_ORD_CODE
FROM STP_ORDERS so
WHERE so.STP_ORD_CODE = P_STP_ORD_CODE;
END7. 구독(Subscription) 관련
7.1 NMP_SYNC_SUBSCRIPTION
StepPay 구독 데이터 동기화 (Upsert) STP_SUBSCRIPTIONS 매핑 테이블도 관리
sql
CREATE PROCEDURE NMP_SYNC_SUBSCRIPTION(
IN P_ID bigint,
IN P_CODE varchar(100),
IN P_USER_IDX int,
IN P_STP_USER_IDX bigint,
IN P_USER_NAME varchar(50),
IN P_PRODUCT_NAME varchar(200),
IN P_STATUS varchar(20),
IN P_ITEMS JSON,
IN P_RECURRING JSON,
IN P_CURRENCY varchar(20),
IN P_NEXT_PAYMENT_DATE_TIME timestamp,
IN P_PAYMENT_METHOD JSON,
IN P_START_DATE_TIME timestamp,
IN P_END_DATE_TIME timestamp,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
INSERT INTO NMT_SUBSCRIPTIONS (
UNIX_CREATE_DT, USR_IDX, USR_NM, PRD_NM, SUB_STATUS,
ITEMS, RECURRING, CURRENCY, NEXT_PAYMENT_DATE_TIME, PAYMENT_METHOD,
START_DATE_TIME, END_DATE_TIME
) VALUES (
UNIX_TIMESTAMP(), P_USER_IDX, P_USER_NAME, P_PRODUCT_NAME, P_STATUS,
P_ITEMS, P_RECURRING, P_CURRENCY, P_NEXT_PAYMENT_DATE_TIME, P_PAYMENT_METHOD,
P_START_DATE_TIME, P_END_DATE_TIME
)
ON DUPLICATE KEY UPDATE ...;
-- STP_SUBSCRIPTIONS 매핑 테이블도 SP 내부에서 관리
END참고: NMT_SUBSCRIPTIONS는 파티션 테이블이므로
UNIX_CREATE_DT반드시 설정 필요
7.2 NMP_GET_USER_SUBSCRIPTIONS
고객별 구독 목록 조회 (STP_SUBSCRIPTIONS LEFT JOIN) 호출:
subscriptions.service.ts
sql
CREATE PROCEDURE NMP_GET_USER_SUBSCRIPTIONS(
IN P_USR_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT s.*, ss.STP_SUB_IDX, ss.STP_SUB_CODE
FROM NMT_SUBSCRIPTIONS s
LEFT JOIN STP_SUBSCRIPTIONS ss ON ss.SUB_IDX = s.SUB_IDX
WHERE s.USR_IDX = P_USR_IDX
ORDER BY s.CREATE_TS DESC;
END7.3 NMP_SUBSCRIPTION_CREATE
구독 생성 호출:
subscriptions.service.ts
sql
CREATE PROCEDURE NMP_SUBSCRIPTION_CREATE(
IN P_USR_IDX int,
IN P_PRD_NM varchar(200),
IN P_RECURRING_INTERVAL varchar(20), -- DAY/WEEK/MONTH/YEAR
IN P_RECURRING_INTERVAL_COUNT int,
IN P_CURRENCY varchar(20),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
INSERT INTO NMT_SUBSCRIPTIONS (
UNIX_CREATE_DT, USR_IDX,
PRD_NM, SUB_STATUS, CURRENCY, RECURRING
) VALUES (
UNIX_TIMESTAMP(), P_USR_IDX,
P_PRD_NM, 'SUB_STAT:PENDING',
COALESCE(P_CURRENCY, 'CURRENCY:KRW'),
JSON_OBJECT(
'interval', P_RECURRING_INTERVAL,
'intervalCount', COALESCE(P_RECURRING_INTERVAL_COUNT, 1)
)
);
SELECT LAST_INSERT_ID() AS SUB_IDX;
END7.4 NMP_SUBSCRIPTION_CREATE_STEPPAY
구독에 StepPay 연동 정보 저장 (STP_SUBSCRIPTIONS 매핑 테이블) 호출:
subscriptions.service.ts
sql
CREATE PROCEDURE NMP_SUBSCRIPTION_CREATE_STEPPAY(
IN P_SUB_IDX int,
IN P_STP_SUB_IDX bigint,
IN P_STP_SUB_CODE varchar(100),
IN P_STP_USR_IDX bigint,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
INSERT INTO STP_SUBSCRIPTIONS (SUB_IDX, STP_SUB_IDX, STP_SUB_CODE, STP_USR_IDX)
VALUES (P_SUB_IDX, P_STP_SUB_IDX, P_STP_SUB_CODE, P_STP_USR_IDX)
ON DUPLICATE KEY UPDATE
STP_SUB_IDX = P_STP_SUB_IDX,
STP_SUB_CODE = P_STP_SUB_CODE,
STP_USR_IDX = P_STP_USR_IDX;
END7.5 NMP_SUBSCRIPTION_CHECK_ACTIVE
기존 활성 구독 확인 (중복 구독 방지, STP_SUBSCRIPTIONS LEFT JOIN) 호출:
subscriptions.service.ts
sql
CREATE PROCEDURE NMP_SUBSCRIPTION_CHECK_ACTIVE(
IN P_USR_IDX int,
IN P_PRD_NM varchar(200), -- 상품명으로 매칭
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT s.*, ss.STP_SUB_IDX, ss.STP_SUB_CODE
FROM NMT_SUBSCRIPTIONS s
LEFT JOIN STP_SUBSCRIPTIONS ss ON ss.SUB_IDX = s.SUB_IDX
WHERE s.USR_IDX = P_USR_IDX
AND s.SUB_STATUS = 'SUB_STAT:ACTIVE'
AND (P_PRD_NM IS NULL OR s.PRD_NM = P_PRD_NM);
END7.6 NMP_SUBSCRIPTION_LIST_BY_USER
사용자별 구독 목록 조회 (페이징, STP_SUBSCRIPTIONS LEFT JOIN) 호출:
subscriptions.service.ts반환: ResultSet 1: 구독 목록, ResultSet 2: TOTAL 페이지네이션: page=1부터 시작 →(P_PAGE - 1) * P_SIZE
sql
CREATE PROCEDURE NMP_SUBSCRIPTION_LIST_BY_USER(
IN P_USR_IDX int,
IN P_STATUS varchar(20), -- NULL이면 전체
IN P_PAGE int,
IN P_SIZE int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
DECLARE V_OFFSET int;
SET V_OFFSET = (P_PAGE - 1) * P_SIZE;
SELECT s.*, ss.STP_SUB_IDX, ss.STP_SUB_CODE
FROM NMT_SUBSCRIPTIONS s
LEFT JOIN STP_SUBSCRIPTIONS ss ON ss.SUB_IDX = s.SUB_IDX
WHERE s.USR_IDX = P_USR_IDX
AND (P_STATUS IS NULL OR s.SUB_STATUS = P_STATUS)
ORDER BY s.CREATE_TS DESC
LIMIT V_OFFSET, P_SIZE;
SELECT COUNT(*) AS TOTAL FROM NMT_SUBSCRIPTIONS
WHERE USR_IDX = P_USR_IDX
AND (P_STATUS IS NULL OR SUB_STATUS = P_STATUS);
END7.7 NMP_SUBSCRIPTION_GET_BY_IDX
구독 상세 조회 (STP_SUBSCRIPTIONS LEFT JOIN) 호출:
subscriptions.service.ts
sql
CREATE PROCEDURE NMP_SUBSCRIPTION_GET_BY_IDX(
IN P_SUB_IDX int,
IN P_USR_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT s.*, ss.STP_SUB_IDX, ss.STP_SUB_CODE
FROM NMT_SUBSCRIPTIONS s
LEFT JOIN STP_SUBSCRIPTIONS ss ON ss.SUB_IDX = s.SUB_IDX
WHERE s.SUB_IDX = P_SUB_IDX AND s.USR_IDX = P_USR_IDX;
END7.8 NMP_SUBSCRIPTION_UPDATE_STATUS
구독 상태 변경 (STP_SUBSCRIPTIONS INNER JOIN) 호출:
webhooks.service.ts,subscriptions.service.ts
sql
CREATE PROCEDURE NMP_SUBSCRIPTION_UPDATE_STATUS(
IN P_STP_SUB_IDX bigint,
IN P_STATUS varchar(20), -- SUB_STAT:ACTIVE, PAUSED, CANCELLED, EXPIRED, UNPAID
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_SUBSCRIPTIONS s
INNER JOIN STP_SUBSCRIPTIONS ss ON ss.SUB_IDX = s.SUB_IDX
SET s.SUB_STATUS = P_STATUS
WHERE ss.STP_SUB_IDX = P_STP_SUB_IDX;
END7.9 NMP_SUBSCRIPTION_ACTIVATE
구독 활성화 (결제 완료 웹훅 수신 시, STP_SUBSCRIPTIONS INNER JOIN) 호출:
webhooks.service.ts
sql
CREATE PROCEDURE NMP_SUBSCRIPTION_ACTIVATE(
IN P_STP_SUB_IDX bigint,
IN P_START_DATE timestamp,
IN P_END_DATE timestamp,
IN P_NEXT_BILLING_DATE timestamp,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_SUBSCRIPTIONS s
INNER JOIN STP_SUBSCRIPTIONS ss ON ss.SUB_IDX = s.SUB_IDX
SET s.SUB_STATUS = 'SUB_STAT:ACTIVE',
s.START_DATE_TIME = P_START_DATE,
s.END_DATE_TIME = P_END_DATE,
s.NEXT_PAYMENT_DATE_TIME = P_NEXT_BILLING_DATE
WHERE ss.STP_SUB_IDX = P_STP_SUB_IDX;
END7.10 NMP_SUBSCRIPTION_RENEW
구독 갱신 (정기 결제 웹훅 수신 시, STP_SUBSCRIPTIONS INNER JOIN) 호출:
webhooks.service.ts
sql
CREATE PROCEDURE NMP_SUBSCRIPTION_RENEW(
IN P_STP_SUB_IDX bigint,
IN P_START_DATE timestamp,
IN P_END_DATE timestamp,
IN P_NEXT_BILLING_DATE timestamp,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_SUBSCRIPTIONS s
INNER JOIN STP_SUBSCRIPTIONS ss ON ss.SUB_IDX = s.SUB_IDX
SET s.START_DATE_TIME = P_START_DATE,
s.END_DATE_TIME = P_END_DATE,
s.NEXT_PAYMENT_DATE_TIME = P_NEXT_BILLING_DATE
WHERE ss.STP_SUB_IDX = P_STP_SUB_IDX;
END7.11 NMP_SUBSCRIPTION_CANCEL
구독 해지 호출:
subscriptions.service.ts
sql
CREATE PROCEDURE NMP_SUBSCRIPTION_CANCEL(
IN P_SUB_IDX int,
IN P_REASON varchar(200),
IN P_IMMEDIATELY tinyint, -- 1: 즉시 해지, 0: 기간 만료 후 해지
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_SUBSCRIPTIONS
SET SUB_STATUS = IF(P_IMMEDIATELY = 1, 'SUB_STAT:CANCELLED', 'SUB_STAT:CANCEL_PENDING')
WHERE SUB_IDX = P_SUB_IDX;
END7.12 NMP_SUBSCRIPTION_PAUSE
구독 일시정지 호출:
subscriptions.service.ts
sql
CREATE PROCEDURE NMP_SUBSCRIPTION_PAUSE(
IN P_SUB_IDX int,
IN P_REASON varchar(200),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_SUBSCRIPTIONS
SET SUB_STATUS = 'SUB_STAT:PAUSED'
WHERE SUB_IDX = P_SUB_IDX;
END7.13 NMP_SUBSCRIPTION_RESUME
구독 재개 호출:
subscriptions.service.ts
sql
CREATE PROCEDURE NMP_SUBSCRIPTION_RESUME(
IN P_SUB_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_SUBSCRIPTIONS
SET SUB_STATUS = 'SUB_STAT:ACTIVE'
WHERE SUB_IDX = P_SUB_IDX;
END8. 배송지(Address) 관련
8.1 NMP_ADDRESS_GET_BY_IDX
배송지 조회 호출:
orders.service.ts,subscriptions.service.ts
sql
CREATE PROCEDURE NMP_ADDRESS_GET_BY_IDX(
IN P_SHP_IDX int,
IN P_USR_IDX int,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
SELECT * FROM NMT_SHIPPING
WHERE SHP_IDX = P_SHP_IDX AND USR_IDX = P_USR_IDX;
END9. 웹훅 로그(Webhook Log) 관련
9.1 NMP_WEBHOOK_LOG_CREATE
웹훅 수신 로그 생성 호출:
webhooks.service.ts
sql
CREATE PROCEDURE NMP_WEBHOOK_LOG_CREATE(
IN P_EVENT_TYPE varchar(200),
IN P_PAYLOAD JSON,
IN P_SIGNATURE varchar(200),
IN P_IP_ADDRESS varchar(20),
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
INSERT INTO NMT_WEBHOOK_LOGS (
EVENT_TYPE, PAYLOAD, SIGNATURE, WHL_STATUS, IP_ADDRESS
) VALUES (
P_EVENT_TYPE, P_PAYLOAD, P_SIGNATURE, 'WHL_STAT:RECEIVED', P_IP_ADDRESS
);
SELECT LAST_INSERT_ID() AS WHL_IDX;
END9.2 NMP_WEBHOOK_LOG_UPDATE
웹훅 처리 결과 업데이트 호출:
webhooks.service.ts
sql
CREATE PROCEDURE NMP_WEBHOOK_LOG_UPDATE(
IN P_WHL_IDX int,
IN P_STATUS varchar(20), -- WHL_STAT:PROCESSED, WHL_STAT:FAILED
IN P_ERROR_MESSAGE text,
OUT P_RESULT_CODE int,
OUT P_RESULT_MSG text
)
PROC_BODY: BEGIN
UPDATE NMT_WEBHOOK_LOGS
SET WHL_STATUS = P_STATUS,
ERROR_MESSAGE = P_ERROR_MESSAGE,
PROCESSED_TS = NOW()
WHERE WHL_IDX = P_WHL_IDX;
END10. 시스템 공통 (00.common)
시스템 공통 SP는 열거형 변수(Enum), 다국어 문자열, 시스템 메시지를 관리합니다. 모든 공통 SP는 구현 완료 상태입니다.
10.1 NMP_SYS_ENUM_LIST
열거형 시스템 변수 값 목록 조회
| 파라미터 | IN/OUT | 타입 | 설명 |
|---|---|---|---|
| P_GRP_CD | IN | varchar(20) | 그룹 코드 |
| P_LANG_CD | IN | varchar(20) | 언어 코드 |
| P_RESULT_CODE | OUT | int | 결과 코드 |
| P_RESULT_MSG | OUT | text | 결과 메시지 |
10.2 NMP_SYS_ENUM_REGIST
시스템 열거형 변수 값 등록
| 파라미터 | IN/OUT | 타입 | 설명 |
|---|---|---|---|
| P_GRP_CD | IN | varchar(20) | 그룹 코드 |
| P_DTL_CD | IN | varchar(20) | 세부 코드 (빈 문자열이면 그룹만 등록) |
| P_LANG_CD | IN | varchar(20) | 언어 코드 |
| P_SYS_TXT | IN | varchar(200) | 표시 문자열 |
| P_DEF_YN | IN | char(1) | 기본 여부 |
| P_CNF_YN | IN | char(1) | 승인 여부 |
| P_RESULT_CODE | OUT | int | 결과 코드 |
| P_RESULT_MSG | OUT | text | 결과 메시지 |
10.3 NMP_SYS_ENUM_UPDATE
시스템 열거형 변수 값 수정
10.4 NMP_SYS_TEXT_LIST
시스템 언어별 문자열 전체 목록 조회 반환: 4개 ResultSet (키 VERSION, 값 VERSION, 키 목록, 값 목록)
10.5 NMP_SYS_TEXT_REGIST
언어별 시스템 문자열 등록 (키 + 값 동시 생성) TXT_CD 자동 생성 (
YYYYMM00001형식)
10.6 NMP_SYS_TEXT_ADD_REGIST
기존 문자열 키에 언어별 값 추가 등록
10.7 NMP_SYS_TEXT_UPDATE
언어별 시스템 문자열 값 수정
10.8 NMP_SYS_MESSAGE_REGIST
언어별 시스템 메시지 등록
11. 동기화 전략
11.1 데이터 흐름
StepPay (마스터) ──웹훅──> NextMarket API ──NMP_SYNC_*──> MySQL (미러)
│
└── 조회 요청 시: 로컬 DB 먼저 → 없으면 StepPay API11.2 STP_* 매핑 테이블 경유 패턴
StepPay와 로컬 DB 간의 ID 매핑은 STP_ 매핑 테이블*을 통해 관리됩니다. 이전에는 NMT_* 테이블에 직접 STP_* 컬럼을 두었지만, 현재는 별도의 매핑 테이블로 분리되었습니다.
[로컬 테이블] [매핑 테이블] [StepPay]
NMT_PRODUCTS (PRD_IDX) ←→ STP_PRODUCTS (PRD_IDX, STP_PRD_IDX, STP_PRD_CODE)
NMT_PRICES (PRC_IDX) ←→ STP_PRICES (PRC_IDX, STP_PRC_IDX, STP_PRC_CODE)
NMT_ORDERS (ORD_IDX) ←→ STP_ORDERS (ORD_IDX, STP_ORD_IDX, STP_ORD_CODE)
NMT_SUBSCRIPTIONS (SUB_IDX) ←→ STP_SUBSCRIPTIONS (SUB_IDX, STP_SUB_IDX, STP_SUB_CODE)
NMT_USERS (USR_IDX) ←→ STP_USERS (USR_IDX, STP_USR_IDX, STP_USR_CODE)매핑 저장 SP 패턴:
NMP_*_CREATE_STEPPAYSP로 매핑 테이블에 INSERT ... ON DUPLICATE KEY UPDATE- 예:
NMP_ORDER_CREATE_STEPPAY,NMP_PRODUCT_CREATE_STEPPAY,NMP_SUBSCRIPTION_CREATE_STEPPAY,NMP_PRICE_CREATE_STEPPAY
조회 시 JOIN 패턴:
- 조회 SP에서
LEFT JOIN STP_*으로 StepPay 매핑 정보 함께 반환 - 예:
NMP_ORDER_GET_BY_IDX는LEFT JOIN STP_ORDERS로 STP_ORD_IDX, STP_ORD_CODE 포함
11.3 웹훅에서 StepPay 코드 → 로컬 IDX 변환
웹훅은 StepPay 코드(STP_ORD_CODE 등)로 이벤트를 수신하므로, 로컬 IDX로 변환이 필요합니다:
웹훅 수신 (STP_ORD_CODE)
→ NMP_ORDER_GET_BY_STP_CODE로 ORD_IDX 조회
→ NMP_ORDER_UPDATE_STATUS(P_ORD_IDX, ...) 호출
→ NMP_ORDER_DECREASE_STOCK(P_ORD_IDX) 호출이를 통해 모든 비즈니스 로직은 로컬 IDX 기반으로 동작하며, StepPay 의존성을 매핑 테이블로 캡슐화합니다.
11.4 동기화 방식
| 방식 | 설명 | SP |
|---|---|---|
| 실시간 | 웹훅 수신 시 즉시 반영 | NMP_SYNC_* |
| 배치 | 주기적 전체 동기화 | NMP_SYNC_* (반복 호출) |
| 온디맨드 | 조회 시 API 호출 후 저장 | NMP_SYNC_* |
11.5 충돌 해결
- StepPay가 마스터, 로컬은 미러
- ON DUPLICATE KEY UPDATE로 항상 최신 데이터 덮어쓰기
- 로컬 전용 필드(PASSWORD_HASH 등)는 COALESCE로 보존
최종 업데이트: 2026년 3월 16일 - NMP_GET_USER_BY_PHONE, NMP_DELETE_USER, NMP_SYNC_PRICE_PLAN 추가