npm install --save @nestjs/swagger
http://localhost:3000/api 에서 Swagger UI를 확인할 수 있다..addCookieAuth().addBearerAuth()persistAuthorization: true 옵션을 추가해주어야 한다.main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const config = new DocumentBuilder()
.setTitle('API 문서 제목')
.setDescription('API 문서 설명')
.setVersion('1.0')
.addCookieAuth() // 쿠키 인증 방식 추가
.addServer(process.env.HOST)
.build();
// config를 바탕으로 swagger document 생성
const document = SwaggerModule.createDocument(app, config);
// Swagger UI 경로 설정
SwaggerModule.setup('api', app, document, {
swaggerOptions: { persistAuthorization: true }, // 인증 정보를 유지
});
await app.listen(3000);
}
bootstrap();
@ApiPropertyimport { ApiProperty } from '@nestjs/swagger';
@ApiProperty({ description: '아이디', example: 'username' })
username: string;
@ApiPropertyOptional@ApiProperty와 동일한 기능을 가지지만, 선택적인 속성임을 명시import { ApiPropertyOptional } from '@nestjs/swagger';
@ApiPropertyOptional({ description: '연락처', example: '010-1234-5678' })
contact?: string;
Class Transformer와 Class Validator 어노테이션을 함께 사용하면 효율적인 API 문서화를 구현할 수 있다.
Class Validator는 DTO의 유효성 검사를 정의하는 데 사용되고, Class Transformer는 데이터 직렬화와 역직렬화를 제어하는 데 사용된다.
@Exclude@Expose 어노테이션을 사용하여 특정 속성만 포함시킬 수 있다.import { Exclude } from 'class-transformer';
@Exclude()
export class UserDTO {
// 클래스 내용
}
@Expose@Exclude된 클래스에서 특정 속성을 직렬화 과정에 포함시킨다.import { Expose } from 'class-transformer';
@Expose()
@ApiProperty({ description: '아이디', example: 'username' })
username: string;
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Exclude, Expose } from 'class-transformer';
import { randomUUID } from 'crypto';
@Exclude()
export class UserDTO {
@Expose()
@ApiProperty({ description: 'ID', example: randomUUID() })
id: string;
@Expose()
@ApiProperty({ description: '아이디', example: 'username' })
username: string;
@Expose()
@ApiPropertyOptional({ description: '연락처', example: '010-1234-5678' })
contact: string;
@Expose()
@ApiProperty({ description: '등록일시', type: 'Date' })
createdAt: Date;
@Expose()
@ApiProperty({ description: '수정일시', type: 'Date' })
updatedAt: Date;
}

@IsNotEmptyimport { IsNotEmpty } from 'class-validator';
@IsNotEmpty({ message: '아이디를 입력해 주세요.' })
username: string;
@IsOptionalimport { IsOptional } from 'class-validator';
@IsOptional()
contact?: string;
@IsString, @IsNumber, @IsEmail@IsString() // 값이 문자열인지 검사
username: string;
@IsNumber() // 값이 숫자인지 검사
age: number;
@IsEmail({}, { message: '유효한 이메일 주소를 입력해 주세요.' }) // 값이 이메일 형식인지 검사
email: string;
@MinLength, @MaxLength@MinLength(8, { message: '비밀번호는 최소 8자 이상이어야 합니다.' })
password: string;
@MaxLength(20, { message: '사용자 이름은 최대 20자까지 가능합니다.' })
username: string;
@Validate@Validate(PasswordMatch, { message: '비밀번호가 일치하지 않습니다.' })
passwordConfirm: string;
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsNotEmpty, IsOptional, MinLength, Validate } from 'class-validator';
import { PasswordMatch } from '../validators/password-match.validator';
export class CreateUserDTO {
@IsNotEmpty({ message: '아이디를 입력해 주세요.' })
@ApiProperty({ description: '아이디', example: 'username' })
username: string;
@IsOptional()
@ApiPropertyOptional({ description: '연락처', example: '010-1234-5678' })
contact?: string;
@IsNotEmpty({ message: '비밀번호를 입력해 주세요.' })
@MinLength(8, { message: '비밀번호는 최소 8자 이상이어야 합니다.' })
@ApiProperty({ description: '비밀번호', example: 'password' })
password: string;
@IsNotEmpty({ message: '비밀번호를 다시 한 번 입력해 주세요.' })
@Validate(PasswordMatch, { message: '비밀번호가 일치하지 않습니다.' })
@ApiProperty({ description: '비밀번호 확인', example: 'password' })
passwordConfirm: string;
}

@ApiTags@ApiTags('users')
@Controller('users')
export class UsersController {
// logic
}

@ApiOperation@Get()
@ApiOperation({
summary: '사용자 전체 조회',
description: '사용자 전체를 조회합니다.',
})
async findAll() {
// logic
}

@ApiResponse()type 대신 사용하며, 더 복잡한 구조를 정의할 때 유용@Post('signup')
@ApiOperation({
summary: '회원가입',
description: '회원가입합니다.',
})
@ApiResponse({
status: 200,
description: '성공적으로 처리됨',
schema: {
type: 'array',
items: { $ref: getSchemaPath(UserDTO) },
},
})
async create(@Body() body: CreateUserDTO) {
// logic
}

@ApiResponse는 모든 상태 코드에 대한 응답을 설명하는데 사용되며, 모든 HTTP 상태 코드에 사용할 수 있다.@ApiCreatedResponse , @ApiOkResponse 과 같이 특정 상태코드을 나타내는데 특화되어 있는 어노테이션을 사용하면, 코드의 가독성을 높일 수 있다.@ApiCreatedResponse @Post('signup')
@ApiOperation({
summary: '회원가입',
description: '회원가입합니다.',
})
@ApiCreatedResponse({
description: '성공적으로 생성됨',
type: UserDTO,
})
async create(@Body() body: CreateUserDTO) {
// logic
}

@ApiOkResponse@ApiOkResponse({
description: '성공적으로 처리됨',
type: UserDTO,
})
@Get(':id')
getUser(@Param('id') id: string) {
// logic
}
@ApiQuery: 쿼리 파라미터를 설명하는 데 사용@ApiQuery({ name: 'page', required: false, description: '페이지 번호', type: Number })
@ApiQuery({ name: 'limit', required: false, description: '페이지당 항목 수', type: Number })
@Get()
getUsers(@Query('page') page: number, @Query('limit') limit: number) {
// logic
}

@ApiParam/users/:id에서 id가 경로 파라미터trueString).@ApiOperation({ summary: '사용자 정보 가져오기', description: '특정 사용자의 정보를 가져옵니다.' })
@ApiParam({ name: 'id', required: true, description: '사용자 ID', type: String })
@Get(':id')
getUser(@Param('id') id: string) {
// logic to get user
}

@ApiBodytrue @ApiOperation({ summary: '사용자 생성', description: '새로운 사용자를 생성합니다.' })
@ApiBody({ description: '사용자 생성 데이터', type: CreateUserDTO })
@Post('create')
create(@Body() createUserDto: CreateUserDTO) {
// logic to create user
}

References
NestJs 프로젝트에서 Swagger 사용하기
[Nest.js] swagger 적용하기
Documentation | NestJS - A progressive Node.js framework
jhyeok.com