ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Kotlin MapStruct 사용하기
    프로젝트/선착순 쿠폰 발급 시스템 2023. 5. 21. 00:01
    728x90

    MapStruct란?

    컴파일 시 매핑 코드를 생성하며 Java Bean 간의 매핑을 단순화하는 Java 기반 코드 생성도구입니다.

    MapStruct를 사용하면 객체 간 데이터 매핑을 위해 boilerplate code를 작성할 필요가 없어집니다.

     

    ModelMapper와의 차이점

    reflection을 사용하여 객체 간의 필드를 매핑하는 Java 기반 코드 생성도구입니다.

    컴파일 시 매핑 코드를 생성하지 않으며, reflection을 사용하기 때문에 MapStruct보다 속도가 느릴 수 있습니다.

     

    Kotlin DSL Gradle MapStruct 적용

    plugins {
    	kotlin("kapt") version "1.7.10"
    }
    
    subprojects {
    	apply(plugin = "kotlin-kapt")
    
    	dependencies {
            implementation("org.mapstruct:mapstruct:1.5.2.Final")
            kapt("org.mapstruct:mapstruct-processor:1.5.2.Final")
            kaptTest("org.mapstruct:mapstruct-processor:1.5.2.Final")
    	}
    }

     

    MapStruct 사용법

    person class와 personDto class가 존재한다고 가정해 보겠습니다.

    data class Person(
      var firstName: String?,
      var lastName: String?,
      var phoneNumber: String?,
      var birthdate: LocalDate?
    )
    data class PersonDto(
      var firstName: String?,
      var lastName: String?,
      var phone: String?,
      var birthdate: LocalDate?
    )

     

     

    person model을 personDto로 변환하는 경우 PersonMapper를 다음과 같이 정의하면 됩니다.

    @Mapper
    interface PersonMapper {
    
        @Mapping(source = "phoneNumber", target = "phone")
        fun convertToDto(person: Person) : PersonDto
    
        @InheritInverseConfiguration
        fun convertToModel(personDto: PersonDto) : Person
    }

    phoneNumber, phone과 같이 이름이 다를 경우는 Mapping 어노테이션을 이용해서 정의해주어야 합니다.

    @InheritInverseConfiguration 어노테이션은 person -> PersonDto의 역방향인 personDto -> person 매핑 코드를 생성하도록 해줍니다.

     

    Converting 하는 방법

    val converter = Mappers.getMapper(PersonMapper::class.java)
    
    val person = Person("Samuel", "Jackson", "0123 334466", LocalDate.of(1948, 12, 21))
    
    val personDto = converter.convertToDto(person)
    println(personDto)
    
    val personModel = converter.convertToModel(personDto)
    println(personModel)

    PersonMapper Interface로부터 converter를 만들어준 후 해당 메서드를 호출해 주면 변환이 자동으로 수행됩니다.

     

     

    동작 원리

     public class CarMapperImpl implements CarMapper {
    @Override
            public CarDto carToCarDto(Car car) {
                if ( car == null ) {
                    return null;
                }
                CarDto carDto = new CarDto();
                if ( car.getFeatures() != null ) {
                    carDto.setFeatures( new ArrayList<String>( car.getFeatures() ) );
                }
                carDto.setManufacturer( car.getMake() );
                carDto.setSeatCount( car.getNumberOfSeats() );
                carDto.setDriver( personToPersonDto( car.getDriver() ) );
                carDto.setPrice( String.valueOf( car.getPrice() ) );
                if ( car.getCategory() != null ) {
                    carDto.setCategory( car.getCategory().toString() );
                }
                carDto.setEngine( engineToEngineDto( car.getEngine() ) );
                return carDto;
            }
    @Override
            public PersonDto personToPersonDto(Person person) {
                //...
    }
            private EngineDto engineToEngineDto(Engine engine) {
                if ( engine == null ) {
                    return null;
                }
                EngineDto engineDto = new EngineDto();
                engineDto.setHorsePower(engine.getHorsePower());
                engineDto.setFuel(engine.getFuel());
                return engineDto;
            }
    }

    MapStruct의 일반적인 철학은 가능한 한 직접 작성한 것처럼 보이는 코드를 생성하는 것입니다. 

    특히 이것은 값이 소스에서 복사된다는 것을 의미합니다.

     

    일반 게터/세터 호출을 통해 타깃으로 값을 복사합니다.
    생성된 코드는 @Mapping을 통해 지정된 모든 이름 매핑을 고려합니다. 

    매핑된 속성의 유형이 소스 엔티티와 대상 엔티티에서 다른 경우, MapStruct는 자동 변환을 적용하거나 선택적으로 다른 매핑 메서드를 호출/생성합니다

     

     

    참고자료

    https://github.com/mapstruct/mapstruct-examples/tree/main/mapstruct-kotlin

    https://mapstruct.org

    https://mapstruct.org/documentation/stable/reference/pdf/mapstruct-reference-guide.pdf

     

    댓글

Designed by Tistory.