[JPA] 잘못된 표현: Optional<List<T>>

현수·2022년 3월 5일
0

Java Spring에서 Service 계층 개발 중 잘못 된 표현으로 개발한 경험을 공유하려고한다.

구현하려했던 기능

Spring Data JPA는 JpaRepository 상속받아서 Interface로 CRUD를 매우 간단하게 구현할 수 있다.

그 중 기본 제공 메소드인 findById()는 DB 속에서 인자로 넘긴 PK에 해당하는 객체를 반환하고 반환 타입은 Optional로 반환한다.

그렇기 때문에 만약 DB에서 PK에 해당하는 객체를 찾지 못할 경우 Optional 객체를 활용하여 orElseThrow() 메소드로 예외처리를 쉽게 할 수 있다.

그리고 나는 이러한 Optional 기능을 활용하면서 여러 포스트 엔티티를 불러오고 싶어서 Repository를 아래와 같이 작성했다.

// Repository
public interface PostRepository extends JpaRepository<PostEntity, Integer> {
	// 작성자 UID가 작성한 모든 포스트 불러오기
    Optional<List<PostEntity>> findByAuthorId(Integer author_id);
}
// Service
List<PostEntity> result = this.postRepo.findByAuthorId(authorId)
			// 찾지 못할 경우 "포스트 없음" 예외 처리
			.orElseThrow(()-> new CustomException(POST_NOT_FOUND));

이러면 List<PostEntity> 로 여러 포스트를 불러오면서 Optional 기능이 적용되어 orElseThrow() 를 이용한 예외처리를 쉽게 할 수 있을 줄 알았다.

실패

그 결과 Post 불러오기 기능은 잘 동작하였으나 잘못된 값을 넘겨주었을 때 예외처리는 잘 작동하지 않았다.

예외처리가 동작하면 POST_NOT_FOUND 출력해야하는데 빈 List를 반환했다.

이유가 무엇일지 조사하던 중 Stackoverflow에서 답을 찾았다.

원인

이 분도 나와 같이 리스트를 Optional로 사용하려했던 것 같다. 근데 잘 안됐나보다.

답변으로 위 방식은 말이 안된다고 아래와 같이 써야한다고 한다.

생각해보니 Optional은 null이 발생했을 경우 NPE가 발생하는 것이 아니라 다양한 메소드로 처리할 수 있게 하는 객체이다.

그런데 Optional<List<T>> 형식으로 쓰게 되면 Optional 제네릭 안에 있는 List<T> 는 리스트가 비어도 빈 리스트를 반환하지 null이 절대로 될 수 없다.

고로 Optional<List<T>> 는 절대로 null이 발생할 수 없으니 예외 처리를 할 수 없었던 것이다.

해결

그래서 나도 List를 Optional로 예외처리하는 것은 포기하고 일반 List 객체에서 빈 리스트가 발생할 경우 If 문으로 예외처리하는 것으로 문제를 해결했다.

// Repository
public interface PostRepository extends JpaRepository<PostEntity, Integer> {
	// 작성자 UID가 작성한 모든 포스트 불러오기
	List<PostEntity> findByAuthorId(Integer author_id);
}
// service
List<PostEntity> posts = this.postRepo.findByAuthorId(authorId);
	if (posts == null || posts.isEmpty())
    	// 찾지 못할 경우 "포스트 없음" 예외 처리
		throw new CustomException(POST_NOT_FOUND);

참고자료

https://stackoverflow.com/questions/52185052/optionallistt-for-empty-list-in-repository-layer-returns-optional-empty-ho

2개의 댓글

comment-user-thumbnail
2023년 4월 9일

같은 문제에 직면했는데 덕분에 많은 참고가 됐습니다.감사합니다!

답글 달기
comment-user-thumbnail
2023년 8월 8일

동일한 고민중이었는데 감사합니다.

답글 달기