프로젝트를 진행하면서
기존 코드에 DTO가 적힌 부분을봤는데 의문점이 들어서 간단하게 정리용으로 작성함 후에 더 깊게 파야함
class UserDto {
address: string;
signature: string;
}
@Post('login/verify')
async login(@Body() dto: UserDto, @Res() res:Response ): any {
const result: { accessToken: string; refreshToken: string } = await this.authService.login(
dto.address,
dto.signature,
);
}
일단 사건의 발단은 저 코드에서 UserDto가 실제로 컴파일타임, 런타임에 무슨 역할을 하는지 궁금했음
내가 알고 있는 TS에대한 지식으로는 저렇게 클래스를 선언하면 변수를 할당하지 않는 이상 해당 클래스는 아무런 프로퍼티가 없는 상태다
class MetaMaskVerifyDto {} <- 컴파일 시점에는 빈 객체
이게 과연 런타임에 무슨 의미가 있을까,
그리고 어떻게 dto.[property]에 접근할 수 있었을까?
조금 더 질문을 좁혀보자면 다음과 같다.
interface/type과 비교해 class로 작성하는 이유?
컴파일시점과 런타임에는 어떻게 동작하는가?
dto를 js/ts에는 어떻게 다뤄야하는가?
일단 ts 공식문서에서는 찾지 못했지만 내가 사용하는 프레임워크인 nestjs공식문서에서 다음과같은 글을 찾았따.
https://docs.nestjs.com/controllers
Before we proceed (if you're using TypeScript), we need to define the DTO (Data Transfer Object) schema. A DTO is an object that specifies how data should be sent over the network. We could define the DTO schema using TypeScript interfaces or simple classes. However, we recommend using classes here. Why? Classes are part of the JavaScript ES6 standard, so they remain intact as real entities in the compiled JavaScript. In contrast, TypeScript interfaces are removed during transpilation, meaning Nest can't reference them at runtime. This is important because features like Pipes rely on having access to the metatype of variables at runtime, which is only possible with classes.
Let's create the CreateCatDto class:
create-cat.dto.tsJS
export class CreateCatDto {
name: string;
age: number;
breed: string;
}
DTO를정의할 때 interface/type을 상용하게 되면 트랜스파일링할때 지워져서 해당 entity에 접근할 수 없다.
그렇기 때문에 class로 작성하는 것을 권장한다.
그리고후에 pipe를 활용할 만들어 놓은 dto 객체가 사용된다고 명시되어 있다.(like Pipes rely on having access to the metatype of variables at runtime, which is only possible with classes)
즉, interface/type을 사용해도 상관은 없지만 nest에서는 다른 feature들을 사용하기 위해서는 class로 dto를 정의한다고 보면된다.
1번에서 많은 의문점이 해소되었지만
컴파일시점 js로 변환됐을 때는 해당 class의 껍데기만 남게된다.
class UserDto {}
그리고 런타임 시점에서는 아무런 역할도 하지 않는다. 그저 객체가 body로 들어오면 아. 들어왔구나 통과~ 다음 로직에서 처리하게 된다.
즉
this.authService.login(
dto.address,
dto.signature,
);
이렇게 dto.address -> json에 address property가 없다? 그냥 undifined로 할당 -> 다음 로직 실행
DATA TRANSFER OBJECTS
데이터를 전달하는 객체...
아마 zod를 몇번 더 써보면 정확하게 답이 나올거같아서
현재는 더 길게는 안적을꺼같음
처음에 작성할 때 의문은 1,2,3 이렇게 3개였는데
1번에서 꽤 많은 의문점이 해소되었다.