npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hamjimin/xplat-back

v0.7.1

Published

Express + TypeScript 백엔드 스캐폴딩 도구 (zium-backend 기반)

Downloads

249

Readme

@hamjimin/xplat-back

Express + TypeScript 백엔드 프레임워크 & CLI 스캐폴딩 도구

커머스 백엔드에 필요한 인증, 스토리지, 결제, 배송, 쿼리 빌더 등의 모듈을 xplatSystem 싱글턴으로 통합 제공하며, CLI를 통해 프로젝트 초기화와 MySQL DDL 자동 설치까지 지원합니다.


설치

npm install @hamjimin/xplat-back
# 또는
yarn add @hamjimin/xplat-back

빠른 시작

1. 프로젝트 스캐폴딩

npx @hamjimin/xplat-back my-project

자동 생성되는 파일:

my-project/
├── src/
│   ├── app.ts                         # Express 앱 진입점
│   ├── server.ts                      # 서버 실행 파일
│   ├── restapi/
│   │   └── health.ts                  # 예시 API 라우트
│   ├── const/
│   │   ├── api_code.ts                # API 응답 코드 상수
│   │   └── constants.ts               # 공통 상수
│   └── util/
│       └── dbconfig/
│           └── dbConnections.ts       # DB 연결 설정 (TypeORM)
├── tsconfig.json
├── package.json
└── .env

2. Express 앱 생성

import { createApp } from '@hamjimin/xplat-back';
import * as path from 'path';

const app = createApp({
  cors: {
    origin: ['http://localhost:3000'],
    credentials: true,
  },
  router: {
    directory: path.join(__dirname, 'restapi'),
    basePath: '/restapi',
  },
  trustProxy: true,
});

app.listen(4000, () => {
  console.log('Server running on port 4000');
});

createApp 옵션:

| 옵션 | 타입 | 기본값 | 설명 | |------|------|--------|------| | cors.origin | string[] | ['*'] | CORS 허용 origin | | cors.credentials | boolean | true | 자격 증명 허용 | | json.limit | string | '1mb' | JSON body 크기 제한 | | router.directory | string | 'src/restapi' | 라우트 파일 디렉토리 | | router.basePath | string | '/restapi' | 라우터 base path | | trustProxy | boolean | true | 프록시 신뢰 | | middleware | Function[] | [] | 커스텀 미들웨어 |

3. 파일 기반 라우팅

디렉토리 구조가 API endpoint에 자동 매핑됩니다.

src/restapi/
├── health.ts          → GET /restapi/health
├── users.ts           → /restapi/users
└── users/
    └── profile.ts     → /restapi/users/profile
import { createRouter } from '@hamjimin/xplat-back';

const router = createRouter(path.join(__dirname, 'restapi'));
app.use('/restapi', router);

CLI

npx @hamjimin/xplat-back [project-name] [options]
npx @hamjimin/xplat-back db:setup

프로젝트 생성 옵션

| 옵션 | 단축 | 설명 | 기본값 | |------|------|------|--------| | --port <port> | -p | 서버 포트 | 4000 | | --cors <origins> | -c | CORS origins (쉼표 구분) | http://localhost:3000 | | --router-dir <dir> | -r | 라우터 디렉토리 | src/restapi | | --router-path <path> | | 라우터 base path | /restapi |

npx @hamjimin/xplat-back my-project --port 3000 --cors "http://localhost:3000,http://localhost:5173"

db:setup - MySQL DDL 자동 설치

인터랙티브 UI로 MySQL 접속 정보를 입력하고, 필요한 테이블을 선택하여 바로 생성합니다.

npx @hamjimin/xplat-back db:setup

실행 흐름:

🗄️  xplat-back 데이터베이스 설정

? DB Host: localhost
? DB User: root
? DB Password: ****
? DB Name: my_shop
? DB Port: 3306

✅ MySQL 연결 성공!

? 설치할 DDL 모듈을 선택하세요 (스페이스바로 선택):
 ◉ 사용자 (User / Employee / Partner)
 ◉ 상품 (Category / Product / Variants / Brand / Side_Product)
 ◯ 패키지 (Product_Package / Detail / Variant)
 ◉ 주문 (Orders / Order_Items / Order_Manage)
 ...

📎 의존성으로 자동 추가된 모듈:
  → 사용자 (01_user.sql)

📋 실행 대상 DDL (3개 파일):
  📦 01_user.sql - 사용자
  📦 02_product.sql - 상품
  📦 04_order.sql - 주문

? 위 3개 DDL 파일을 실행하시겠습니까? Yes

  ✅ 01_user.sql → user, employee, partner
  ✅ 02_product.sql → category, product, variants, brand, side_product
  ✅ 04_order.sql → orders, order_items, order_manage, order_manage_comment

🎉 데이터베이스 설정이 완료되었습니다!

