본문 바로가기
Java

[Java] 자바에서 Optional의 올바른 사용법

by 긍고 2024. 9. 24.
반응형

개요


개발을 하면서 가장 많이 만나는 예외 중 하나가 NullPointerException(NPE)이다. 특히 객체가 null일 때 이를 처리하지 않고 사용하면 프로그램이 예기치 않게 종료될 수 있다. 최근에 내가 작업하던 프로젝트에서도 이런 상황을 여러 번 마주쳤다. 이를 해결하기 위해 Optional을 활용해 NPE를 방지하고자 했지만, Optional의 잘못된 사용법을 보고 오히려 코드가 복잡해지는 경우도 경험했다. 그래서 이번 글에서는 자바의 Optional을 올바르게 사용하는 방법과 피해야 할 안티패턴을 설명하고자 한다.

 

Optional이란 무엇인가?


 

Optional은 자바 8에서 추가된 클래스다. 이 클래스는 값이 있을 수도 없을 수도 있는 객체를 감싸서 NPE를 방지하는 역할을 한다. 기본적으로 Optional은 두 가지 상태를 가질 수 있다:

  • 값이 존재하는 상태 (Optional.of(), Optional.ofNullable() 사용)
  • 값이 없는 상태 (Optional.empty() 사용)

이를 통해 객체가 null인지 여부를 명시적으로 확인하고, NPE가 발생하지 않도록 안전하게 코드를 작성할 수 있다.

 

Optional로 NPE 방지하기


Optional을 사용하면 값이 없는 경우를 깔끔하게 처리할 수 있다. 특히 if (obj != null)과 같은 반복적인 null 체크 코드를 없앨 수 있다.

public String getUsername(User user) {
    return Optional.ofNullable(user)
                   .map(User::getName)
                   .orElse("Unknown");
}

위 코드에서 user가 null일 때도 NPE가 발생하지 않고, "Unknown"을 반환하게 된다. Optional.ofNullable()을 사용하여 null을 감싸주고, 값이 있을 경우 map()으로 변환하며, 없을 경우 orElse()로 기본값을 반환한다.

 

Optional 사용 시 안티패턴


Optional은 유용하지만, 잘못 사용하면 오히려 코드가 더 복잡해지고 성능 문제를 일으킬 수 있다. 대표적인 안티패턴은 다음과 같다:

 

Optional을 필드로 사용하는 것

Optional은 필드로 사용해서는 안 된다. 이는 불필요한 래핑과 메모리 사용을 초래하며, 직렬화 과정에서도 문제가 생길 수 있다.

public class User {
    // 나쁜 예: 필드에 Optional 사용
    private Optional<String> name;
}

대신 필드는 null로 처리하고, getter에서 Optional을 반환하는 방식이 더 적절하다.

public class User {
    private String name;

    public Optional<String> getName() {
        return Optional.ofNullable(name);
    }
}

 

get() 메서드의 남용

Optional.get()은 값을 무조건 반환하는 메서드인데, 값이 없을 경우 NoSuchElementException을 발생시킨다. 따라서 가능한 사용을 피하고, 항상 안전한 방법으로 값을 추출해야 한다.

Optional<String> name = Optional.ofNullable(user.getName());
// 나쁜 예: get() 사용
String result = name.get(); // 값이 없으면 예외 발생

 

올바른 Optional 사용법 예제


Optional을 사용할 때는 항상 안전한 방법으로 값에 접근하고, 기본값을 설정하는 것이 중요하다. 아래는 적절한 예제이다:

public String getUserEmail(User user) {
    return Optional.ofNullable(user)
                   .map(User::getEmail)
                   .orElseThrow(() -> new IllegalArgumentException("사용자 이메일을 찾을 수 없습니다."));
}

이 코드는 user가 null이 아니면 이메일을 반환하고, 값이 없으면 커스텀 예외를 발생시킨다. orElseThrow()는 필요한 경우 명시적으로 예외를 던질 수 있어, 잘못된 상태를 빠르게 파악하는 데 도움이 된다.

 

정리


자바의 Optional은 NullPointerException을 방지하는 데 유용한 도구이다. 하지만 잘못 사용하면 코드가 복잡해지고 성능이 저하될 수 있다. 필드에 Optional을 사용하지 말고, 값을 추출할 때는 get() 대신 orElse(), orElseGet(), orElseThrow() 등을 활용하는 것이 좋다. 올바른 방법으로 Optional을 사용하면 더 안전하고 가독성 높은 코드를 작성할 수 있다.

댓글