It's Ward

[Spring] DTO와 Mapper, Mapper(Map Struct) 사용 방법 - gradle 본문

Java/Spring

[Spring] DTO와 Mapper, Mapper(Map Struct) 사용 방법 - gradle

I'm ward 2022. 6. 27. 23:50

이 글에선 DTO에 대한 간략한 설명과 ,Mapper에 대해서 설명합니다. 

DTO(Data Transfer Object)란?

 DTO는 Data Transfer Object의 약자로 마틴 파울러(Martin Fowler)가 ‘Patterns of Enterprise Application Architecture’ 라는 책에서 처음 소개한 엔터프라이즈 애플리케이션 아키텍처 패턴중 하나로, 데이터를 전송하기 위한 용도의 객체 이다.

Patterns of Enterprise Application Architecture, 마틴 파울러

 

스프링에서는 이전에 포스팅 했던 계층구조 간 데이터를 전송할 때 주로 사용된다.

클라이언트에서 서버 쪽으로 전송하는 요청 데이터, 서버에서 클라이언트 쪽으로 전송하는 응답 데이터 형식으로 데이터가 전송된다.

https://its-ward.tistory.com/entry/Spring-Spring%EC%9D%98-%ED%8A%B9%EC%A7%95%EA%B3%BC-%EA%B3%84%EC%B8%B5-%EA%B5%AC%EC%A1%B0

 

[Spring] Spring의 특징과 계층 구조

Spring을 공부하고 있지만, 기본기가 부족하여 항상 되돌아 오는건 "아 이걸 왜 써야하는거지?", "한번 봤던 것 같은데.." 였다. 이 참에, 확실한 정보를 기억하면서 공부하고 조금 더 내 스스로 이

its-ward.tistory.com

 

객체로 데이터를 전송하게되었을 때의 장점으로는

1. 요청에 필요한 객체를 만들어 프로그램에 적절하게 사용할 수 있고

2. 객체 내 필드와 유효성 검사를 엄격하게 진행할 수 있고

3. 많은 파라미터가 있더라도, 가독성이 떨어지지 않는다는 장점이있다.

한마디로, 프로그램을 만들 때 편의성 증가와 유지보수성을 모두 잡을 수 있다는 장점과, 프로그래밍 측면에서도 한번에 많은 데이터를 옮겨 호출이 줄어들기 때문에, 효율적이다 라는 것이다.

DTO는 어디에 사용되는가?

위에 살짝 나왔지만, DTO는 계층간 이동(Service  <-> Cotroller 등) 뿐만이 아니라 요청 (요청Body -> Cotroller 내 핸들러) 에도 사용된다.

계층간 이동간에는 로직을 가지고 있지 않은 순수한 데이터 객체로, 불변성을 유지하기위해 Setter 사용을 지양한다.

요청에 필요한  DTO는 Entity간 객체 매핑을 통해 Entity로 변환하는경우가 많은데, 이 경우 Builder 패턴을 이용하여 작성도 가능하며

빌더 패턴 예시

Entity를 작성해야하는 경우가 많고, 효율적으로 관리하기 위해 외부 Mapper 클래스를 사용할 수도 있다.

 

Mapper란?

DTO 클래스와 엔티티(Entity) 클래스를 서로 변환해주는 것이다.(DB에 저장하기위해 엔티티에 맞게 변환해 주는 과정이다)

다만, 도메인 기능이 늘어날 때마다 혹은 변경될 때 마다 매번 DTO 내부에 구현을 하는것은 굉장히 비효율적이므로, 속도가 빠른 외부 라이브러리를 가져다가 사용하면 편리하다.

 

어떤 외부 Mapper라이브러리가 있을까?

여기에서 주로 JAVA에서 사용하는 매퍼 라이브러리들을 비교한 것을 확인 할 수 있다.

 

GitHub - arey/java-object-mapper-benchmark: JMH benchmark of Java object-to-object mapping frameworks

JMH benchmark of Java object-to-object mapping frameworks - GitHub - arey/java-object-mapper-benchmark: JMH benchmark of Java object-to-object mapping frameworks

github.com

해당 데이터에 따르면, MapStruct가 굉장히 빠르게 작동하는 것을 확인 할 수 있는데,

이후 프로젝트나, 내가 회사에 들어갔을 때 매퍼가 없거나, 상위권 매퍼가아닌 다른 라이브러리를 사용한다면 이 자료를 참고하여 적극적으로 진행해보면 좋을 것 같다.

Mapper를 gradle에서 사용하기 위해서는 우선, 의존성을 추가해야한다.

dependencies {
    implementation 'org.mapstruct:mapstruct:1.4.2.Final'
	annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'
    ...
}

 

만약에 Member와 Member를 추가하는 MemberPostDto를 mapper를 이용해 만든다면

member Class
요청이 들어오면, 받는 memberResponseDto

 

Mapper 폴더에 MemberMapper를 입력하고, 

 

해당 인터페이스에 다음과 같이 설정하면 자동으로 Bean에 Mapper가 등록된다.

@Mapper(componentModel = "spring") //스프링에서 사용하기 위해 인터페이스 위에 설정
public interface MemberMapper {

    Member memberPostDtoToMember(MemberPostDto memberPostDto); //메소드 이름은 자유롭게 변경 가능
    
}

 

등록이 모두 되었으면 사용하려는 위치에 Mapper를 추가하여 다음과 같이 사용가능하다

Comments