@axyl-tcb/middleware
v1.3.0
Published
고객사에서 TCB 용 함수를 개발할 때 사용할 수 있는 JavaScript 래퍼
Readme
axyl-tcb-middleware
Axyl TCB Cloud Function 템플릿에서 공통으로 사용하는 Gateway 주입 헤더 기반 컨텍스트 미들웨어 패키지입니다.
이 패키지는 Cloud Function 진입점에서 Gateway가 주입한 X-Hive-* 헤더를 읽고, 필요한 컨텍스트를 생성해 baseHandler 에 전달하며, 최종 응답을 Axyl 표준 포맷으로 강제합니다.
목적
axyl-tcb-middleware 는 다음 책임을 가집니다.
- Gateway가 주입한
X-Hive-Player-Id,X-Hive-Aud헤더 추출 X-Hive-Aud파싱 및 컨텍스트 주입- 필요 시
gameIndex컨텍스트 주입 - 공통 로깅 처리
- 템플릿에서는
baseHandler만 구현하면 되도록 handler factory 제공 - 성공/실패 응답을 Axyl 표준 포맷으로 강제
보안 모델
이 패키지는 제품(Cloud Function) 측 미들웨어를 위한 것입니다.
현재 전제는 다음과 같습니다.
- Authorization 헤더는 Gateway 단계에서 제거됨
- JWT 검증은 Gateway 책임
- 클라이언트가 보낸
X-Hive-*위조 헤더는 Gateway에서 제거 또는 차단됨 - 제품은 Gateway가 주입한
X-Hive-*헤더만 신뢰함
따라서 이 패키지는 JWT를 직접 검증하지 않고, Gateway가 주입한 헤더를 읽는 역할에 집중합니다.
타입 설계 원칙
이 패키지는 다음 3가지를 분리합니다.
- ReqDTO: 사용자가 입력으로 받는 비즈니스 요청 값
- ResDTO: 사용자가 반환하는 비즈니스 응답 값
- Context: middleware가 주입하는 런타임 값
즉 playerId, aud 같은 값은 ReqDTO/ResDTO가 아니라 Context의 필수 필드입니다.
현재 사용하는 헤더
현재 제품에서 사용하는 헤더는 아래 3개입니다.
| Header | 설명 | 사용 여부 |
|---|---|---|
| X-Hive-Player-Id | PlayerId | 사용 |
| X-Hive-Aud | {appIndex}-{gameIndex}-{companyIndex} | 사용 |
| traceparent | W3C Trace Context — trace-id 를 로그 상관관계에 사용 (없으면 자동 생성) | 사용 |
현재 구현은 X-Hive-Player-Id, X-Hive-Aud, traceparent 를 사용합니다.
traceparent는 observability(추적) 전용입니다. 보안 판단이나 멱등성 키로 사용하지 않습니다.
aud 파싱 규칙
X-Hive-Aud 값은 아래 형식을 따라야 합니다.
{appIndex}-{gameIndex}-{companyIndex}appIndex, gameIndex, companyIndex 는 모두 정수입니다.
예:
2789-539-1검증 성공 시 아래와 같이 파싱된 결과가 context.aud 에 주입됩니다(세 값 모두 number).
{
raw: '2789-539-1',
appIndex: 2789,
gameIndex: 539,
companyIndex: 1
}주요 기능
withTrace- 이벤트 헤더의
traceparent에서 trace-id(32 hex)를 추출해context.traceId에 주입 traceparent가 없거나 형식이 올바르지 않으면 새 trace-id 를 자동 생성 (로컬 실행·직접 호출 대비)- 성공/실패 응답의
metadata.traceId에 항상 포함됨 - 로그 상관관계·분산 추적 전용 — 보안 판단·멱등성 키로 사용하지 않음
- 이벤트 헤더의
withHiveHeadersX-Hive-Player-Id,X-Hive-Aud헤더 추출- 필수 헤더 검증
playerId,aud,injectedHeaders주입AxylContext를AxylAuthorizedContext로 승격
withGameContext- 이벤트에서
gameIndex추출 및 컨텍스트 주입
- 이벤트에서
withLogger- 공통 요청/응답 로깅
createAxylHandler- 미들웨어 조합을 내부에 숨기고 최종 handler 생성
- 템플릿에서는
baseHandler만 구현하면 되도록 지원 - 성공/실패 응답을 Axyl 표준 포맷으로 생성
응답 포맷
createAxylHandler 는 최종 응답을 아래 구조로 강제합니다.
성공 응답
{
"success": true,
"code": "OK",
"metadata": {
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
"elapsedMs": 3
},
"data": {}
}실패 응답
{
"success": false,
"code": "HIVE_PLAYER_ID_REQUIRED",
"metadata": {
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
"elapsedMs": 1
},
"error": {
"message": "X-Hive-Player-Id header is required"
}
}즉 baseHandler 는 최종 응답 전체를 만들지 않고, 비즈니스 data 만 반환하면 됩니다.
설치
공개 npm 패키지이므로 별도 레지스트리 설정이나 인증 없이 바로 설치할 수 있습니다.
npm install @axyl-tcb/middleware코어(헤더/컨텍스트 처리)는 의존성이 없습니다.
DB / Storage / Document DB 헬퍼 (subpath)
mysql2·TCB Cloud Storage·Document DB 클라이언트를 subpath 로 제공합니다. 라이브러리로 관리되므로 수정·보안 패치가 npm update 로 전파됩니다.
import { pool, transaction } from '@axyl-tcb/middleware/db'; // mysql2
import { uploadFile, getTempURL } from '@axyl-tcb/middleware/storage'; // Cloud Storage
import { db, command, collection } from '@axyl-tcb/middleware/docdb'; // Document DB이 subpath 들은 mysql2 / @cloudbase/node-sdk 를 직접 require 하지만, 미들웨어가 자동 설치하지 않습니다(헤더만 쓰는 사용자에게 불필요한 의존성·취약점을 부과하지 않기 위함). 사용하는 subpath 의 패키지를 직접 설치하세요.
npm install mysql2 # /db 사용 시
npm install @cloudbase/node-sdk # /storage, /docdb 사용 시설치하지 않고 subpath 를 import 하면 런타임에 모듈을 찾지 못합니다. (Axyl 템플릿으로 생성한 프로젝트는 필요한 패키지를 이미 선언합니다.)
| subpath | 필요 peer | 환경변수 |
|---|---|---|
| /db | mysql2 | DB_HOST DB_PORT DB_USER DB_PASSWORD DB_NAME |
| /storage | @cloudbase/node-sdk | TCB_ENV_ID(미설정 시 현재 함수 환경) |
| /docdb | @cloudbase/node-sdk | TCB_ENV_ID · TCB_DOCDB_INSTANCE · TCB_DOCDB_DATABASE |
헤더/컨텍스트만 쓰는 사용자는 이 패키지들을 설치하지 않으므로, 코어는 가볍게 유지되고 관련 보안 advisory 도 부과되지 않습니다.
개발
의존성 설치:
npm install빌드:
npm run build테스트:
npm test배포
npmjs.com 에 공개 배포합니다(@axyl-tcb 스코프, access public). 사용자 레벨 ~/.npmrc 에 npm Access Token 이 설정되어 있어야 합니다.
npm version patch # 또는 minor, major
npm test
npm run build
npm publish이 패키지는 템플릿(
@axyl-tcb/create-template)의 의존성이므로 템플릿보다 먼저 배포해야 합니다. 버전 규칙·인증 설정·배포 순서 등 전체 릴리스 절차는 axyl-tcb-template 저장소의 PUBLISHING.md 를 참고하세요.
프로젝트 구조
axyl-tcb-middleware/
├─ src/
│ ├─ constants/
│ │ └─ errorCodes.ts
│ ├─ factory/
│ │ └─ createAxylHandler.ts
│ ├─ middlewares/
│ │ ├─ withGameContext.ts
│ │ ├─ withHiveHeaders.ts
│ │ ├─ withLogger.ts
│ │ └─ withTrace.ts
│ ├─ utils/
│ │ ├─ aud.ts
│ │ ├─ hiveHeaders.ts
│ │ └─ traceparent.ts
│ ├─ errors.ts
│ ├─ index.ts
│ └─ types.ts
└─ test/사용 예시
템플릿 프로젝트에서는 baseHandler 만 구현하고, createAxylHandler 로 최종 main 을 생성하면 됩니다.
baseHandler 는 Gateway 헤더를 직접 다루지 않습니다.X-Hive-Player-Id, X-Hive-Aud 는 middleware 가 읽고 AxylAuthorizedContext 로 전달합니다.
따라서 템플릿 사용자는 이벤트 타입에 headers 를 직접 정의할 필요 없이, 비즈니스 로직에 필요한 필드만 정의하면 됩니다.
import {
createAxylHandler,
type AxylBaseHandler
} from '@axyl-tcb/middleware';
interface HelloReqDto {
gameIndex?: string;
message?: string;
}
interface HelloResDto {
echo: string;
}
const baseHandler: AxylBaseHandler<HelloReqDto, HelloResDto> = async (
event,
context
) => {
context.logger?.info('business logic', {
playerId: context.playerId,
aud: context.aud.raw,
gameIndex: context.gameIndex
});
return {
echo: event.message ?? 'hello'
};
};
export const main = createAxylHandler(baseHandler, {
gameContext: {
required: false,
extractor: (event) => event.gameIndex
}
});실제 요청 payload 예시
Gateway 또는 테스트 호출에서는 실제로 headers 가 포함될 수 있습니다.
{
"headers": {
"X-Hive-Player-Id": "player-123",
"X-Hive-Aud": "2789-539-1"
},
"gameIndex": 539,
"message": "hello axyl"
}createAxylHandler 기본 동작
createAxylHandler 는 내부적으로 아래 순서로 처리합니다.
traceId결정 (traceparent헤더의 trace-id 추출, 없으면 자동 생성)withLoggerwithHiveHeaderswithGameContext
기본 정책은 다음과 같습니다.
traceparent헤더의 trace-id 를 사용, 없거나 형식 오류면 새 trace-id 자동 생성X-Hive-Player-Id,X-Hive-Aud는 기본적으로 필수gameIndex는 기본적으로 필수 아님- 필요 시
gameContext.required = true로 강제 가능 - 성공 응답의
code는 기본적으로OK - 필요 시
successCode옵션으로 변경 가능
예:
createAxylHandler(baseHandler, {
hiveHeaders: {
required: false
},
gameContext: {
required: false,
extractor: (event) => event.gameIndex
},
successCode: 'CUSTOM_OK'
});공개 API
현재 외부로 공개하는 주요 API는 다음과 같습니다.
createAxylHandlerwithHiveHeaderswithGameContextwithLoggerwithTrace
주요 타입:
AxylBaseHandlerAxylContextAxylAuthorizedContextAxylHttpEventAxylHiveHeadersAxylAudPartsAxylResponseMetadataAxylSuccessResponseAxylErrorResponseAxylResponseCreateAxylHandlerOptions
테스트 범위
현재 테스트는 다음 범위를 포함합니다.
parseAxylAudgetHiveHeaderswithHiveHeaderswithGameContextwithLoggerwithTracecreateAxylHandler
참고
- 이 패키지는 Cloud Function 비즈니스 로직이 아니라 헤더 추출/주입/공통 처리에 집중합니다.
- Authorization 헤더와 JWT 검증은 제품이 아니라 Gateway 단계에서 처리된다는 전제를 둡니다.
- 현재는
X-Hive-Player-Id,X-Hive-Aud만 사용합니다. aud의 비즈니스 검증(예: 게임 정보 DB 조회 기반 검증)은 제품 책임입니다.
