모델 매퍼(ModelMapper)
스프링의 경우 DTO와 엔터티간의 변환을 할 때 ModelMapper나 Mapstruct라는 라이브러리를 많이 사용합니다. 그러면, 객체가 가질 수 있는 프로퍼티는 옮겨지게 되고, 아닌 프로퍼티는 버려지게 되죠.
JS는 그러한 역할이 없어서 상당히 불편했습니다. Interface를 고집한다는 점과 Class instance와 Literal object 간 변환이 어렵다는 점이 이유입니다. 그나마 쓸만한 라이브러리가 AutoMapper인데 사용하기가 어렵고 유지보수가 중지되었죠.
그래서 최근에 나와서 핫한 라이브러리 중 하나가 class-transformer입니다. 이 라이브러리는 ModelMapper 역할을 훌륭하게 수행할 수 있고, 상당히 강력하고 간단합니다. 최근 commit을 보거나, star 수를 보더라도 충분히 신뢰할만 하다고 할 수 있습니다.
repository: https://github.com/typestack/class-transformer
npm: https://www.npmjs.com/package/class-transformer'
준비
1. class-transformer 라이브러리와 reflect-metadata 라이브러리를 설치해야 합니다.
npm install class-transformer --save
npm install reflect-metadata --save
2. 전역 설정 파일(app.ts, config.ts 등 -> 본인은 config.ts)에서 reflect-metadata를 import해야 합니다.
(그래야 설정이 적용됨)
import 'reflect-metadata';
실제 사용(구현)
아래 예시를 보면 굉장히 간단합니다. 이를 통해, userJson에 있는 User클래스가 가진 프로퍼티들만 새로운 객체를 생성해서 부어줍니다.
import { plainToClass } from 'class-transformer';
let users = plainToInstance(User, userJson);
저의 프로젝트의 예시입니다. 이전에는 아래와 같이 굉장히 긴 코드를 사용하고 있었습니다. 딱 봐도 코드가 길어서 짜증나고, request body가 길면 길 수록 코드도 더 길어집니다. 그리고 DTO가 변경되면, 이런 Layer를 이동시키기 위한(DTO -> Service) 코드들도 전부 변경해줘야 합니다.
toCreate = async (req: Request): Promise<CreateBookingDto> => {
return {
categoryId: toString(req.body.categoryId),
resourceId: toString(req.body.resourceId),
count: req.body.count,
startTime: req.body.startTime,
endTime: req.body.endTime,
status: req.body.status,
isAnonymous: req.body.isAnonymous,
images: [{
image_path: req.body.image_path,
image_name: req.body.image_name,
image_type: req.body.image_type
}]
};
};
아래는 class-transformer를 도입한 후 코드입니다. 코드도 줄었고, 유지보수도 간편해졌습니다. 단일 책임의 원칙도 지킬 수 있게 되었네요. excludeExtraneousValues 옵션은 class가 가지고 있지 않은 properties는 제외시키는 옵션입니다.
toCreate = async (req: Request): Promise<CreateBookingDto> => {
const createBookingDto: CreateBookingDto =
plainToInstance(CreateBookingDto, req.body, { excludeExtraneousValues: true });
return createBookingDto;
};
감사합니다.
'Server > Node.js' 카테고리의 다른 글
NodeJS - 전역 예외 핸들러 구현 (Custom global exception handler) (0) | 2021.12.29 |
---|---|
NodeJS - API Response를 snake case로 변환하기(DTO, Entity 필드는 camel case) (0) | 2021.12.27 |
NodsJS - BullMQ 사용 (대기열, 동시성 제어 등) (0) | 2021.12.25 |
NodeJS - JSON null필드를 Response에서 생략하는 방법! (0) | 2021.12.21 |
Sequelize - 자식 테이블까지 한 번에 Insert 치는 방법 (Join Insert) + 상황에 따라 다른 쿼리를 날리는 방법 (0) | 2021.12.19 |