NestJS - Mapped Types와 혼란

저뉼(스님?)·2023년 3월 9일
3
post-custom-banner

기본 개념

NestJS는 DTO를 재사용할 수 있는 유용한 기능들을 제공해.

  • PartialType()
    부모 DTO의 모든 속성들을 물려받지만 전부 Optional
  • PickType()
    부모 DTO의 속성 중 몇 개만 골라서 물려받음
  • OmitType()
    부모 DTO의 속성 중 몇 개만 제외하고 물려받음.
  • IntersectionType()
    두 부모 DTO의 속성들을 모두 물려받음.

그리고 이런 식으로 함께 사용할 수도 있어.

  • PartialType(OmitType())

보통 다음과 같이 UPDATE DTO를 만들 때 사용하지.

export class UpdateUserDto extends PartialType(CreateUserDto) {}

혼란

그런데 말이야.
공식 문서 보면 이렇게 말하고 있단 말이야?

HINT
The PartialType() function is imported from the @nestjs/swagger package.

난 이게 한동안 문서를 잘못 작성한 건가 싶었어.

문서대로 한다고 아래처럼 코드를 작성해 보면,

// create-user.dto.ts
import { IsString } from 'class-validator';

export class CreateUserDto {
  @IsString()
  readonly name: string;
  
  @IsString()
  readonly email: string;
}
// update-user.dto.ts
import { PartialType } from '@nestjs/swagger';

export class UpdateUserDto extends PartialType(CreateUserDto) {}

PartialType을 사용했기 때문에, 요청 보낼 때 name이나 email의 값을 마음대로 생략할 수 있어야 하는데 하나라도 생략하면 에러 응답을 뱉더라고. 둘 다 그대로 필수인 거야.

그런데 PartialType@nestjs/mapped-types 패키지에도 있고 이 패키지를 사용하면 의도대로 잘 동작한단 말이지?
그래서 '문서 수정 PR을 올려야 하나..' 하다가 좀 더 찾아봤어.

@nestjs/swaggerPartialType()도 비슷한 기능을 하긴 한다더라고? (Thanks to New Bing and ChatGPT)
'아, 그러면 @nestjs/swagger가 제대로 동작 안 하는 건가? 저걸 고쳐서 PR을 올려야 하나..' 하다가 찾았지, 동작하지 않았던 이유를.

If you import the PartialType from the @nestjs/swagger package, you should either annotate all DTO properties with the @ApiProperty() decorator OR enable the @nestjs/swagger CLI Plugin. Otherwise (in case you don't want to use Swagger), you should use PartialType from the @nestjs/mapped-types package instead

간단히 말해서,
@nestjs/swagger 패키지의 PartialType을 사용할 때는 부모 DTO의 모든 property에 @ApiProperty()를 붙여야 한다는 거야. 😅

+
하긴.. 안 그러면 문제가 되겠네.
Update DTO가 PartialType()을 사용하면 property를 명시하지 않으니, Create DTO에서 했듯이 property에 @ApiProperty()를 붙이는 방식으로 문서화할 수는 없겠네.
문서화는 스프링으로 해 둔 거 쓰고 있어서 구현에만 집중하느라 몰랐다.

post-custom-banner

3개의 댓글

깃헙과 이슈를 찾아다녀야만 문제를 해결할 수 있는, 공식문서 미니멀리즘 nestjs...

2개의 답글