Contents
📦 개념 요약📦 개념 요약
Optional<T>
은 null로 인한 예외를 방지하고, 명시적으로 값 유무를 처리할 수 있는 컨테이너 클래스
- 흔히
null
체크에 사용되던 코드를 더 명확하고 선언적으로 바꾸어줌
- 비유하자면, "선물 상자에 값이 들어있을 수도, 없을 수도 있다"
🧪 테스트 예제
public class OptionalTest {
@Test
public void t1() {
String name = "metacoding";
Optional<String> opt = Optional.of(name);
System.out.println(opt.get()); // metacoding 출력
}
@Test
public void t1_null() {
String name = null;
Optional<String> opt = Optional.ofNullable(name);
if (opt.isPresent()) {
System.out.println(opt.get());
} else {
System.out.println("선물박스에 값이 없어요");
}
}
@Test
public void t2() {
String name = null;
Optional<String> opt = Optional.ofNullable(name);
String result = opt.orElseThrow(() -> new RuntimeException("값이 없어요"));
System.out.println(result);
}
@Test
public void t3() {
String name = null;
Optional<String> opt = Optional.ofNullable(name);
String result = opt.orElseGet(() -> "metacoding"); // 기본값 리턴
System.out.println(result); // metacoding
}
}
💡 Optional.of()는 null을 허용하지 않음.💡Optional.ofNullable()
은 null 허용 (값 없으면 empty).💡orElseThrow()
는 값 없을 때 예외 발생.💡orElseGet()
은 값 없을 때 기본값 제공.
🔁 기존 코드 vs Optional 적용
📍 Before: null 체크 수동 처리
public User findById(Integer id) {
User user = em.find(User.class, id);
if (user == null) {
return null;
} else {
return user;
}
}
✅ After: Optional 적용
public Optional<User> findById(Integer id) {
return Optional.ofNullable(em.find(User.class, id));
}
📌 서비스 계층 적용 예시
❌ Before
User userPS = userRepository.findById(userId);
if (userPS == null) throw new Exception404("자원을 찾을 수 없습니다");
userPS.update(updateDTO.getPassword(), updateDTO.getEmail());
✅ After
User userPS = userRepository.findById(userId)
.orElseThrow(() -> new Exception404("자원을 찾을 수 없습니다."));
userPS.update(updateDTO.getPassword(), updateDTO.getEmail());
👤 로그인 기능 개선
❌ Before
User user = userRepository.findByUsername(loginDTO.getUsername());
if (user == null) throw new Exception401("유저네임 혹은 비밀번호가 틀렸습니다");
✅ After
User userPS = userRepository.findByUsername(loginDTO.getUsername())
.orElseThrow(() -> new Exception401("유저네임 혹은 비밀번호가 틀렸습니다"));
✅ 유저네임 중복 체크
❌ Before
User user = userRepository.findByUsername(username);
Map<String, Object> dto = new HashMap<>();
if (user == null) {
dto.put("available", true);
} else {
dto.put("available", false);
}
✅ After
Optional<User> userOP = userRepository.findByUsername(username);
Map<String, Object> dto = new HashMap<>();
if (userOP.isPresent()) {
dto.put("available", false);
} else {
dto.put("available", true);
}
return dto;
}
✨ 정리
메서드 | 설명 |
Optional.of() | null 허용 ❌ (NPE 발생) |
Optional.ofNullable() | null 허용 ⭕ |
isPresent() | 값 존재 여부 확인 |
orElse() | 기본값 제공 |
orElseGet() | 람다식으로 기본값 제공 |
orElseThrow() | 예외 발생 |
Share article