본문 바로가기

Tech/Spring | SpringBoot

[Spring] MapStruct

반응형

1. MapStruct ?

MapStruct 는 매핑된 object 를 서로 변환해주는 기능을 제공하는 라이브러리이다. mapper 인터페이스에서 두개의 Java Bean 타입에 대해서 매핑하는 함수를 선언하면 MapStruct 는 해당 인터페이스를 자동으로 구현하여 매핑 함수를 생성해준다.

 

스프링을 사용하다 보면 객체를 다른 객체로 변환해야 하는 경우가 있다. 주로 DTO DB Entity 간의 변환이 많이 발생한다. 이런 부분에서 MapStruct 를 사용한다면 bean mapper 함수를 따로 구현하지 않고 자동으로 변환할 수 있도록 할 수 있다.

 

MapStruct 는 어노테이션 기반으로 동작한다. @Mapper 어노테이션을 통해서 mapper 인터페이스를 선언하고 메서드를 선언하여 사용할 수 있다. 그외에도 @Mapping 어노테이션을 사용하여 객체의 필드 간에 매핑을 정의할 수 있다.

2. MapStruct 예제

- gradle 설정

스프링에서 MapStruct 를 사용하기 위해서는 MapStruct 라이브러이에 대한 dependency 설정을 추가해주어야 한다. gradle 을 사용하는 경우에는 아래와 같이 build.gradle 의 dependencies 에 mapstruct 라이브러리를 추가해주면 된다.

 

dependencies {
    implementation 'org.mapstruct:mapstruct:1.5.3.Final'
    annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final'
}
// https://mapstruct.org/documentation/installation/

- Java Bean 구현

MapStruct 를 통해 매핑할 자바 객체를 구현한다.

 

@Getter
@Setter
public class Source {
    private String id;
    private String name;
    private String source;
}

@Getter
@Setter
public class Dest {
    private String id;
    private String name;
    private String dest;
}

 

Source 와 Dest 는 각각 id 와 name 이라는 필드를 가지는 간단한 클래스이다. MapStruct 를 사용하기 위해서는 변환 되기 전의 객체는 필드 값을 가져올 수 있도록 getter 가 있어야 하고 변환 결과의 객체는 필드 값을 설정할 수 있는 setter 가 필요하다. 예제에서는 lombok 을 사용하여 각각의 클래스에 getter, setter 를 추가해주었다.

- Mapper Interface

Mapper 인터페이스를 구현한다. @Mapper 어노테이션으로 지정해준 인터페이스 내부에 Source to Dest 와 Dest to Source 라는 각각의 클래스 간의 변환을 위한 메서드를 선언해준다. 이때 @Mapping 어노테이션을 사용하면 서로 다른 이름을 가진 필드를 매핑해줄 수 있다. 예제에서는 Source 의 source 필드와 Dest 의 dest 필드를 매핑하였다.

 

@Mapper
public interface CustomMapper {
    @Mapping(target = "dest", source = "source.source")
    public Dest sourceToDest(Source source);

    @Mapping(target = "source", source = "dest.dest")
    public Source destToSource(Dest dest);
}

 

MapStruct 는 컴파일 시점에 Mapper Interface 를 구현한 클래스를 자동 생성한다. 그렇기 때문에 해당 프로젝트를 빌드한 후에 프로젝트의 'bin/generated-sources/annotations/' 아래를 찾아보면 MapStruct 가 구현한 CustomMapperImpl.java 라는 코드를 발견할 수 있다.

 

@Mapper(componentModel = "spring")
public interface CustomMapper { ... }

 

스프링에서는 Mapper 클래스를 스프링 빈으로 등록할 수 있다. Mapper 어노테이션의 componentModel 을 "spring" 으로 정의해주면 자동으로 스프링 빈에 등록되어 @Autowired 를 통해 사용할 수 있다. 만약 따로 componentModel 을 지정하지 않으면 default 로 값이 들어가는데, 이 경우에는 Mapper.getMapper(Class) 메서드를 통해서 mapper 객체를 사용할 수 있다.

- Test code

@SpringBootTest
public class CustomMapperTest {
   
    @Autowired
    CustomMapper mapper;

    @Test
    public void testCustomMapper() {
        Source source = new Source();
        source.setId("testId");
        source.setName("testName");

        Dest dest = mapper.sourceToDest(source);

        assertEquals(source.getId(), dest.getId());
        assertEquals(source.getName(), dest.getName());
       
        source = mapper.destToSource(dest);
       
        assertEquals(source.getId(), dest.getId());
        assertEquals(source.getName(), dest.getName());
    }
}

 

앞에서 구현한 Java Bean 들과 이들을 변환하는 mapper 인터페이스를 사용하여 실제 객체를 변환하는 테스트 코드를 작성하였다.

 

mapper 는 @Autowired 로 injection 하도록 하였다. 테스트 코드는 Source 객체를 Dest 로 변환한 다음 id, name 을 비교하고, Dest 객체를 다시 Source 객체로 변환하여 id, name 을 비교하도록 구현하였다. 이 테스트 코드로 각각의 변환이 정상적으로 이루어지는지 확인할 수 있다.

[Reference]

- https://www.baeldung.com/mapstruct

-  https://mapstruct.org/documentation/installation/

 

Installation – MapStruct

Installation Distribution Bundle You can obtain a distribution bundle containing the MapStruct binaries, source code and API documentation from GitHub. Apache Maven If you’re using Maven to build your project add the following to your pom.xml to use MapS

mapstruct.org

 

반응형