
Dto
계층 간 데이터 교환을 위한 객체(Data Transfer Object)를 의미한다. 일반적인 Dto는 로직을 갖고 있지 않으며 순수한 데이터 객체 형태로 존재한다. 프로젝트 진행 전 올바른 Dto의 설계는 필수조건이다. Dto 설계란 도메인에서 필요한 데이터값 들을 객체화시키고 어떤 타입의 데이터로 정의하는지에 대한 의미로 해석하면 될 거 같다. 다음은 효과적인 Dto 사용을 위해 준수해야할 사항이다.
- 상용구 코드 최소화를 최소화해야 함(코드를 일일이 새로 작성하므로)
- 작성이 용이해야 함 작성이 어려울 정도로 복잡해서는 안 됨
- 누구든지 코드 구문을 분석할 수 있어야 함
간단한 회원가입 앤드 포인트
router.post("/create", new UserController().createUser);
joi 라이브러리를 기본으로 상속받는 사용자 Dto 클래스 생성
export interface ICreateUser {
email: string;
password: string;
}
export class CreateUserDto implements IBaseDto {
email: string;
password: string;
constructor({ email, password }: { email: string; password: string; }) {
this.email = email;
this.password = password;
}
getJoiInstance(): ObjectSchema<CreateUserDto> {
return joi.object<CreateUserDto>({
email: joi.string().trim().min(2).max(10).required(),
password: joi.string().trim().min(2).max(20).required(),
});
}
}
export default interface IBaseDto {
getJoiInstance(): ObjectSchema;
}
export default class JoiValidator {
public async validatorAsync<T extends IBastDto>(anyDto: IBastDto): Promise<T> {
return await anyDto.getJoiInstance().validateAsync(anyDto);
}
}
Controller 레이어의 Dto
요청의 바디에 담겨있는 값들을 JoiValidator를 통해 유효성 검사 후 결과값으로 Service 레이어의 createUser 메서드를 호출한다.
export default class UserController {
private userService: UserService;
private joiValidator: JoiValidator;
constructor() {
this.userService = new UserService();
this.joiValidator = new JoiValidator();
}
public createUser: RequestHandler = async (req, res) => {
const validator = await this.joiValidator.validatorAsync<CreateUserDto>(new CreateUserDto({
email: req.body.email,
password: req.body.password,
}));
const createUser = await this.userService.createUser(validator);
}
}
Service 레이어의 Dto
실질적인 비즈니스 로직이 호출되는 단계다. 유효성 검사가 끝난 Dto를 넘겨받아 Repository 레이어의 createUser 메서드를 호출한다.
export default class UserService {
private userRepository: UserRepository;
constructor() {
this.userRepository = new UserRepository();
}
createUser = async (userDto: CreateUserDto) => {
const createUser = this.userRepository.createUser(userDto);
}
}
Repository 레이어의 Dto
해당 Dto의 적절한 로직에 따라 데이터베이스 쿼리를 작성한다.
export default class UserRepository {
public createUser(userDto: CreateUserDto) {
// 데이터베이스 쿼리 작성
}
}