엔티티를 controller 에 노출시키는 것은 controller 가 service 뿐만 아니라 repository 에서 다루는 entity 까지 의존관계를 가지게 되므로 controller 에 의존성이 너무 높아지게 된다. 그렇다면 어떻게 dto 를 설정하는 것이 좋을까?
기본적으로 3개의 계층으로 이루어져 있다.
1. 유저 + 브라우저와 상호작용하는 로직이 잇는 Presentation Layer
2. 요청에 맞는 비즈니스 로직을 수행하는 Business Layer
3. 데이터를 저장하고 관리하는 persistence Layer
화살표에 방향을 잘 보아야 한다.
controller -> Service -> Repository
의존성의 방향이 Controller에서 Repository로 단방향으로 흐르는 것이 일반적이다.
여기서 발생할 수 있는 문제는 바로
이는 controller -> Service -> Repository
의존성의 방향에서 service 가 controller 를 바라보는 역방향을 나타나게 된다. 결국 service 가 받는 데이터 형태는 controller 에 의존하게 된다.
만약 service 레이어가 모듈로 분리되면 해당 데이터를 사용하기 어려워진다.
또한 controller 가 외부 API를 호출하면서 controller 에서 받은 dto 의 값이 변하게 되어 service 가 받는 dto 값이 달라지게 될 수도 있다고 한다.
결론적으로 의존성의 방향뿐만 아니라 확장성을 위하여 service 가 필요한 정확한 데이터만 담는 dto 를 servie 계층에서 다루는 것이 더 이상적이다.
@RestController
@RequestMapping("/api/v1")
@RequiredArgsConstructor
public class DrawController {
private final DrawService drawService;
private final DrawTicketService drawTicketService;
private final ControllerDrawMapper controllerDrawMapper;
@PostMapping("/draws")
public ResponseEntity<DrawResponse> saveDraw(
@Valid @RequestBody DrawSaveRequest saveRequest
) {
ServiceDrawSaveDto serviceDrawSaveDto = controllerDrawMapper.convertToServiceDrawSaveDto(saveRequest);
DrawResponse drawResponse = drawService.save(serviceDrawSaveDto);
return ResponseEntity
.ok()
.body(drawResponse);
}
@Service
@RequiredArgsConstructor
@Transactional
public class DrawService {
private final DrawRepository drawRepository;
private final ServiceDrawMapper serviceDrawMapper;
public DrawResponse save(ServiceDrawSaveDto drawSaveRequest) {
Draw draw = serviceDrawMapper.convertoDraw(drawSaveRequest);
Draw savedDraw = drawRepository.save(draw);
return serviceDrawMapper.convertToDrawResponseDto(savedDraw.getId());
}
}
원칙은 없다 performance 와 개발속도 등 많은 것을 고려하여 결정할 것이다. 하지만 MSA 와 모듈 개발이 보편적인 지금 의존성을 최대한 줄여 확작성과 유지보수를 우선시 하는 것이 더 중요하다고 판단된다.