스프링

@Mappings 사용하기

지팡구 2023. 12. 13. 15:44

[ 바로가기 목차 ]


[ 들어가기 ]

여러 테이블 혹은 DB에서 데이터를 가져와서 원하는 작업을 하는 방법에는 여러가지가 있습니다. 가져온 데이터를 원하는 형식이나 여러 객체를 하나의 객체로 합치는 일은 매우 흔한 일입니다.

이때

이러한 매핑 작업을 직접 개발자가 하게 된다면 문제가 발생할 수 있습니다.

- 코드의 중복

- 생산성 저하 

- 실수로 인한 데이터 누락

- 복잡한 로직까지 추가된다면 코드 가독성 저하  

 

 

이러한 문제를 해결하기 위해 스프링(Spring)에서는 라이브러리를 지원합니다. 

- Mapstruct

- ModelMapper

 

맵 스트럭트(MapStruct)모델 매퍼(ModelMapper)의 차이점을 간단하게 설명하자면 객체의 생성 방식에 조금의 차이를 가지고 있습니다.


모델 매퍼(ModelMapper)는 reflection으로 모델을 매핑하는데, 리플렉션은 런타임(runtime)시점에 동적으로 클래스의 정보를 추출해서 사용하기에, 성능이 그렇게 좋지 않다. (런타임 시점에 리플렉션으로 매핑이 결정되기에 실제 매핑 로직을 파악하기 어려움

 

맵 스트럭트(MapStruct)Annotation Processor를 이용해서 컴파일(compile)시점에 매핑 클래스를 생성해 만든 구현체를 런타임에 사용하기에 성능상의 이슈가 없다.

 

 


 

[ 알아보기 ]

프로젝트의 버전 및 상황에 따라 변경될 수요가 있는 코드로 예시 및 참고로만 보시길 권장합니다.

 

[ 의존성 설정 ]

gradle

buildscript {
	ext {
		mapstructVersion = '1.3.1.Final'
	}
}

...

// Mapstruct
implementation "org.mapstruct:mapstruct:${mapstructVersion}"
annotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}"
testAnnotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}"

...

compileJava {
	options.compilerArgs = [
			'-Amapstruct.suppressGeneratorTimestamp=true',
			'-Amapstruct.suppressGeneratorVersionInfoComment=true'
	]
}

 

[ 출처 : https://coding-start.tistory.com/349]

 

implementation 'org.mapstruct:mapstruct:1.4.2.Final'
annotationProcessor "org.mapstruct:mapstruct-processor:1.4.2.Final"
annotationProcessor(
        'org.projectlombok:lombok',
        'org.projectlombok:lombok-mapstruct-binding:0.1.0',
        'org.mapstruct:mapstruct-processor:1.4.2.Final'        
)

// 테스트에서 사용할 경우
//testAnnotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}"

 

[ 출처 : https://velog.io/@backtony/Spring-Mapper-Mapstruct-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0]

 

(롬복이 추가된 이유는 Dto 필드의 get method가 있어야 field와 매칭이 될 수 있다. setter는 선택적 ) 

Sample Code

@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface CarMapper {

    CarResponse toDto(Car car);

    @Mappings({
       @Mapping(target = "loginId", source = "createDto.loginId"),
       @Mapping(target = "id", ignore = true)
    })
    Car toEntity(CarRequestDto createDto, IdentityVerificationResponse identityVerification);

}

 

 

 

윗 코드에서 의존성 등록이 끝났으면 MapStruct를 사용할 수 있다. 

 

[ 어노테이션 간단 설명 ]

 

@Mapper : MapStruct를 사용하기 위한 인터페이스 정의

빌드 시  해당 어노테이션을 찾아 xxImpl 형태로 구현체를 모두 만들고, componentModel의 속성을 spring으로 주면 Impl은 스프링의 싱글톤으로 관리 (@Component)

 

@Mappings : 여러 조건을 묶기 위한 어노테이션 

 

@Mapping : 매핑에 관한 조건 설정 

- ignore  : 소스에는 있지만 타겟 무시 

- source : 변수 명이 다를 경우 매핑 설정

 

윗 코드를 빌드하게 되면 Impl 형태의 코드가 generated 폴더에 생성되는데,  이렇게 세팅을 해주면 맵스트럭트를 이용해서 객체를 간편하게 매핑 가능하다. 

( 코드는 임의로 작성한 것이라 신경쓰지 않으시면 됩니다.)

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2022-05-08T13:01:47+0900",
    comments = "version: 1.4.2.Final, compiler: javac, environment: Java 11.0.11 (AdoptOpenJDK)"
)
@Component
public class CarMapperImpl implements CarMapper {

 	@Override
    public Car to(CarDto carDto) {
        if ( carDto == null ) {
            return null;
        }

   	Car.CarBuilder car = Car.builder();

        if ( createDto != null ) {
            member.loginId( createDto.getLoginId() );
        }
        if ( identityVerification != null ) {
            car.name( identityVerification.getPhoneNumber() );
            car.color( identityVerification.getName() );
        }

        return car.build();
    }
    // ... 생략
}

 

[ 마무리 ]

 

이런 형태로 간단하게 객체를 매핑할 수 있는 장점이 있습니다.

 

덕분에 개발자의 생산성도 올라가고 잘못된 데이터를 넣을 위험도 많이 줄어들었습니다. 위에 정리한 내용 외에 다양한 속성을 지원해주니 필요에 의한 속성 사용이 권장됩니다.

 

참고 레퍼런스 https://meetup.nhncloud.com/posts/213

 

Object Mapping 어디까지 해봤니? : NHN Cloud Meetup

이 글에서는 Object Mapping 라이브러리인 MapStruct에 대해 소개합니다. NHN Forward 2019에서 발표한 내용에 대해 조금 더 자세히 설명합니다.

meetup.nhncloud.com

https://coding-start.tistory.com/349

 

Java - Model(Object) mapping을 위한 Mapstruct (맵스트럭트)!

오늘 다루어볼 내용은 Model mapping을 아주 쉽게 해주는 Mapstruct라는 라이브러리를 다루어볼 것이다. 그 전에 Model mapping에 많이 사용되는 ModelMapper와의 간단한 차이를 이야기해보면, Model Mapper는 Runt

coding-start.tistory.com

https://velog.io/@backtony/Spring-Mapper-Mapstruct-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

 

Spring Mapper - Mapstruct 사용하기

모든 코드는 Github에 있기 때문에 함께 보시면 더 이해하기 쉬우실 것 같습니다.(공부한 내용을 정리하는 Github와 이 모든 내용을 담고 있는 블로그가 있습니다. )복잡한 애플리케이션을 여러 개

velog.io