Nest 프로젝트를 진행하며 특수한 상황의 유효성 검사를 해야할 경우가 생겼다
구현해야 할 유효성 검사 로직
export class ContentDto {
@ApiProperty({
required: false,
type: Sections,
example: '[{ section: 등장 인물, detail: 나용환 }] | null',
})
@IsOptional()
@IsArray({ message: 'sections 리스트 형식이여야 합니다' })
@ArrayNotEmpty({ message: 'sections 리스트가 비어있습니다' })
@ValidateNested({ each: true, message: '유효하지 않은 sections 형식' })
sections?: Sections[] | null = null;
@ApiProperty({
required: false,
example: 'string | null',
type: String,
})
@IsNotEmpty()
@IsString()
@IsOptional()
freeContent?: string | null = null;
}
sections와 freeContent는 둘다 옵션값이지만
둘다 null 일 순 없고
둘 중 하나라도 값이 있어야 했다
class-validator 의 경우는 Dto의 특정 속성에 대한 유효성 검사를 담당하기 때문에
pipe에서 Dto의 검사를 하는게 맞다고 판단했다
커스텀 파이프 만들어보기
먼저 커스텀 파이프를 만들기 위해서는 Nest에서 추상화를 해놓은 PipeTransform 인터페이스로 구현해야 한다

PipeTransform 인터페이스는 value와 metadata 를 인자로 받는데
value는 검증 하고자 하는 대상이고
metadata는 대상의 메타 정보를 담고있다
그리고 transform 메서드를 오버라이딩 해야한다

PipeTransform 인터페이스를 상속하여 sections와 freeContent 중 하나라도 존재하는지 검증하는 파이프를 만들어 보았다
@Injectable()
export class OneFieldRequiredPipe implements PipeTransform {
transform(value: CreateDiaryDto, metadata: ArgumentMetadata) {
const { content } = value;
if (!content.freeContent && !content.sections) {
throw new BadRequestException(
'sections와 freeContent중 하나의 필드는 존재해야 합니다',
);
}
return value;
}
}
간단히 만들수는 있었지만 해당 파이프는 CreateDiaryDto의 타입만 받아야 하는데
다른 실행 영역에서 파이프를 사용하게 되면 타입에러가 나게 된다
그래서 개발자들에게 사용처가 잘못됬다고 알려주는 로직도 추가했다
@Injectable()
export class OneFieldRequiredPipe implements PipeTransform {
transform(value: CreateDiaryDto, metadata: ArgumentMetadata) {
try {
const { content } = value;
if (!content.freeContent && !content.sections) {
throw new BadRequestException(
'sections와 freeContent중 하나의 필드는 존재해야 합니다',
);
}
return value;
} catch (e) {
if (e instanceof BadRequestException) {
throw e;
}
console.error('OneFieldRequiredPipe의 사용처가 잘못됨', e);
throw new InternalServerErrorException();
}
}
}
커스텀 파이프 적용
@ApiOperation({ summary: '일기 작성' })
@Post()
async createDiary(
@Body(OneFieldRequiredPipe) createDiaryDto: CreateDiaryDto,
@GetUser() user: User,
) {
await this.diaryService.createDiary(user, createDiaryDto);
}
'Nestjs' 카테고리의 다른 글
| AI stream 응답을 클라이언트와 SSE 통신하기 (1) | 2024.11.01 |
|---|