공공부하자개발 · 영어 학습 노트
자바
고급모던 자바와 성능0/10 완료
  • 01제네릭과 와일드카드
  • 02멀티스레드와 동기화
  • 03람다식과 함수형 인터페이스
  • 04Stream API와 병렬 처리
  • 05Optional로 NPE 방지
  • 06메서드 활용 패턴 (고급)
  • 07Java 21 모던 문법
  • 08어노테이션·리플렉션·동적 프록시
  • 09CompletableFuture 심화와 가상 스레드 실전
  • 10JVM 메모리·GC·OOM 진단
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 고급 › 05 / 10

Optional로 NPE 방지

섹션 7진행 0 / 10
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6연습 문제7정리‹ 이전다음 ›

5. 자주 하는 실수 (Tip)

❌ 실수 1: isPresent() + get()

java
Optional<User> u = repo.findById(id);
if (u.isPresent()) {
    return u.get().name();
}
return "unknown";

if (x != null) x.name() 과 완전히 같은 구조입니다. Optional 객체만 하나 더 만들었을 뿐 null 검사를 잊을 위험이 그대로입니다.

java
✅
return repo.findById(id).map(User::name).orElse("unknown");

❌ 실수 2: orElse 에 비싼 연산

java
User u = cache.find(id).orElse(db.load(id));   // 캐시에 있어도 DB 를 항상 조회!

메서드 인자는 호출 전에 평가됩니다(2.5). 캐시 히트율이 99% 여도 DB 부하는 100% 입니다.

java
✅
User u = cache.find(id).orElseGet(() -> db.load(id));

❌ 실수 3: 필드 / 파라미터에 Optional

java
class User {
    private Optional<String> nickname;                    // 직렬화 불가, 필드가 null 일 수도 있음
    void setNickname(Optional<String> nick) { ... }       // 호출자가 Optional.ofNullable 로 감싸야 함
}
java
✅
class User {
    private String nickname;                              // nullable 필드
    Optional<String> nickname() { return Optional.ofNullable(nickname); }   // getter 에서만 Optional
    void setNickname(String nick) { this.nickname = nick; }
}

❌ 실수 4: 컬렉션을 Optional 로 감싸기

java
Optional<List<Order>> findOrders(long userId) {
    List<Order> list = query(userId);
    return list.isEmpty() ? Optional.empty() : Optional.of(list);
}

빈 리스트가 이미 "없음"입니다. 호출자는 orElse(List.of()) 를 붙여야 해서 오히려 불편해집니다.

java
✅
List<Order> findOrders(long userId) { return query(userId); }   // 없으면 빈 리스트

❌ 실수 5: Optional.of 에 nullable 값

java
Optional<String> email = Optional.of(user.getEmail());   // getEmail 이 null 이면 NPE

of 는 "절대 null 아님" 단언입니다. 외부에서 온 값은 ofNullable.

java
✅
Optional<String> email = Optional.ofNullable(user.getEmail());

❌ 실수 6: get() 무방비 호출

java
Order biggest = orders.stream().max(comparing(Order::amount)).get();   // 빈 스트림이면 NoSuchElementException

NoSuchElementException 은 이름만 다른 NPE 입니다.

java
✅
Order biggest = orders.stream().max(comparing(Order::amount))
    .orElseThrow(() -> new IllegalStateException("주문이 없습니다"));

❌ 실수 7: 모든 반환 타입을 Optional 로

java
Optional<Boolean> isAdmin(User u)          // Boolean 은 이미 두 값. 세 번째 상태가 필요한가?
Optional<Integer> count()                  // 0 이 "없음"이다

Optional 은 "값이 존재하지 않을 수 있는 조회" 에만. 항상 값이 있는 계산, 컬렉션, boolean, 카운트에는 쓰지 않습니다.

java
✅
boolean isAdmin(User u)
int count()
자주 하는 실수 (Tip)
  • ❌ 실수 1: isPresent() + get()
  • ❌ 실수 2: orElse 에 비싼 연산
  • ❌ 실수 3: 필드 / 파라미터에 Optional
  • ❌ 실수 4: 컬렉션을 Optional 로 감싸기
  • ❌ 실수 5: Optional.of 에 nullable 값
  • ❌ 실수 6: get() 무방비 호출
  • ❌ 실수 7: 모든 반환 타입을 Optional 로
이전 섹션4 응용 변형 예제5 / 7다음 섹션6 연습 문제