이번 시간에는 Nest.js의 DTO(Data transfer object)로부터 MongoDB 의존성을 없앴던 방법을 공유하려 합니다.
이 포스팅을 읽고 난 후에는 다음의 내용을 얻어가실 수 있습니다.
- DTO로부터 특정 DB의 의존성을 제거하기
Model
User, Report model들을 코드로 확인해보죠.
user.entity.ts
@Schema()
export class User {
id: string;
@Prop({
select: false,
})
__v?: number;
@ApiProperty()
@Prop()
email: string;
@Prop({})
password: string;
@Prop({
default: true,
})
isAdmin: boolean;
}
report.entity.ts
@Schema()
export class Report {
id: string;
@Prop({ select: false })
__v?: number;
@Prop()
price: number;
@Prop()
make: string;
@Prop()
model: string;
@Prop()
year: number;
@Prop()
lng: number;
@Prop()
lat: number;
@Prop()
mileage: number;
@Prop({
ref: User.name,
type: mongoose.Schema.Types.ObjectId,
})
userId: mongoose.Types.ObjectId | string;
@Prop({
default: false,
})
approved: boolean;
}
User
와 Report
는 one-to-Many의 관계를 가지고 있죠. Report.userId
필드를 확인해보면 Report가 User
의 id
를 reference로 가지고 있는 것을 확인할 수 있습니다.
Create Report
report를 생성하는 API가 있다면 생성된 Report를 클라이언트에게 response body로 전달하겠죠. 이를 ReportDto
라고 하겠습니다.
report.dto.ts
export class ReportDto {
//...
@Expose()
userId: mongoose.Types.ObjectId;
}
mongoDB로 부터 생성된 Report
는 userId
필드에 mongoose.Types.ObjectId
인스턴스를 가집니다. 바로 여기서 문제가 된다고 생각한 점이 2가지가 있습니다.
- DTO가 specific한 MongoDB의 의존성을 가지고 있는 점
- ObjectId를 string화 해야하는 점
위의 두 경우를 해결하기 위해 class-transformer
라이브러리의 Transform
데코레이터를 활용했습니다. 이 데코레이터를 사용해서 ObjectId
를 string
으로 바꾸는 과정을 거치게합니다.
export const TransormToString = () =>
applyDecorators(Transform(({ obj, key }) => obj[key].toString()));
이를 적용한 후에 typing을 mongoose.Types.ObjectId
가 아닌 string
으로 바꿔줬습니다.
export class ReportDto {
@Expose()
@TransformToString()
userId: string;
}
이렇게 MongoDB 의존성을 제거하면 미래에 다른 DB로 바꾸는 시점에 코드가 깨지는 일을 최소화시킬 수 있습니다. 물론 너무 먼 얘기일 수도 있지만 그렇지 않을 수도 있죠.
마치며
최근 Nest.js를 학습하며 회사에서 프런트엔드 뿐만이 아닌 서버 코드에서 개선할 점이 있는지 고민하고 있습니다. 그 과정에서 Dto의 사용범위를 어디까지 가져야할 것인지 즉, controller와 service 레이어 중 어디까지로 제한할지 고민을 했습니다. 다음 포스팅에서는 해당 내용에 대해 얘기해보도록 하겠습니다.
'Backend' 카테고리의 다른 글
NestJS dependency injection flow (0) | 2023.06.10 |
---|