|

자바 Optional은 null을 완전히 없애줄까: 써야 할 곳과 피해야 할 곳

자바 Optional null 사용 기준 대표 이미지
자바 Optional은 null을 완전히 없애줄까를 한눈에 정리합니다.

자바 Optional은 null을 완전히 없애 주는 마법 상자가 아닙니다. 값이 없을 수 있다는 사실을 반환 타입에 드러내고, 호출자가 그 가능성을 처리하게 만드는 도구에 가깝습니다.

핵심은 Optional을 어디에 쓰느냐가 코드 품질을 결정한다는 점입니다. 반환 타입에서는 의도를 분명히 만들 수 있지만, 필드나 파라미터에 무심코 넣으면 오히려 코드가 무거워질 수 있습니다.


자바 Optional은 무엇을 표현할까

Optional은 값이 있을 수도 있고 없을 수도 있는 컨테이너입니다. 메서드가 null을 돌려줄 가능성이 있을 때, 그 사실을 타입으로 드러낼 수 있습니다.

Optional<User> findUserById(long id) {
    User user = repository.find(id);
    return Optional.ofNullable(user);
}

이 메서드를 호출하는 쪽은 결과가 없을 수 있다는 점을 무시하기 어렵습니다. 바로 이 강제성이 Optional의 장점입니다.

of, ofNullable, empty는 구분해서 써야 한다

  • Optional.of(value): value가 절대 null이 아니어야 할 때
  • Optional.ofNullable(value): value가 null일 수도 있을 때
  • Optional.empty(): 의도적으로 값이 없음을 표현할 때
Optional<String> nickname = Optional.ofNullable(user.getNickname());
String displayName = nickname.orElse("익명");

orElse와 orElseGet은 비용 차이가 날 수 있다

orElse는 대체 값을 미리 계산합니다. 반면 orElseGet은 값이 없을 때만 Supplier를 실행합니다. 대체 값을 만드는 비용이 있거나 부수 효과가 있다면 orElseGet이 더 안전합니다.

String name = userName.orElseGet(() -> loadDefaultName());

map과 flatMap은 null 체크 흐름을 줄인다

Optional을 잘 쓰면 if문을 없애는 것이 아니라, 값이 있을 때만 다음 변환을 이어 가는 흐름을 명확히 만들 수 있습니다.

String email = findUserById(id)
    .map(User::getEmail)
    .orElse("no-email@example.com");

Optional을 피하는 편이 나은 위치

  • 엔티티 필드처럼 직렬화나 ORM과 직접 맞물리는 곳
  • 메서드 파라미터처럼 호출자가 이미 값을 넘길지 말지 결정하는 곳
  • 컬렉션을 감싼 Optional, 예: Optional<List<T>>
  • 단순히 null 체크 한 줄을 감추기 위한 과도한 체이닝

정리

자바 Optional은 null을 없애는 문법이 아니라, 값 없음의 가능성을 반환 타입에 드러내는 API 설계 도구입니다. 반환 타입에는 유용하지만 필드와 파라미터에는 신중해야 합니다.

내부 글은 자바 varargs는 언제 편하고 언제 위험할까, 자바 enum은 상수 모음보다 더 강하다, 자바 람다에서 effectively final은 왜 필요할까와 함께 보면 좋습니다. 외부 기준은 Oracle Java API – Optional를 확인했습니다.

함께보면 좋은 글