일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- minikube
- Pinpoint
- aws
- APM
- Linux
- IntelliJ
- 오블완
- Kubernetes
- kotlin coroutine
- mysql 튜닝
- Spring
- 정보처리기사실기 기출문제
- Elasticsearch
- PETERICA
- 정보처리기사 실기 기출문제
- kotlin querydsl
- 티스토리챌린지
- AWS EKS
- kotlin spring
- 기록으로 실력을 쌓자
- CKA
- 코틀린 코루틴의 정석
- 공부
- AI
- kotlin
- MySQL
- Java
- CloudWatch
- 정보처리기사 실기
- CKA 기출문제
- Today
- Total
피터의 개발이야기
[Kotlin] Spring에 MapStruct와 Lombok을 함께 사용할 때 isCompleted 필드가 null로 넘어오는 문제 본문
[Kotlin] Spring에 MapStruct와 Lombok을 함께 사용할 때 isCompleted 필드가 null로 넘어오는 문제
기록하는 백앤드개발자 2024. 7. 19. 10:10
ㅁ 들어가며
ㅇ Kotlin Spring 프로젝트에서 MapStruct와 Lombok을 사용할 때 isCompleted가 null로 넘어오는 문제가 발생하였다.
ㅇ 이를 해결하면서 Lombok과 MapStruct의 충돌에 대해서 알게 되어 이를 정리하였다.
ㅇ 우선 나의 문제와 해결방법을 정리하고, 원인을 분석하는 과정에 다른 글에서 null일 수 있는 경우도 정리하였다.
ㅁ 문제상황
ㅇ reqDto.isComplated가 swagger에 보이지 않음.
ㅇ MapStruct 구현부에서 isComplated가 entity로부터 값을 set받지 못하여 null.
ㅇ resDto.isComplated이 결과 JSON에서 아예 키까지 빠져있음.
// RequestDto: Swagger에서 나타나지 않음
val isComplated: String
// entity: snake case에서 camelcase 형태로 선언되었고, Y/N으로 값이 입력된다.
@Column(name = "is_complated")
val isComplated: String
// QueryDSL 데이터 조회
val products =
jpaQueryFactory.selectFrom(product)
.where(
product.name.like("p%"),
)
.fetch()
// mapstruct로 변환
products.map {
productsMapper.entityToResponseDto(it)
}
// ResponseDto: null로 세팅된다.
val isComplated: String
ㅇ 처음 문제점을 인식한건 isComplated가 ResDto에 결과가 null이 아닌 key 자체가 없는 점이었다.
ㅇ 누락 또는 오타로 문제점을 파악했지만, 아키덱트 내부의 문제점으로 파악해 나아갔다.
ㅇ 더욱이 ReqDto에서도 isComplated가 Swagger에서 표출되지도 않았다.
ㅇ 무엇인가 구조상 버그가 틀림없어 보였다.
ㅁ 해결 방법
// entity 수정
@Column(name = "is_complated")
val complatedYn: String
// req, res도 수정
val complatedYn: String
ㅇ isComplated는 Boolean타입으로 오인할 수 있는 형태여서, 명확한 complatedYn으로 변경하였다.
ㅇ 문제가 되었던 reqDto, resDto에 값이 잘 전달되었다.
ㅇ 원인이 무엇인지 Searching을 하였다.
ㅁ 분석을 위한 Searching과 내용정리
ㅇ Lombok의 동작 방식 <+++ 나의 경우 핵심 원인
For boolean fields that start with is immediately followed by a title-case letter, nothing is prefixed to generate the getter name.
Any variation on boolean will not result in using the is prefix instead of the get prefix; for example, returning java.lang.Boolean results in a get prefix, not an is prefix.
- Lombok의 공식 문서의 내용이다.
- Lombok은 boolean 타입 필드에 대해 'is' 접두사를 사용한 getter를 생성한다.
- 예를 들어, isCompleted()와 같은 형태다.
ㅇ Jackson의 동작 방식
Jackson은 기본적으로 getter 메서드의 이름을 기반으로 JSON 필드 이름을 결정한다. boolean 타입의 경우, 'is' 접두사를 제거하고 첫 글자를 소문자로 바꾼다.
참조 블로그 다른 내용 요약
- Spring 의 Json Message Converter 는 Jackson라이브러리를 사용
- lombok 의 Getter 는 필드명 맨 앞을 항상 대문자로 만듬
- Jackson 라이브러리는 Getter 의 맨 앞 두글자가 전부 대문자인 경우 필드명과 Json key 값이 달라짐
- aCount 라는 필드명을 lombok 을 사용해서 Getter 를 만들면 getACount() 가 되기 때문에 이슈가 발생
[참조] Spring Request DTO 에 null 값이 들어가는 이유 (Jackson, Lombok)
ㅇ MapStruct와 Lombok의 충돌
- Lombok 라이브러리에 먼저 dependency (의존성) 추가가 되어있어야 한다.
- MapStruct는 Lombok의 getter, setter, builder를 이용하여 생성된다.
- 그래서 MapStruct와 Lombok은 빌드과정 중에 생성 순서에 따라 MapStruct가 "Unknown property" 오류가 발생할 수 있다.
- 이를 방지 하기 위해서는 MapStruct와 Lombok을 함께 사용할 때는 버전 호환성, 처리 순서, 그리고 필요한 추가 의존성을 고려해야 한다.
ㄴ Maven의 annotationProcessorPaths에 Lombok 추가
ㄴ MapStruct와 Lombok의 처리 순서 조정 (Lombok을 먼저 처리)
ㄴ lombok-mapstruct-binding 의존성 추가 (Lombok 1.18.16 이상 버전에서 필요)
ㄴ MapStruct와 Lombok 버전 호환성 확인
[참조] MapStruct + Lombok together not compiling: unknown property in result type
[참조] 편리한 객체 간 매핑을 위한 MapStruct 적용기 (feat. SENS)
ㅁ 마무리
isCompleted가 null로 넘어오는 문제는 주로 Lombok, MapStruct, 그리고 Jackson의 상호작용으로 인해 발생한다. 이를 해결하면서 각 라이브러리의 동작 방식을 이해하고, 적절한 어노테이션이나 설정 방법을 잘 이해하고 사용해야 함을 배우게 되었다.
ㅁ 함께 보면 좋은 사이트
ㅇ 편리한 객체 간 매핑을 위한 MapStruct 적용기 (feat. SENS)
ㅇ MapStruct + Lombok together not compiling: unknown property in result type
ㅇ [Java] Lombok에서 boolean타입 프로퍼티에 대한 get,set
'Programming > Kotlin' 카테고리의 다른 글
[Kotlin] Entity list에서 id 추출하기 (0) | 2024.07.22 |
---|---|
[Kotlin] QueryDSL java.lang.NoSuchFieldError: TREATED_PATH (0) | 2024.07.20 |
[Kotlin] Kotlin으로 Shell 유틸리티 만들기: 파일 복사와 압축 (1) | 2024.07.18 |
[Kotlin] kotlin에서 shell 실행하기 (0) | 2024.07.17 |
[Kotlin] QueryDSL에서 YYYY-MM로 검색하기 (1) | 2024.07.16 |