본문 바로가기
프로젝트/DailycluB

Entity와 DTO의 사용 범위는 어떻게 해야 할까?

by 넬준 2022. 9. 22.

 

 현재 프로젝트에서는 API계층, Controller에서 DTO <-> Entity 변환 작업을 하고 있다. 즉, Controller에서 Controller에 의존적인 Mapper를 이용해 RequestDto를 Entity로 변환하고, 이를 Service 계층으로 넘긴다. 그리고 작업 후 Repository로부터 넘어온 Entity를 Service 계층은 그대로 Controller로 넘기고 Entity를 ResponseDto로 변환한다.

 

@Operation(summary = "프로그램 등록")
@ApiResponses(
    @ApiResponse(
        responseCode = "201",
        description = "CREATED"
    )
)
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<ProgramDto.Response> postProgram(@ParameterObject @Validated @ModelAttribute ProgramDto.Post programPostDto,
                                                       @RequestPart(required = false) MultipartFile imageFile,
                                                       @Parameter(hidden = true) @AuthenticationPrincipal AuthDetails authDetails) throws IOException {
    Long loginUserId = authDetails.getUserId();
    log.info("[postProgram] loginUserId={}", loginUserId);

    //DTO -> Entity
    Program programFromPostDto = programMapper.programPostDtoToProgram(programPostDto);

    //ProgramService 호출 (Program 등록 후 ProgramImage 등록)
    Program createdProgram = programService.createProgram(loginUserId, programFromPostDto, imageFile);

    //Entity -> DTO
    ProgramDto.Response response = programMapper.programToProgramResponseDto(createdProgram);

    return new ResponseEntity<>(response, HttpStatus.CREATED);
}

 

 일단 Controller에서 Entity를 응답하지 않는 이유는 명확하다. 

1. Entity에는 화면에 필요하지 않은 정보까지 가지고 있으므로 보안에 문제가 생길 수 있다. 즉, Entity의 모든 정보가 외부에 노출이 된다.

2. Model과 View가 강하게 상호 결합하게 된다. View의 변화와 Model의 변화가 서로에게 영향을 미치기 때문에 유지보수가 힘들어지게 된다.

 

 하지만 'Entity와 DTO 변환 작업을 꼭 Controller 계층에서 해야 하는 것인가? Service 계층에서 하는 것은 불가능한가?'에 대한 의문이 생겼고, 관련 글들을 찾아보니 역시나 비슷한 고민을 하는 개발자들이 많았다. 

 

 결론 먼저 정리하자면, "딱 떨어지는 정답은 없다"는 것이다.

 좀 더 풀어보자면, Controller 계층에서 변환하는 것과 Service 계층에서 변환하는 것은 각각 다른 장단점을 가지고 있으므로,현재 프로젝트의 규모, 특성, 상황에 맞게 설계해야 한다는 뜻이다.

 

 만일, Service 계층까지 DTO를 그대로 넘겨주면 다음과 같은 상황이 발생할 수 있다. (변환 계층 : Service 계층)

1. View의 상황에 따라 DTO가 변경될 수 있는데 이 영향이 Service 계층까지 미치게 된다. 즉 Service와 View 사이가 강하게 결합하게 된다.

2. Service 계층의 메서드가 특정 DTO에 의존하게 되면 여러 Controller에서 해당 메서드를 사용할 수 없을 수 있다.

 

 Controller 계층에서 Entity를 사용하게 되면 다음과 같은 상황이 발생할 수 있다. (변환 계층 : Controller 계층)

1. 결국 View에 필요없는 Entity 정보까지 Controller 계층까지 넘어온다.

2. 하나의 DTO를 만들기 위해 여러 Entity의 정보가 필요하다면, Controller가 의존하는 Service 클래스가 많아진다.

 

 이를 해결하기 위해 Controller 계층과 Service 계층에 각각 다른 DTO를 만드는 방식도 있다. 단, 이 경우에는 타입 간 변환을 위한 보일러 플레이트 코드가 많이 생길 수 있다.


참고


https://kafcamus.tistory.com/12

https://dbbymoon.tistory.com/4

https://techblog.woowahan.com/2711/

https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/

https://stella-ul.tistory.com/163

https://velog.io/@483759/DTO의-사용성과-매핑-전략

댓글