-
[nest.js] swagger 적용하기TIL 2024. 5. 29. 16:04
왜 swagger를 쓰는가?)
swagger 를 사용하면 api명세서를 코드내에서 자동으로 쓸 수 있게해준다
api가 많아질경우 api명세서를 쓰는 시간을 훨씬 더 단축시킬 수 있고,
백엔드 작업을 하다보면 놓친부분이나, api명세서 변경이 꽤 많이 일어난다.
그럴때마다 코드와 api명세서를 둘다 수정하는 것은 시간도 오래걸리고, 만약 코드만 수정하고, api명세서 수정하는 것을 깜빡하면
프론트엔드쪽에서는 잘못된 명세서를 많은 시간을 낭비하게된다.
swagger 설치하기
npm install --save @nestjs/swagger
main.ts에 swagger 적용하기)
main.tsimport { NestFactory } from '@nestjs/core'; import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); const config = new DocumentBuilder() .setTitle('nest-practice-youtube') // 명세서 제목 .setDescription('nest practice description') // 명세서 설명 .setVersion('1.0') // 명세서 버전 .addTag('cats') // 명세서 태그 .build(); // 명세서 생성(필수) const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('api', app, document); await app.listen(3000); } bootstrap();
ㄴ 별도의 파일에 swagger config를 작성해준뒤 main.ts에서 불러올 수도있다.
api에 swagger 적용하기)
@ApiTags('channel') @Controller('channel') export class ChannelController { constructor(private channelService: ChannelService) {} //회원가입 @Post() @ApiOperation({ summary: '회원가입' }) @ApiCreatedResponse({ description: 'created id' }) @ApiConflictResponse({ description: 'id duplicate' }) async signUp( @Body(ValidationPipe) signUpDto: SignUpDto, ): Promise<ChannelEntity> { return await this.channelService.signUp(signUpDto); } //채널상세보기 @Get(':channelIdx') @ApiOperation({ summary: 'get channel in detail' }) @ApiParam({ name: 'channelIdx' }) @ApiBadRequestResponse({ description: 'no channelIdx' }) @ApiNotFoundResponse({ description: 'not found channel' }) @ApiOkResponse({ description: 'ok' }) @UseGuards(AuthGuard) async getChannelInfo( @GetUser() loginUser: LoginUser, @Param('channelIdx', ParseIntPipe) channelIdx: number, ): Promise<{ channel: ChannelEntity; subscribe: boolean; }> { const subscribeState = await this.channelService.getSubscrbeState( loginUser.idx, channelIdx, ); const channel = await this.channelService.getChannelByIdx(channelIdx); return { channel, subscribe: subscribeState, }; }
@ApiTags
ㄴ api들을 태그별로 분류한다
ㄴ컨트롤러에 쓸 수도 있고, 개별api에 쓸 수도 있다
@ApiOperation
ㄴapi 설명
@ApiResponse
ㄴ 각각의 상태코드 기본값 예외처리로도 쓸 수 있음 (ex) @ApiCreatedResponse, @ApiConflictResponse ... )
ㄴ 상태코드, 설명등을 추가할수 있음
@ApiBody
@ApiParam
@ApiQuery
ㄴ 필요한 body, param, query 지정
ㄴ변수명, 타입지정(dto, string)
// SignupDto export class SignUpDto { @IsString() @Length(1, 20) @ApiProperty({ example: 'testid', description: '1-20자', }) id: string; @IsString() @Length(8, 20) @IsStrongPassword({ minLength: 8, }) @ApiProperty({ example: 'testpw', description: '8-20자', }) pw: string; @IsString() @Length(1, 10) @ApiProperty({ example: 'testname', description: '1-10자', }) name: string; } //컨트롤러 //회원가입api @Post() @ApiOperation({ summary: '회원가입' }) @ApiBody({ type: SignUpDto }) @ApiCreatedResponse({ description: 'created id' }) @ApiConflictResponse({ description: 'id duplicate' }) async signUp( @Body(ValidationPipe) signUpDto: SignUpDto, ): Promise<ChannelEntity> { return await this.channelService.signUp(signUpDto); }
'TIL' 카테고리의 다른 글
모듈 분리 / 서비스 코드 분리 기준 (0) 2024.06.10 의존성 주입(Dependency Injection) (0) 2024.06.10 [ERROR] ReferenceError: exports is not defined in ES module scope (0) 2024.05.28 Express static (0) 2024.05.25 [DB] 트랜잭션 동시에 실행해서 성능올리기 ( confilct serializable한 nonserial schedule을 허용하기 ) (0) 2024.04.08