## 개요 - NodeJS 서버로 이루어진 MSA 환경에서 계층적으로 생성되는 OpenAPI 문서들을 통합하고 이를 사용자에게 제공하기 위한 모듈
npm install node-msa-openapi-tatum
// user.controller.ts
@Controller('user')
export class UserController {
@ApiSecurity('securityCategory',["requirement"])
@UseGuards(MyGuard)
@Get(':id')
getUser(@Param('id') userId: string) {
return this.userService(userId);
}
}
`
- 사용 가드의 바인딩과 해당 가드의 정보가 각각 관리되는 구조 (ApiSecurity 데코레이터에 리터럴 형식으로 입력)
- 이를 위해 NestJS 가드 클래스에 데코레이터를 하나 추가하면, 이후 해당 가드를 컨트롤러에 바인딩할 때 자동으로 가드의 정보가 OpenApi 문서에 추가
$3
- 설정 파일을 읽어온 뒤 검증 후 반환사용
$3
`
npm i node-msa-openapi-tatum
`
---
$3
- [config].js
`
module.exports = {
outDir: string; // openAPI 문서를 내보낼 상대 경로 입력 ex "./doc"
microservices: {
[microserviceName: string]: { // 서비스들의 이름 ex "gateway", "user"
appModuleName: string; // NestJS 인스턴스 생성을 위한 루트 모듈 클래스명 ex "AppModule"
appModulePath: string; // 프로젝트 루트 경로를 기준으로 해당 서비스의 tsc 빌드된 루트 모듈의 상대 경로 ex "./dist/microservice/user/src/app.module"
globalPrefix: string; // 해당 서비스에 설정된 전역 Api prefix ex. "api"
isGateway: boolean; // 해당 서비스의 게이트웨이 여부
openApi: {
title: string; // openAPI 문서에 명시할 title
description: string; // openAPI 문서에 명시할 description
version: string; // openAPI 문서에 명시할 version
tags: TagObject[]; // openAPI 문서에 명시할 tags
};
};
};
};
`- [config].json
`
{
"outDir": string; // openAPI 문서를 내보낼 상대 경로 입력 ex "./doc"
"microservices": {
[microserviceName: string]: { // 서비스들의 이름 ex "gateway", "user"
"appModuleName": string; // NestJS 인스턴스 생성을 위한 루트 모듈 클래스명 ex "AppModule"
"appModulePath": string; // 프로젝트 루트 경로를 기준으로 해당 서비스의 tsc 빌드된 루트 모듈의 상대 경로 ex "./dist/microservice/user/src/app.module"
"globalPrefix": string; // 해당 서비스에 설정된 전역 Api prefix ex. "api"
"isGateway": boolean; // 해당 서비스의 게이트웨이 여부
"openApi": {
"title": string; // openAPI 문서에 명시할 title
"description": string; // openAPI 문서에 명시할 description
"version": string; // openAPI 문서에 명시할 version
"tags": TagObject[]; // openAPI 문서에 명시할 tags
};
};
};
};
`
---
$3
- user.guard.ts
`
import { CanActivate, ExecutionContext } from '@nestjs/common';
import { ApiDecoratorForGuard } from 'node-msa-openapi-tatum';
import { Observable } from 'rxjs'; @ApiDecoratorForGuard('security 종류(ex.bearer)', ['이게 필요해요.'])
export class TestGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise | Observable {
return true;
}
}
@ApiDecoratorForGuard('test', ['accessToken', 'refreshToken'])
export class TestGuard2 implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise | Observable {
return true;
}
}
`
- user.controller.ts
`
import { Body, Controller, Get, Param, Post } from '@nestjs/common';
import axios from 'axios';
import { UseGuardsForOpenApi } from 'node-msa-openapi-tatum';
import { TestGuard, TestGuard2 } from 'src/app.guard';
import { CreateUserDto } from './dto/createUserDto'; @Controller('user')
export class UserController {
// @ApiSecurity('security 종류(ex.bearer)', ['이게 필요해요.'])
// @ApiSecurity('test', ['testtest'])
// @UseGuards(TestGuard,TestGuard2)
// 원래는 위와 같이 비효율적인 구조로 데코레이터를 추가해야 했으나 해당 패키지에서는 아래 하나의 데코레이터로 위 로직 추가 가능
@UseGuardsForOpenApi(TestGuard, TestGuard2)
@Get(':id')
async getUserInfo(@Param('id') userId: string) {
const result = await axios
.get<{ id: string; email: string }>(
http://user_service:3001/user/${userId},
)
.then((res) => res.data)
.catch(() => ({ id: '실패', email: '실패' }));
return result;
}
}
`
---
$3
`
// tsc 실행 후 서버 로직 진입점이 dist/src/main.js에 존재할 경우
npx tatum-openapi scan .[config].js
`$3
`
// tsc 실행 후 서버 로직 진입점이 dist/src/main.js에 존재할 경우
npx tatum-openapi integrate .[config].js
``