Optional

sungs·2025년 6월 27일

자바

목록 보기
22/95

💡 Optional이란?

Optional은 Java 8부터 추가된 null을 명시적으로 다루기 위한 컨테이너 클래스다.
즉, 값이 있을 수도 있고 없을 수도 있는 객체를 감싸서 NullPointerException을 방지하고, 더 읽기 쉬운 코드를 만들 수 있도록 도와준다.

가장 큰 장점이 이 값이 값이 있을 수도 있고, 없을 수도 있다는 걸 명시적으로 보여준다는 점이다. 그렇게 함으로써 NullPointerException을 방지할 수 있다. 다만, 반드시 값이 있는 경우에는 쓰지 말아야 한다.

Optional<String> name = Optional.of("철수");

🧩 Optional 생성 방법

1. Optional.of(T value)

  • 값이 절대 null이 아니라고 확신할 때 사용

  • 만약 null을 넣으면 예외 발생

Optional<String> name = Optional.of("홍길동"); // ✅
Optional<String> name = Optional.of(null);    // ❌ NullPointerException

2. Optional.ofNullable(T value)

  • 값이 null일 수도 있을 때 안전하게 사용
Optional<String> name = Optional.ofNullable(null); // ✅ 빈 Optional 생성

3. Optional.empty()

  • 명시적으로 빈 Optional을 만들 때 사용
Optional<String> empty = Optional.empty();

🔍 Optional 값 가져오기

Optional<String> name = Optional.of("철수");
메서드설명
get()값을 가져옴 (값이 없으면 예외 발생), 잘 사용하지 않음. 주로 orElse나 orElseXxx를 사용함
isPresent()값이 존재하면 true
orElse(T other)값이 없으면 다른 기본값 반환
orElseGet(Supplier)값이 없으면 함수 실행 후 반환
orElseThrow()값이 없으면 예외 발생
or(Supplier<? extends Optional<? extends T>> supplier)값이 없으면 Supplier가 제공하는 다른 Optional을 반환. 있어도 그 값의 Optional로 반환.

✅ 예시:

Optional<String> name = Optional.ofNullable(null);

// 1. 기본값 제공
String result = name.orElse("기본값");

// 2. 값이 있으면 출력
name.ifPresent(System.out::println);

// 3. 값이 없으면 예외 발생
name.orElseThrow(() -> new IllegalArgumentException("값이 없음"));

orElse와 orElseGet의 차이

둘의 가장 큰 차이는 orElse는 즉시 평가, orElseGet은 지연 평가라는 점이다. orElse는 즉시 평가라서 메서드가 호출되기 전에 괄호 안의 값이 먼저 평가되지만, orElseGet은 람다를 사용하기 때문에 지연 평가가 되어 그 값이 필요할 때까지 실행되지 않아 불필요한 연산을 사용하지 않을 수 있다. 따라서 간단한 대체 값이 쓰일 경우에는 orElse가 맞지만, 복잡한 로직 등의 상대벅으로 무거운 대체값이 쓰이거나 대체로 값이 있을 경우에는 orElseGet을 쓰는 게 맞다.

Optional 값 처리

메서드설명
ifPresent(Consumer<? super T> action)값이 있을 때만 action 실행
ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)값이 있으면 action, 없으면 emptyAction 실행
map(Function<? super T, ? extends U> mapper)있으면 변환해서 Optinal로 반환, 없으면 empty 반환
flatMap(Function<? super T, ? extends Optional<? extends U>> mapper)map과 유사하지만, 반환할 때 평탄화해서 반환
filter(Predicate<? super T> predicate)값이 조건에 만족하면 그대로 반환, 없거나 조건에 만족하지 않으면 empty 반환
stream()있으면 단일 요소 스트림 반환, 없으면 빈 스트림 반환

🛠 Optional의 활용 예시

1. null 체크 대체

// 기존 방식
if (user != null && user.getName() != null) {
    System.out.println(user.getName());
}

// Optional 사용
Optional.ofNullable(user)
        .map(User::getName)
        .ifPresent(System.out::println);

2. 메서드 반환값 처리

public Optional<User> findUser(String id) {
    return Optional.ofNullable(userRepository.get(id));
}

⚠️ Optional 사용 시 주의할 점

  • 필드로 사용 금지: Optional은 주로 리턴 타입으로 사용하는 것이 권장된다. 필드나 파라미터에는 사용하지 않는 게 좋다.

  • 성능 민감 구간에서는 자제: 불필요한 객체 생성이 있기 때문에 성능이 중요한 곳에서는 사용을 피하는 것이 좋다.

  • Optional.get()은 지양: 값이 없을 때 예외를 던지므로 get()보다 orElse, ifPresent, orElseThrow 등을 활용해야 한다.

✅ 결론

Optional은 null 안전성과 가독성을 높여주는 강력한 도구다. 단, 무분별하게 사용하기보다는 반환 값 처리용으로만 국한해서 사용하는 것이 바람직하다.

profile
앱 개발 공부 중

0개의 댓글