제공되는 DDL 모듈 (10개):

| # | 모듈 | 테이블 | |---|------|--------| | 1 | 사용자 | user, employee, partner | | 2 | 상품 | category, product, variants, brand, side_product | | 3 | 패키지 | product_package, product_package_detail, product_package_variant | | 4 | 주문 | orders, order_items, order_manage, order_manage_comment | | 5 | 결제 | payment, calcurate | | 6 | 배송 | delivery, reservation | | 7 | 장바구니 | cart, cart_items | | 8 | 캠페인 | campaign, promotion_detail, event_detail | | 9 | 리뷰 | product_review, review_images, package_product_review, package_review_images | | 10 | 연결 테이블 | chain_category_detail, chain_product_detail, chain_variant_detail 외 5개 |

  • FK 의존성이 자동 해결됩니다 (예: 주문 선택 시 사용자 자동 포함)
  • IF NOT EXISTS로 멱등성이 보장되어 중복 실행해도 안전합니다
  • 이미 존재하는 테이블은 체크박스에 상태가 표시됩니다

xplatSystem 싱글턴

모든 모듈은 xplatSystem 인스턴스를 통해 접근할 수 있습니다.

import { xplatSystem } from '@hamjimin/xplat-back';

xplatSystem.auth       // 인증/JWT
xplatSystem.storage    // S3 스토리지
xplatSystem.payment    // 결제
xplatSystem.shipping   // 배송
xplatSystem.orm        // 쿼리 빌더
xplatSystem.middleware // 미들웨어
xplatSystem.commerce   // NestJS 커머스 모듈

모듈 상세

Auth - 인증/JWT

import { xplatSystem } from '@hamjimin/xplat-back';

// 토큰 생성
const token = xplatSystem.auth.generateToken(
  { id: 'user-1', role: 'admin' },
  { secret: process.env.JWT_SECRET!, expiresIn: '1h' }
);

// Access + Refresh 토큰 쌍 생성
const tokenPair = xplatSystem.auth.createTokenPair(
  { id: 'user-1' },
  { secret: process.env.JWT_SECRET!, expiresIn: '15m' },   // access
  { secret: process.env.JWT_SECRET!, expiresIn: '7d' }     // refresh
);

// 인증 미들웨어
const authMiddleware = xplatSystem.auth.createMiddleware({
  secret: process.env.JWT_SECRET!,
  cookieName: 'accessToken',
  onSuccess: (req, payload) => { req.user = payload; },
});

app.use('/api/protected', authMiddleware);

토큰은 Cookie 또는 Authorization: Bearer 헤더에서 자동 추출됩니다.

Storage - S3 파일 관리

const storage = xplatSystem.storage;

// S3 설정 (환경변수 또는 직접 전달)
// S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY, AWS_REGION

// 업로드
await storage.upload({
  key: 'uploads/2025/01/image.png',
  body: fileBuffer,
  bucket: 'my-bucket',
  contentType: 'image/png',
});

// Presigned 다운로드 URL 생성
const url = await storage.getDownloadUrl({
  key: 'uploads/2025/01/image.png',
  bucket: 'my-bucket',
  expiresInSec: 3600,
});

// 삭제
await storage.delete({ key: 'uploads/2025/01/image.png', bucket: 'my-bucket' });

유틸 함수:

  • buildKey(prefix, fileName, date?) - 날짜 기반 S3 key 생성 (prefix/YYYY/MM/DD/fileName)
  • extractKey(url) - S3 URL에서 key 추출
  • getDatePrefix() - YYYY/MM/DD 형태의 접두사

Payment - 결제

Toss Payments, KakaoPay를 플러그인 방식으로 지원합니다.

import { TossPaymentProvider, KakaoPayProvider } from '@hamjimin/xplat-back';

const payment = xplatSystem.payment;

// 결제 프로바이더 등록
payment.registerProvider(new TossPaymentProvider({
  secretKey: process.env.TOSS_SECRET_KEY!,
  testMode: true,
}), true);   // true = 기본 프로바이더로 설정

payment.registerProvider(new KakaoPayProvider({
  adminKey: process.env.KAKAO_ADMIN_KEY!,
  cid: 'TC0ONETIME',
}));

// 결제 요청
const response = await payment.requestPayment({
  orderId: 'order-123',
  amount: 15000,
  customerName: '홍길동',
});

// 결제 승인
const details = await payment.confirmPayment({
  paymentKey: response.paymentKey,
  orderId: 'order-123',
  amount: 15000,
});

// 결제 취소
await payment.cancelPayment({
  paymentKey: response.paymentKey,
  cancelReason: '고객 요청',
});

Shipping - 배송

CJ대한통운, 로젠, 편의점 택배를 플러그인 방식으로 지원합니다.

import { CJLogisticsProvider, LogenProvider } from '@hamjimin/xplat-back';

