프로젝트를 진행하면서 dto를 평소처럼 사용하던 도중... 고민거리가 생기게 됬다. 나는 각각의 layer가 잘 분리된 형태로 사용 될수있기를 원했는데 생각보다 잘 되지 않았다.
일단 아래와 같이 Service layer에서 DTO <> Entity 로 변환하는 코드를 포함해서 구현해 놓았다.
@PostMapping
public ResponseEntity<Object> create(@Valid RequestDTO requestDTO) {
ResponseDTO response = service.create(RequestDTO);
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}
public ResponseDTO create(RequestDTO parameterDTO) {
Entity entityData = mapper.toEntity(parameterDTO);
Entity result = repository.save(entityData);
ResponseDTO dto = mapper.toDto(result);
return dto;
}
Client가 요청하는 데이터가 변경되면 비지니스 로직도 같이 변경해야 하는게 많이 어색해 보였다. Domain Service는 단지 Domain Service로의 역할만 했으면 했다.
위의 문제를 해결하기 위해서 한곳에서 DTO를 사용하는 것을 고정하는 것이 아닌 둘다 사용하면 어떨까? 라는 생각을 하게 되었다.
Service layer에는 Entity를 그대로 사용하면 문제(Entity 외부노출, 순환참조 문제 등)가 될 수 있기 때문에 기존대로 DTO <> Entity 로직이 들어간다. 그러나 Service layer에서 사용하는 DTO는 하나에 속한 View를 위한것이 아닌 공통적으로 사용하기 위한 DTO가 되고, 이것을 사용하는 Controller에서는 DTO 그대로 사용하거나 자신이 필요한 구조로 변경을 해서 다시 사용을 하는 것이다.
@PostMapping
public ResponseEntity<Object> create(@Valid RequestDTO requestDTO) {
EntityDTO dto = mapper.toEntityDto(requestDTO);
EntityDTO resultDto = service.create(dto);
ResponseDTO response = mapper.toResponse(resultDto);
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}
public EntityDTO create(EntityDTO parameterDTO) {
Entity entityData = mapper.toEntity(parameterDTO);
Entity result = repository.save(entityData);
EntityDTO dto = mapper.toDto(result);
return dto;
}
DTO <> DTO 의 구조처럼 변경이 되게 되는데, 이렇게 되면 Client에서 요청하는 데이터가 변경되게 되더라고 Service에서 공통으로 사용되는 DTO로 변환을 통해서 Service의 로직은 변경되지 않고 사용할 수 있을것 같다.
Service layer에서 사용하는 Object는 Entity와 EntityDTO로 일관되게 사용할 수 있다.