본문 바로가기
개발 지식/Kotlin

[Mapstruct] Protobuf repeated와 Kotlin List 매핑이 되지 않는 문제

by 에르주 2023. 1. 9.
반응형

개발하면서 약 일주일간의 삽질을 통해 해결했던 경험을 쓰려고 한다. 

결론부터 이야기하자면 protobuf repeated와 코틀린 프로퍼티 또는 자바 객체간 변환을 mapstruct로는 완벽히 커버할 수 없으며 추가 라이브러리(https://github.com/entur/mapstruct-spi-protobuf)를 설정해야 한다.

 

최초 문제:

protobuf와 kotlin 객체변환을 위해 mapstruct를 활용하고자 하였다. (보일러플레이트 코드를 지양하기 위해서) 그래서  다음과 같은 proto, kt를 작성하였다. 

 

 

base.proto

message BaseResponse {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
  string baseId = 4;
  string baseName = 5;
  string baseNumber = 6;
  repeated string baseList = 7;
  repeated CarList cars = 8;

}

message CarList{
  string name = 1;
  string madeYear = 2;
}

 

baseDto.kt

class BaseDTO(

    val id: Any?,
    val baseId: String,
    val baseName: String,
    var baseNumber: String,
    var baseList : List<String>,
    var carList: List<Car>,
) {

    class Car(
        var name: String,
        var madeYear: String,
    )

}

 

baseMapper.kt

@Mapper
interface BaseMapper {
    fun toBaseGrpcStream(baseDTO: BaseDTO) : BaseResponse
}

각각의 프로퍼티 값이 proto 변수값과 매핑되는 것을 원했다

 

 

 

하지만 genereate시에 해당 리스트값에 대한 mapping은 진행되지 않는 것을 확인 하였다.

매핑이 되지 않았다.

 

원인 :

repeated string을 compile시에 ProtocolStringList로 변환된다.하지만 kotlin에서는 protocolStringList를 List<String>으로 인식하지 못하여 제대로 매핑이 되지 않았다.
→ 1.3.0 beta 버전 이후에 조치 되었다고 하는데 위의 프로젝트에서 1.5.2.Final 버전을 쓰고 있는데도 Mapping 되지 않는 것을 보면 아직 작업이 완벽히 되지 않은 것 같다. (https://github.com/mapstruct/mapstruct/issues/1338)

 

 

또한 repeated baseList or carList를  complie시 네이밍이 baseListlist or carListlist(xxxlist)로 변환되어 kotlin의 List<Image> ko의 변수명과 맞지 않아 제대로 매핑이 되지 않았다.

결론적으로 mapstruct를 활용하여 protobuf의 완벽한 mapping은 아직이다

 

 

해결법 :

1) Mapstruct mapper 설정을 통해 list 하나 하나 매핑해야 한다.

2) https://github.com/entur/mapstruct-spi-protobuf 오픈 소스를 활용하여 해결 

  • Mapper 설정에 CollectionMappingStrategy.ADDER_PREFERRED 추가
    → 옵션 내용 : 기존 Target 객체의 컬렉션 객체를 유지한 채로 새로운 데이터 추가 및 업데이트 진행
  • implementation("no.entur.mapstruct.spi:protobuf-spi-impl:1.41") 추가

 

 

나는 1번과 2번 중 2번 설정을 진행 한 후 compile시 다음과 같이 정상적으로 매핑되는 것을 확인할 수 있었다.

매핑 됌

 

끝.

반응형

댓글