티스토리 뷰
Java의 Optional을 사용하면 null 체크를 명시적으로 하지 않고도 안전하게 값을 다룰 수 있습니다. 특히 체이닝(chaining) 기법을 통해 여러 단계의 연산을 한 줄로 연결할 수 있어 가독성이 좋고 오류 가능성을 줄일 수 있습니다. 아래에서 Optional 체인을 어떻게 사용하는지에 대해 자세히 설명하겠습니다.
1. 기본 사용법
Optional은 주로 메서드의 리턴값으로 사용되어, 반환값이 null일 가능성이 있을 때 클라이언트가 안전하게 처리할 수 있도록 도와줍니다. 예를 들어:
public Optional<User> findUserById(Long id) {
// DB나 다른 소스에서 User를 조회한다고 가정
User user = ...; // 조회된 user 혹은 null
return Optional.ofNullable(user);
}
이렇게 반환된 Optional을 클라이언트에서 아래와 같이 사용할 수 있습니다.
Optional<User> optionalUser = findUserById(1L);
optionalUser.ifPresent(user -> {
// user가 존재하는 경우 실행
System.out.println("User name: " + user.getName());
});
2. 체이닝을 이용한 연산
Optional의 여러 메서드(map, flatMap, filter 등)를 이용하여 연속적인 연산을 수행할 수 있습니다. 이를 체이닝이라고 합니다.
2.1. map 사용하기
map은 Optional 내부의 값을 다른 값으로 변환할 때 사용합니다. 예를 들어, User 객체에서 이름을 추출하는 경우:
Optional<String> userName = findUserById(1L)
.map(User::getName);
위 코드에서 findUserById(1L)이 빈 Optional일 경우, 이후의 map 연산은 수행되지 않고 최종 결과는 빈 Optional이 됩니다.
2.2. flatMap 사용하기
flatMap은 내부에서 또 다른 Optional을 반환하는 경우에 사용합니다. 예를 들어, User 객체에서 Address 객체를 Optional로 반환하는 메서드가 있다고 가정하면:
public Optional<Address> getAddress() {
return Optional.ofNullable(address);
}
이를 체인으로 연결하면:
Optional<String> city = findUserById(1L)
.flatMap(User::getAddress) // User -> Optional<Address>
.map(Address::getCity); // Address -> city (String)
이처럼 flatMap을 사용하면 Optional이 중첩되는 문제를 피할 수 있습니다.
2.3. filter 사용하기
filter는 Optional 내부의 값을 조건에 따라 걸러내는 역할을 합니다. 예를 들어, 특정 조건을 만족하는 User만 처리하고 싶을 때:
Optional<User> adultUser = findUserById(1L)
.filter(user -> user.getAge() >= 18);
조건을 만족하지 않으면 최종 Optional은 빈 값이 됩니다.
2.4. 최종 결과값 처리
체이닝된 Optional의 결과값을 얻거나 기본값을 지정할 때는 아래 메서드들을 사용합니다.
- orElse(T other): Optional이 비어있을 경우 다른 값을 반환합니다.
- orElseGet(Supplier<? extends T> supplier): Optional이 비어있을 경우 Supplier에서 제공하는 값을 반환합니다.
- orElseThrow(): Optional이 비어있으면 예외를 던집니다.
예시:
String name = findUserById(1L)
.map(User::getName)
.orElse("Default Name");
User user = findUserById(1L)
.orElseThrow(() -> new IllegalArgumentException("User not found"));
3. 실전 예제
실제 Spring Boot 애플리케이션에서 Optional 체인을 사용한 예제입니다. 예를 들어, 게시글(Post) 객체에서 작성자(User) 정보를 가져오고, 작성자의 이메일을 추출하는 경우:
// Post 엔티티
public class Post {
private User author;
// getter, setter 등
}
// User 엔티티
public class User {
private String email;
// getter, setter 등
}
// 서비스 레이어에서 Optional 체인 사용
public String getAuthorEmail(Long postId) {
return findPostById(postId) // Optional<Post> 반환
.map(Post::getAuthor) // Optional<User>로 변환
.map(User::getEmail) // Optional<String>로 변환
.orElse("no-email@example.com");
}
public Optional<Post> findPostById(Long postId) {
// DB 조회 로직 (예: JPA Repository 사용)
Post post = ...; // 게시글 조회
return Optional.ofNullable(post);
}
이 코드는 다음과 같은 과정을 거칩니다.
- findPostById(postId)로 Optional를 받아옵니다.
- map(Post::getAuthor)를 통해 Optional에서 Optional로 변환합니다.
- 다시 map(User::getEmail)로 Optional에서 Optional로 변환합니다.
- orElse("no-email@example.com")으로 값이 없을 경우 기본 이메일을 반환합니다.
이처럼 Optional 체인을 활용하면 null 체크와 관련된 복잡한 코드를 간결하게 작성할 수 있습니다.
결론
- map: Optional 내부 값을 다른 값으로 변환할 때 사용합니다.
- flatMap: 내부 값이 Optional일 때 중첩을 피하기 위해 사용합니다.
- filter: 조건에 따라 Optional 내부 값을 걸러냅니다.
- orElse, orElseGet, orElseThrow: 최종 결과가 없는 경우 기본값을 제공하거나 예외를 발생시킵니다.
이러한 체이닝 방식을 통해 코드가 보다 선언적이고 명확해지며, null 체크로 인한 오류를 방지할 수 있습니다. 추가 질문이 있으시면 언제든지 문의해주세요!
- Total
- Today
- Yesterday
- nl2br
- error-java
- 특정 문자를 기준으로 자르기
- 메이븐(maven)
- java web-mvc
- docker
- 스프링 시큐리티(spring security)
- 스프링 프레임워크(spring framewordk)
- 인텔리제이(intellij)
- 스프링 프레임워크(spring framework)
- System.Diagnostics
- 스프링 시큐리티(spring security)-http basic 인증
- .submit()
- java-개발 환경 설정하기
- MainActor
- jstl(java standard tag library)-core
- jsp 오픈 소스
- jstl(java standard tag library)
- In App Purchase
- system.io
- java 키워드 정리
- 진수 변환
- 람다식(lambda expression)
- 문자 자르기
- await
- REST API
- 제품 등록
- 표현 언어(expression language)
- java.sql
- React
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |