오류일기

Optional의 동작방식

sami355 2023. 8. 17. 17:30

현상

Data Jpa를 사용하는 환경에서 Optional<Boolean>을 반환하는 exits 메서드를 만들고 만약 DB에 중복된 값존재한다면 레포지토리 레이어에서 바로 예외를 발생시키고자 하였다.

그러나 중복된 값이 있더라도 예외는 발생하지 않았고 DDL을 통해 생성한 유니크 제약조건에 의해서 예외가 발생했다.

원인

내가 Optional문법에 대해서 정확하게 모르고 있어서 생긴 문제였다.

문제가 된 코드는 다음과 같다.

Optional<Boolean> existsByCode(String code);
userRepository.existsByCode(DTO.getCode()).orElseThrow(() -> new IllegalArgumentException("이미 존재하는 유저 코드입니다."));

Optional 문법에서 orElse 뒤에 있는 람다식이 실행될때는 Optional 객체가 감싸고 있는 객체 자체가 비어있을때 즉 null일때 이다.

이를 나의 경우에 대입하면, DB에 중복된 값이 존재하는 경우 true 가 나오게 되고 이는 Optional<Boolean>에서 Boolean이 값이 null이 아니기에 예외가 발생하지 않는 것 이다.

고치는 법

나의 경우에는 exists메서드를 사용하기 때문에 반환값은 true혹은 false 둘중 하나가 되고 null이 대입될 일은 없다. 그렇기에 exists메서드의 반환타입에서 Optional 문법을 빼고 원시타입인 boolean으로 지정해준다. 이후 해당 메서드를 통해 중복된 값을 확인할때 조건문으로 분기를 해주어 만약 중복된 값이 있다면 적절한 예외 메시지와 함께 예외를 던져주면 된다.

boolean existsByCode(String code);
if (userRepository.existsByCode(DTO.getCode())) throw new DataIntegrityViolationException("이미 존재하는 유저 코드입니다.");