Java / Spring -> Kotlin / Spring
Optional은 JDK8에서 등장한 null이 될 가능성을 가진 값을 wrapping 하기 위해 생긴 타입으로,
NPE를 피하기 위해서 Optional을 적극적으로 사용해왔다.
반면 코틀린에서는 타입 시스템에서 ? 를 활용해 null 가능성을 판단할 수 있기 때문에 Optional을 대신할 수 있다.
그러나 CrudRepository의 findById와 같은 메서드의 경우 Optional 값을 반환하고 있으므로
기존 자바 코드를 코틀린으로 변환하는 과정에서 예외 처리를 해야할 때 orElseThrow()와 같은 Optional의 메서드들에 종속되게 된다.
이처럼 Kotlin과 CrudRepository를 함께 사용할 때 이런 상황에 대비하여
스프링에서는 CrudRepositoryExtension.kt 이라는 확장함수가 담긴 파일을 제공한다.
이를 통해
기존 Optional 대신에, findByIdOrNull 함수와 Elvis 연산자를 사용하여 코틀린스럽게 null 처리가 가능하다.
기존 코틀린 코드
@Transactional
fun updateUserName(request: UserUpdateRequest) {
val user = userRepository.findById(request.id).orElseThrow(::IllegalArgumentException)
user.updateName(request.name)
}
개선 후 코틀린 코드
@Transactional
fun updateUserName(request: UserUpdateRequest) {
val user = userRepository.findByIdOrNull(request.id) ?: throw IllegalArgumentException()
user.updateName(request.name)
}
여기서 더 나아가서
CrudRepository 인터페이스에 findByIdOrThrow라는 새로운 기능을 추가는 형태로 확장 함수를 만들어 사용할 수 있다. CrudRepository의 findByIdOrNull(id)는 null을 반환할 수 있는 반면, findByIdOrThrow(id)는 존재하지 않으면 즉시 예외를 던지도록 커스터마이징하였다.
fun <T, ID> CrudRepository<T, ID>.findByIdOrThrow(id: ID): T {
return this.findByIdOrNull(id) ?: throw IllegalArgumentException()
}
@Transactional
fun updateUserName(request: UserUpdateRequest) {
val user = userRepository.findByIdOrThrow(request.id)
user.updateName(request.name)
}
이렇게 코드를 수정하면, 보다 간결해지고 어떤 도메인의 Repository 이건 findByIdOrThrow 를 사용해 자주 사용하는 예외처리 패턴을 간편하게 재사용할 수 있다는 장점이 있다.
아래와 같이 지금까지의 코드 변천사 과정을 정리해 보았다
'SpringBoot' 카테고리의 다른 글
Redis 캐싱을 사용하여, 일일 조회수와 좋아요 증감 수를 반영한 일일 HOT 상품 목록 조회 기능 개발 (0) | 2024.12.19 |
---|---|
비효율적인 상품 상세 검색 코드 수정과 nGrinder를 활용한 성능 테스트 (0) | 2024.11.12 |
Spring Boot와 Kafka 테스트: Embedded Kafka로 상품 좋아요 메시지 검증하기 (1) | 2024.10.13 |
MSA) 서비스 별 각 인스턴스에서 애플리케이션을 Docker 컨테이너화 후, 발생한 Eureka Client 간의 통신 문제 (0) | 2024.07.09 |
MSA) Spring Cloud 기반의 MSA 구조에서 Swagger 통합하기 + FastAPI의 Swagger까지 (0) | 2024.06.17 |