@hamjimin/xplat-back 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,16 +1,11 @@
1
1
  # @hamjimin/xplat-back
2
2
 
3
- Express + TypeScript 백엔드 스캐폴딩 도구 (zium-backend 기반)
3
+ Express + TypeScript 백엔드 프레임워크 & CLI 스캐폴딩 도구
4
4
 
5
- 파일명과 API endpoint가 자동으로 일치하는 라우팅 시스템을 제공합니다. 디렉토리 구조를 기반으로 자동으로 Express 라우터를 생성하여, 파일명만으로 API endpoint를 매핑할 수 있습니다.
5
+ 커머스 백엔드에 필요한 **인증, 스토리지, 결제, 배송, 쿼리 빌더** 등의 모듈을 `xplatSystem` 싱글턴으로 통합 제공하며,
6
+ CLI를 통해 프로젝트 초기화와 **MySQL DDL 자동 설치**까지 지원합니다.
6
7
 
7
- ## 특징
8
-
9
- - 🚀 **파일 기반 라우팅**: 파일명과 디렉토리 구조가 API endpoint로 자동 매핑
10
- - 📁 **자동 라우터 생성**: 디렉토리 구조를 재귀적으로 탐색하여 라우터 자동 생성
11
- - ⚡ **빠른 프로젝트 설정**: CLI를 통한 프로젝트 초기화
12
- - 🔧 **TypeScript 지원**: 완전한 TypeScript 타입 정의 포함
13
- - 🎯 **zium-backend 기반**: 검증된 프로젝트 구조 기반
8
+ ---
14
9
 
15
10
  ## 설치
16
11
 
@@ -22,43 +17,39 @@ yarn add @hamjimin/xplat-back
22
17
 
23
18
  ## 빠른 시작
24
19
 
25
- ### CLI를 통한 프로젝트 초기화
26
- ```bash
27
- npx @hamjimin/xplat-back [project-name]
28
- ```
29
-
30
- 옵션:
20
+ ### 1. 프로젝트 스캐폴딩
31
21
 
32
22
  ```bash
33
- npx @hamjimin/xplat-back my-project --port 3000 --cors "http://localhost:3000,http://localhost:5173"
23
+ npx @hamjimin/xplat-back my-project
34
24
  ```
35
25
 
36
- 사용 가능한 옵션:
37
- - `-p, --port <port>`: 서버 포트 (기본값: 4000)
38
- - `-c, --cors <origins>`: CORS 허용 origins (쉼표로 구분)
39
- - `-r, --router-dir <directory>`: 라우터 디렉토리 (기본값: src/restapi)
40
- - `--router-path <path>`: 라우터 base path (기본값: /restapi)
41
- - `--with-next`: Next.js 프론트엔드(web) 템플릿 추가
26
+ 자동 생성되는 파일:
42
27
 
43
- ### 수동 설정
44
-
45
- #### 1. 패키지 설치
46
-
47
- ```bash
48
- npm install express @hamjimin/xplat-back
49
- npm install -D typescript @types/express @types/node ts-node tsconfig-paths
28
+ ```
29
+ my-project/
30
+ ├── src/
31
+ │ ├── app.ts # Express 앱 진입점
32
+ │ ├── server.ts # 서버 실행 파일
33
+ │ ├── restapi/
34
+ │ │ └── health.ts # 예시 API 라우트
35
+ │ ├── const/
36
+ │ │ ├── api_code.ts # API 응답 코드 상수
37
+ │ │ └── constants.ts # 공통 상수
38
+ │ └── util/
39
+ │ └── dbconfig/
40
+ │ └── dbConnections.ts # DB 연결 설정 (TypeORM)
41
+ ├── tsconfig.json
42
+ ├── package.json
43
+ └── .env
50
44
  ```
51
45
 
52
- #### 2. Express 앱 생성
53
-
54
- `src/app.ts`:
46
+ ### 2. Express 앱 생성
55
47
 
56
48
  ```typescript
57
- import express, { Application } from 'express';
58
- import * as path from 'path';
59
49
  import { createApp } from '@hamjimin/xplat-back';