const shipping = xplatSystem.shipping;

shipping.registerProvider(new CJLogisticsProvider({
  apiKey: process.env.CJ_API_KEY!,
  customerCode: 'CUSTOMER-001',
}), true);

// 배송비 계산
const fee = await shipping.calculateFee({
  destinationZip: '06234',
  weight: 2.5,
});

// 운송장 생성
const label = await shipping.createLabel({
  orderId: 'order-123',
  toName: '홍길동',
  toPhone: '010-1234-5678',
  toAddress: '서울시 강남구 테헤란로 123',
  toZip: '06234',
});

// 배송 조회
const tracking = await shipping.track(label.trackingNumber);

ORM - 쿼리 빌더

SQL WHERE / ORDER BY 절을 구조화된 데이터로 생성합니다.

import { xplatSystem } from '@hamjimin/xplat-back';

const orm = xplatSystem.orm;

// WHERE 절 생성
const whereQuery = orm.createWhereQuery({
  condition: 'AND',
  searchData: [
    { column: 'name', operator: 'LIKE', value: '홍' },
    { column: 'status', operator: 'IN', value: ['active', 'pending'] },
    { column: 'created_at', operator: 'BETWEEN', value: ['2025-01-01', '2025-12-31'] },
  ],
});

// ORDER BY 절 생성
const sortQuery = orm.createSortQuery([
  { column: 'created_at', operator: 'DESC' },
  { column: 'name', operator: 'ASC' },
]);

// 기존 쿼리에 적용
let query = 'SELECT * FROM user WHERE 1=1';
query = orm.appendWhereClause(query, whereQuery);
query = orm.appendOrderClause(query, sortQuery);

지원 연산자: =, !=, LIKE, IN, NOTIN, BETWEEN, ISNULL, ISNOTNULL

Middleware - 미들웨어

const mw = xplatSystem.middleware;

// 요청 로깅
app.use(mw.logger());

// 상세 로깅 (body 포함)
app.use(mw.detailedLogger());

// 필드 검증
app.post('/users', mw.requireFields(['email', 'password']));

// 커스텀 검증
app.post('/users', mw.validator({
  body: {
    email: (v) => typeof v === 'string' && v.includes('@') || 'Invalid email',
    age: (v) => typeof v === 'number' && v > 0 || 'Age must be positive',
  },
}));

// 에러 핸들러 + 404 (마지막에 등록)
app.use(mw.notFound());
app.use(mw.errorHandler());

NestJS 커머스 모듈

Store/Admin API 분리 구조를 제공합니다.

import { Module } from '@nestjs/common';
import { CommerceModule } from '@hamjimin/xplat-back';

@Module({
  imports: [CommerceModule],
})
export class AppModule {}
Store API: /store/v1/*
Admin API: /admin/v1/*
const { storePrefix, adminPrefix } = xplatSystem.commerce.getVersioning();
// storePrefix: /store/v1
// adminPrefix: /admin/v1

환경변수

.env 파일에서 설정 가능한 환경변수:

# 앱
NODE_ENV=development
PORT=4000
CORS_ALLOW_ORIGINS=http://localhost:3000

# 데이터베이스
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASSWORD=
DB_DATABASE=my_database

# AWS S3
AWS_REGION=ap-northeast-2
S3_BUCKET=my-bucket
S3_ACCESS_KEY=
S3_SECRET_KEY=

# JWT
JWT_SECRET=your-secret-key

TypeScript 설정

권장 tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2021",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "baseUrl": "./src",
    "paths": { "@/*": ["*"] }
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Export 목록

// 싱글턴
export { xplatSystem, XplatSystem } from '@hamjimin/xplat-back';

// 앱/라우터
export { createApp, createRouter } from '@hamjimin/xplat-back';

// 모듈
export {
  AppModule, RouterModule, AuthModule,
  UtilsModule, MiddlewareModule, ConstantsModule,
  StorageModule, ORMModule, PaymentModule, ShippingModule,
} from '@hamjimin/xplat-back';

// 결제 프로바이더
export { TossPaymentProvider, KakaoPayProvider } from '@hamjimin/xplat-back';

// 배송 프로바이더
export { CJLogisticsProvider, LogenProvider, CvsProvider } from '@hamjimin/xplat-back';

// 타입
export type {
  AppConfig, ExtendedRequest, ExtendedResponse, AuthenticatedRequest,
  TokenPayload, TokenOptions, TokenPair,
  DetailSearch, SortQueryData, SearchDataItem, ColumnMapper,
  S3Config,
  PaymentRequestParams, PaymentResponse, PaymentConfirmParams, PaymentDetails,
  ShippingFeeParams, ShippingFee, CreateLabelParams, ShippingLabel, TrackingInfo,
} from '@hamjimin/xplat-back';

라이센스

ISC