50
+ import * as path from 'path';
60
51
 
61
- const app: Application = createApp({
52
+ const app = createApp({
62
53
  cors: {
63
54
  origin: ['http://localhost:3000'],
64
55
  credentials: true,
@@ -70,185 +61,400 @@ const app: Application = createApp({
70
61
  trustProxy: true,
71
62
  });
72
63
 
73
- const port = parseInt(process.env.PORT || '4000', 10);
74
-
75
- app.listen(port, () => {
76
- console.log(`🚀 Server is running on port ${port}`);
64
+ app.listen(4000, () => {
65
+ console.log('Server running on port 4000');
77
66
  });
78
-
79
- export default app;
80
67
  ```
81
68
 
82
- #### 3. 라우트 파일 생성
69
+ `createApp` 옵션:
70
+
71
+ | 옵션 | 타입 | 기본값 | 설명 |
72
+ |------|------|--------|------|
73
+ | `cors.origin` | `string[]` | `['*']` | CORS 허용 origin |
74
+ | `cors.credentials` | `boolean` | `true` | 자격 증명 허용 |
75
+ | `json.limit` | `string` | `'1mb'` | JSON body 크기 제한 |
76
+ | `router.directory` | `string` | `'src/restapi'` | 라우트 파일 디렉토리 |
77
+ | `router.basePath` | `string` | `'/restapi'` | 라우터 base path |
78
+ | `trustProxy` | `boolean` | `true` | 프록시 신뢰 |
79
+ | `middleware` | `Function[]` | `[]` | 커스텀 미들웨어 |
80
+
81
+ ### 3. 파일 기반 라우팅
83
82
 
84
- `src/restapi/health.ts`:
83
+ 디렉토리 구조가 API endpoint에 자동 매핑됩니다.
84
+
85
+ ```
86
+ src/restapi/
87
+ ├── health.ts → GET /restapi/health
88
+ ├── users.ts → /restapi/users
89
+ └── users/
90
+ └── profile.ts → /restapi/users/profile
91
+ ```
85
92
 
86
93
  ```typescript
87
- import express, { Request, Response } from 'express';
94
+ import { createRouter } from '@hamjimin/xplat-back';
95
+
96
+ const router = createRouter(path.join(__dirname, 'restapi'));
97
+ app.use('/restapi', router);
98
+ ```
88
99
 
89
- const router = express.Router();
100
+ ---
90
101
 
91
- router.get('/', (req: Request, res: Response) => {
92
- res.json({
93
- success: true,
94
- message: 'Server is healthy',
95
- timestamp: new Date().toISOString(),
96
- });
97
- });
102
+ ## CLI
98
103
 
99
- export = router;
104
+ ```bash
105
+ npx @hamjimin/xplat-back [project-name] [options]
106
+ npx @hamjimin/xplat-back db:setup
100
107
  ```
101
108
 
102
- 이제 `GET /restapi/health` 엔드포인트가 자동으로 생성됩니다!
109
+ ### 프로젝트 생성 옵션
103
110
 
104
- #### 4. 서버 실행
111
+ | 옵션 | 단축 | 설명 | 기본값 |
112
+ |------|------|------|--------|
113
+ | `--port <port>` | `-p` | 서버 포트 | `4000` |
114
+ | `--cors <origins>` | `-c` | CORS origins (쉼표 구분) | `http://localhost:3000` |
115
+ | `--router-dir <dir>` | `-r` | 라우터 디렉토리 | `src/restapi` |
116
+ | `--router-path <path>` | | 라우터 base path | `/restapi` |
105
117
 
106
118
  ```bash
107
- npm run dev
108
- # 또는
109
- ts-node -r tsconfig-paths/register src/app.ts
119
+ npx @hamjimin/xplat-back my-project --port 3000 --cors "http://localhost:3000,http://localhost:5173"
110
120
  ```
111
121
 
112
- ## API 문서
122
+ ### db:setup - MySQL DDL 자동 설치
113
123
 
114
- ### `createApp(config?)`
124
+ 인터랙티브 UI로 MySQL 접속 정보를 입력하고, 필요한 테이블을 선택하여 바로 생성합니다.
115
125
 
116
- Express 애플리케이션을 생성합니다.
126
+ ```bash
127
+ npx @hamjimin/xplat-back db:setup
128
+ ```
117
129
 
118
- #### Parameters
130
+ **실행 흐름:**
119
131
 
120
- ```typescript
121
- interface AppConfig {
122
- cors?: {
123
- origin?: string[] | ((origin: string | undefined, callback: (err: Error | null, allow?: boolean) => void) => void);
124
- credentials?: boolean;
125
- };
126
- json?: {
127
- limit?: string;
128
- };
129
- urlencoded?: {
130
- extended?: boolean;
131
- };
132
- router?: {
133
- directory?: string;
134
- basePath?: string;
135
- };
136
- trustProxy?: boolean;
137
- middleware?: Array<(req: Request, res: Response, next: NextFunction) => void>;
138
- }
139
132
  ```
133
+ 🗄️ xplat-back 데이터베이스 설정
140
134
 
141
- #### 예제
135
+ ? DB Host: localhost
136
+ ? DB User: root
137
+ ? DB Password: ****
138
+ ? DB Name: my_shop
139
+ ? DB Port: 3306
142
140
 
143
- ```typescript
144
- import { createApp } from '@hamjimin/xplat-back';
141
+ ✅ MySQL 연결 성공!
145
142
 
146
- const app = createApp({
147
- cors: {
148
- origin: process.env.CORS_ALLOW_ORIGINS?.split(',') ?? ['*'],
149
- credentials: true,
150
- },
151
- router: {
152
- directory: path.join(__dirname, 'restapi'),
153
- basePath: '/restapi',
154
- },
155
- middleware: [
156
- // 커스텀 미들웨어
157
- (req, res, next) => {
158
- console.log(`${req.method} ${req.path}`);
159
- next();
160
- },
161
- ],
162
- });
143
+ ? 설치할 DDL 모듈을 선택하세요 (스페이스바로 선택):
144
+ ◉ 사용자 (User / Employee / Partner)
145
+ ◉ 상품 (Category / Product / Variants / Brand / Side_Product)
146
+ ◯ 패키지 (Product_Package / Detail / Variant)
147
+ ◉ 주문 (Orders / Order_Items / Order_Manage)
148
+ ...
149
+
150
+ 📎 의존성으로 자동 추가된 모듈:
151
+ → 사용자 (01_user.sql)
152
+
153
+ 📋 실행 대상 DDL (3개 파일):
154
+ 📦 01_user.sql - 사용자
155
+ 📦 02_product.sql - 상품
156
+ 📦 04_order.sql - 주문
157
+
158
+ ? 위 3개 DDL 파일을 실행하시겠습니까? Yes
159
+
160
+ ✅ 01_user.sql → user, employee, partner
161
+ ✅ 02_product.sql → category, product, variants, brand, side_product
162
+ ✅ 04_order.sql → orders, order_items, order_manage, order_manage_comment
163
+
164
+ 🎉 데이터베이스 설정이 완료되었습니다!
163
165
  ```
164
166
 
165
- ### `createRouter(directory)`
167
+ **제공되는 DDL 모듈 (10개):**
166
168
 
167
- 디렉토리 구조를 기반으로 Express 라우터를 생성합니다.
169
+ | # | 모듈 | 테이블 |
170
+ |---|------|--------|
171
+ | 1 | 사용자 | `user`, `employee`, `partner` |
172
+ | 2 | 상품 | `category`, `product`, `variants`, `brand`, `side_product` |
173
+ | 3 | 패키지 | `product_package`, `product_package_detail`, `product_package_variant` |
174
+ | 4 | 주문 | `orders`, `order_items`, `order_manage`, `order_manage_comment` |
175
+ | 5 | 결제 | `payment`, `calcurate` |
176
+ | 6 | 배송 | `delivery`, `reservation` |
177
+ | 7 | 장바구니 | `cart`, `cart_items` |
178
+ | 8 | 캠페인 | `campaign`, `promotion_detail`, `event_detail` |
179
+ | 9 | 리뷰 | `product_review`, `review_images`, `package_product_review`, `package_review_images` |
180
+ | 10 | 연결 테이블 | `chain_category_detail`, `chain_product_detail`, `chain_variant_detail` 외 5개 |
168
181
 
169
- #### Parameters
182
+ - FK 의존성이 자동 해결됩니다 (예: 주문 선택 시 사용자 자동 포함)
183
+ - `IF NOT EXISTS`로 멱등성이 보장되어 중복 실행해도 안전합니다
184
+ - 이미 존재하는 테이블은 체크박스에 상태가 표시됩니다
170
185
 
171
- - `directory` (string): 라우트 파일들이 위치한 디렉토리 경로
186
+ ---
172
187
 
173
- #### 예제
188
+ ## xplatSystem 싱글턴
174
189
 
175
- ```typescript
176
- import { createRouter } from '@hamjimin/xplat-back';
177
- import * as path from 'path';
190
+ 모든 모듈은 `xplatSystem` 인스턴스를 통해 접근할 수 있습니다.
178
191
 
179
- const router = createRouter(path.join(__dirname, 'restapi'));
180
- app.use('/restapi', router);
192
+ ```typescript
193
+ import { xplatSystem } from '@hamjimin/xplat-back';
194
+
195
+ xplatSystem.auth // 인증/JWT
196
+ xplatSystem.storage // S3 스토리지
197
+ xplatSystem.payment // 결제
198
+ xplatSystem.shipping // 배송
199
+ xplatSystem.orm // 쿼리 빌더
200
+ xplatSystem.middleware // 미들웨어
201
+ xplatSystem.commerce // NestJS 커머스 모듈
181
202
  ```
182
203
 
183
- #### 라우팅 규칙
204
+ ---
205
+
206
+ ## 모듈 상세
184
207
 
185
- 디렉토리 구조가 다음과 같을 때:
208
+ ### Auth - 인증/JWT
186
209
 
210
+ ```typescript
211
+ import { xplatSystem } from '@hamjimin/xplat-back';
212
+
213
+ // 토큰 생성
214
+ const token = xplatSystem.auth.generateToken(
215
+ { id: 'user-1', role: 'admin' },
216
+ { secret: process.env.JWT_SECRET!, expiresIn: '1h' }
217
+ );
218
+
219
+ // Access + Refresh 토큰 쌍 생성
220
+ const tokenPair = xplatSystem.auth.createTokenPair(
221
+ { id: 'user-1' },
222
+ { secret: process.env.JWT_SECRET!, expiresIn: '15m' }, // access
223
+ { secret: process.env.JWT_SECRET!, expiresIn: '7d' } // refresh
224
+ );
225
+
226
+ // 인증 미들웨어
227
+ const authMiddleware = xplatSystem.auth.createMiddleware({
228
+ secret: process.env.JWT_SECRET!,
229
+ cookieName: 'accessToken',
230
+ onSuccess: (req, payload) => { req.user = payload; },
231
+ });
232
+
233
+ app.use('/api/protected', authMiddleware);
187
234
  ```
188
- restapi/
189
- ├── health.ts → GET /restapi/health
190
- ├── user/
191
- │ ├── profile.ts → GET /restapi/user/profile
192
- │ └── settings.ts → GET /restapi/user/settings
193
- └── admin/
194
- └── users.ts → GET /restapi/admin/users
235
+
236
+ 토큰은 **Cookie** 또는 **Authorization: Bearer** 헤더에서 자동 추출됩니다.
237
+
238
+ ### Storage - S3 파일 관리
239
+
240
+ ```typescript
241
+ const storage = xplatSystem.storage;
242
+
243
+ // S3 설정 (환경변수 또는 직접 전달)
244
+ // S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY, AWS_REGION
245
+
246
+ // 업로드
247
+ await storage.upload({
248
+ key: 'uploads/2025/01/image.png',
249
+ body: fileBuffer,
250
+ bucket: 'my-bucket',
251
+ contentType: 'image/png',
252
+ });
253
+
254
+ // Presigned 다운로드 URL 생성
255
+ const url = await storage.getDownloadUrl({
256
+ key: 'uploads/2025/01/image.png',
257
+ bucket: 'my-bucket',
258
+ expiresInSec: 3600,
259
+ });
260
+
261
+ // 삭제
262
+ await storage.delete({ key: 'uploads/2025/01/image.png', bucket: 'my-bucket' });
195
263
  ```
196
264
 
197
- - 파일명이 endpoint로 변환됩니다 (`.ts`, `.js` 확장자 제거)
198
- - 디렉토리는 경로의 일부가 됩니다
199
- - 파일은 Express Router를 export해야 합니다
265
+ 유틸 함수:
266
+ - `buildKey(prefix, fileName, date?)` - 날짜 기반 S3 key 생성 (`prefix/YYYY/MM/DD/fileName`)
267
+ - `extractKey(url)` - S3 URL에서 key 추출
268
+ - `getDatePrefix()` - `YYYY/MM/DD` 형태의 접두사
200
269
 
201
- ## 라우트 파일 작성법
270
+ ### Payment - 결제
202
271
 
203
- 라우트 파일은 Express Router를 export해야 합니다:
272
+ Toss Payments, KakaoPay를 플러그인 방식으로 지원합니다.
204
273
 
205
274
  ```typescript
206
- import express, { Request, Response } from 'express';
275
+ import { TossPaymentProvider, KakaoPayProvider } from '@hamjimin/xplat-back';
276
+
277
+ const payment = xplatSystem.payment;
278
+
279
+ // 결제 프로바이더 등록
280
+ payment.registerProvider(new TossPaymentProvider({
281
+ secretKey: process.env.TOSS_SECRET_KEY!,
282
+ testMode: true,
283
+ }), true); // true = 기본 프로바이더로 설정
284
+
285
+ payment.registerProvider(new KakaoPayProvider({
286
+ adminKey: process.env.KAKAO_ADMIN_KEY!,
287
+ cid: 'TC0ONETIME',
288
+ }));
289
+
290
+ // 결제 요청
291
+ const response = await payment.requestPayment({
292
+ orderId: 'order-123',
293
+ amount: 15000,
294
+ customerName: '홍길동',
295
+ });
207
296
 
208
- const router = express.Router();
297
+ // 결제 승인
298
+ const details = await payment.confirmPayment({
299
+ paymentKey: response.paymentKey,
300
+ orderId: 'order-123',
301
+ amount: 15000,
302
+ });
209
303
 
210
- // GET /restapi/example
211
- router.get('/', (req: Request, res: Response) => {
212
- res.json({ message: 'Hello World' });
304
+ // 결제 취소
305
+ await payment.cancelPayment({
306
+ paymentKey: response.paymentKey,
307
+ cancelReason: '고객 요청',
213
308
  });
309
+ ```
310
+
311
+ ### Shipping - 배송
312
+
313
+ CJ대한통운, 로젠, 편의점 택배를 플러그인 방식으로 지원합니다.
314
+
315
+ ```typescript
316
+ import { CJLogisticsProvider, LogenProvider } from '@hamjimin/xplat-back';
214
317
 
215
- // POST /restapi/example
216
- router.post('/', (req: Request, res: Response) => {
217
- res.json({ message: 'Created' });
318
+ const shipping = xplatSystem.shipping;
319
+
320
+ shipping.registerProvider(new CJLogisticsProvider({
321
+ apiKey: process.env.CJ_API_KEY!,
322
+ customerCode: 'CUSTOMER-001',
323
+ }), true);
324
+
325
+ // 배송비 계산
326
+ const fee = await shipping.calculateFee({
327
+ destinationZip: '06234',
328
+ weight: 2.5,
329
+ });
330
+
331
+ // 운송장 생성
332
+ const label = await shipping.createLabel({
333
+ orderId: 'order-123',
334
+ toName: '홍길동',
335
+ toPhone: '010-1234-5678',
336
+ toAddress: '서울시 강남구 테헤란로 123',
337
+ toZip: '06234',
218
338
  });
219
339
 
220
- export = router;
221
- // 또는
222
- export default router;
340
+ // 배송 조회
341
+ const tracking = await shipping.track(label.trackingNumber);
223
342
  ```
224
343
 
225
- ## 프로젝트 구조 예시
344
+ ### ORM - 쿼리 빌더
345
+
346
+ SQL WHERE / ORDER BY 절을 구조화된 데이터로 생성합니다.
347
+
348
+ ```typescript
349
+ import { xplatSystem } from '@hamjimin/xplat-back';
350
+
351
+ const orm = xplatSystem.orm;
226
352
 
353
+ // WHERE 절 생성
354
+ const whereQuery = orm.createWhereQuery({
355
+ condition: 'AND',
356
+ searchData: [
357
+ { column: 'name', operator: 'LIKE', value: '홍' },
358
+ { column: 'status', operator: 'IN', value: ['active', 'pending'] },
359
+ { column: 'created_at', operator: 'BETWEEN', value: ['2025-01-01', '2025-12-31'] },
360
+ ],
361
+ });
362
+
363
+ // ORDER BY 절 생성
364
+ const sortQuery = orm.createSortQuery([
365
+ { column: 'created_at', operator: 'DESC' },
366
+ { column: 'name', operator: 'ASC' },
367
+ ]);
368
+
369
+ // 기존 쿼리에 적용
370
+ let query = 'SELECT * FROM user WHERE 1=1';
371
+ query = orm.appendWhereClause(query, whereQuery);
372
+ query = orm.appendOrderClause(query, sortQuery);
227
373
  ```
228
- my-backend-project/
229
- ├── src/
230
- │ ├── app.ts # Express 앱 설정
231
- │ ├── server.ts # 서버 시작 (선택적)
232
- │ └── restapi/ # API 라우트 파일들
233
- │ ├── health.ts # GET /restapi/health
234
- │ ├── user/
235
- │ │ └── profile.ts # GET /restapi/user/profile
236
- │ └── admin/
237
- │ └── users.ts # GET /restapi/admin/users
238
- ├── dist/ # TypeScript 컴파일 결과
239
- ├── tsconfig.json
240
- ├── package.json
241
- └── .env
374
+
375
+ 지원 연산자: `=`, `!=`, `LIKE`, `IN`, `NOTIN`, `BETWEEN`, `ISNULL`, `ISNOTNULL`
376
+
377
+ ### Middleware - 미들웨어
378
+
379
+ ```typescript
380
+ const mw = xplatSystem.middleware;
381
+
382
+ // 요청 로깅
383
+ app.use(mw.logger());
384
+
385
+ // 상세 로깅 (body 포함)
386
+ app.use(mw.detailedLogger());
387
+
388
+ // 필드 검증
389
+ app.post('/users', mw.requireFields(['email', 'password']));
390
+
391
+ // 커스텀 검증
392
+ app.post('/users', mw.validator({
393
+ body: {
394
+ email: (v) => typeof v === 'string' && v.includes('@') || 'Invalid email',
395
+ age: (v) => typeof v === 'number' && v > 0 || 'Age must be positive',
396
+ },
397
+ }));
398
+
399
+ // 에러 핸들러 + 404 (마지막에 등록)
400
+ app.use(mw.notFound());
401
+ app.use(mw.errorHandler());
402
+ ```
403
+
404
+ ---
405
+
406
+ ## NestJS 커머스 모듈
407
+
408
+ Store/Admin API 분리 구조를 제공합니다.
409
+
410
+ ```typescript
411
+ import { Module } from '@nestjs/common';
412
+ import { CommerceModule } from '@hamjimin/xplat-back';
413
+
414
+ @Module({
415
+ imports: [CommerceModule],
416
+ })
417
+ export class AppModule {}
418
+ ```
419
+
420
+ ```
421
+ Store API: /store/v1/*
422
+ Admin API: /admin/v1/*
242
423
  ```
243
424
 
425
+ ```typescript
426
+ const { storePrefix, adminPrefix } = xplatSystem.commerce.getVersioning();
427
+ // storePrefix: /store/v1
428
+ // adminPrefix: /admin/v1
429
+ ```
430
+
431
+ ---
432
+
244
433
  ## 환경변수
245
434
 
246
- `.env` 파일에서 설정할 있는 환경변수:
435
+ `.env` 파일에서 설정 가능한 환경변수:
247
436
 
248
437
  ```env
438
+ # 앱
249
439
  NODE_ENV=development
250
440
  PORT=4000
251
- CORS_ALLOW_ORIGINS=http://localhost:3000,http://localhost:5173
441
+ CORS_ALLOW_ORIGINS=http://localhost:3000
442
+
443
+ # 데이터베이스
444
+ DB_HOST=localhost
445
+ DB_PORT=3306
446
+ DB_USER=root
447
+ DB_PASSWORD=
448
+ DB_DATABASE=my_database
449
+
450
+ # AWS S3
451
+ AWS_REGION=ap-northeast-2
452
+ S3_BUCKET=my-bucket
453
+ S3_ACCESS_KEY=
454
+ S3_SECRET_KEY=
455
+
456
+ # JWT
457
+ JWT_SECRET=your-secret-key
252
458
  ```
253
459
 
254
460
  ## TypeScript 설정
@@ -267,23 +473,46 @@ CORS_ALLOW_ORIGINS=http://localhost:3000,http://localhost:5173
267
473
  "moduleResolution": "node",
268
474
  "sourceMap": true,
269
475
  "baseUrl": "./src",
270
- "paths": {
271
- "@/*": ["*"]
272
- }
476
+ "paths": { "@/*": ["*"] }
273
477
  },
274
478
  "include": ["src/**/*"],
275
479
  "exclude": ["node_modules", "dist"]
276
480
  }
277
481
  ```
278
482
 
279
- ## 라이센스
280
-
281
- ISC
282
-
283
- ## 기여
483
+ ## Export 목록
284
484
 
285
- 버그 리포트 및 기능 제안은 이슈로 등록해주세요.
485
+ ```typescript
486
+ // 싱글턴
487
+ export { xplatSystem, XplatSystem } from '@hamjimin/xplat-back';
488
+
489
+ // 앱/라우터
490
+ export { createApp, createRouter } from '@hamjimin/xplat-back';
491
+
492
+ // 모듈
493
+ export {
494
+ AppModule, RouterModule, AuthModule,
495
+ UtilsModule, MiddlewareModule, ConstantsModule,
496
+ StorageModule, ORMModule, PaymentModule, ShippingModule,
497
+ } from '@hamjimin/xplat-back';
498
+
499
+ // 결제 프로바이더
500
+ export { TossPaymentProvider, KakaoPayProvider } from '@hamjimin/xplat-back';
501
+
502
+ // 배송 프로바이더
503
+ export { CJLogisticsProvider, LogenProvider, CvsProvider } from '@hamjimin/xplat-back';
504
+
505
+ // 타입
506
+ export type {
507
+ AppConfig, ExtendedRequest, ExtendedResponse, AuthenticatedRequest,
508
+ TokenPayload, TokenOptions, TokenPair,
509
+ DetailSearch, SortQueryData, SearchDataItem, ColumnMapper,
510
+ S3Config,
511
+ PaymentRequestParams, PaymentResponse, PaymentConfirmParams, PaymentDetails,
512
+ ShippingFeeParams, ShippingFee, CreateLabelParams, ShippingLabel, TrackingInfo,
513
+ } from '@hamjimin/xplat-back';
514
+ ```
286
515
 
287
- ## 관련 프로젝트
516
+ ## 라이센스
288
517
 
289
- 이 패키지는 [zium-backend](https://github.com/your-org/zium-backend) 프로젝트의 구조를 기반으로 만들어졌습니다.
518
+ ISC