Optional 클래스 사용법

프로젝트를 진행하며 처음으로 Optional이란 클래스를 사용하게 되었다. 사용하면 어떤 것이 좋은지, 어떻게 잘 활용할 수 있는지 알아보고 코드에 적용해보자!!

 

 

Optional 클래스

  • Optional 클래스란 자바 8부터 null값에 대한 처리를 좀 더 깔끔하게 할 수 있도록 추가된 클래스이다. 좀 더 가독성 좋은 코드를 만들기 위해서 사용한다.
  • null 값일 수도 있는 어떤 변수를 Optional 클래스로 감싸주는 방식으로 사용한다.

 

 

사용예시

  1. 유저 객체를 조회해 유저가 있으면 리턴, 없으면 예외를 발생
    • orElseThrow()
      • 객체가 null이면 함수형 인자를 통해 생성된 예외 발생, null이라면 객체를 반환

 

Optional 사용 전

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userRepository.findById(username);
    if (user == null){
        return user;   
    }else{
        throw new CustomException(ErrorCode.NOT_FOUND_USER);
    }
}

 

Optional 사용

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    Optional<User> user = userRepository.findById(username);
    return user.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_USER);
}

 

 

  1. 유저를 조회해 유저가 있으면 활동구분코드 검증, 유저가 없으면 예외발생
    • ifPresentOrElse()
      • 함수형 인자 2개를 매개변수로 받는다.
      • 첫번째 인자는 객체에 값이 존재할 경우 실행된다.
      • 두번째 인자는 객체에 값이 null일 경우 실행된다.

 

public User findById(String uid){
    Optional<User> user = userRepository.findById(uid);
    user.ifPresentOrElse(
        // user객체가 있으면 실행
        findUser -> {
            if (findUser.getActDvCd() != '1')
                throw new CustomException(ErrorCode.DELETED_USER);
        },
        // user 객체가 없으면 실행
        () -> {
            throw new CustomException(ErrorCode.NOT_FOUND_USER);
        });
    return user.get();
}

 

  1. 유저를 조회해 유저가 있으면 유저 프로필 이미지 업데이트, 없으면 예외발생
    • isPresent()
      • 객체에 값이 있으면 True, 없으면 false
    • get()
      • Optional 객체 안에 들어있는 값을 리턴
      • 값이 null일 경우 NoSuchElementException이 발생하기 때문에 값이 있는걸 확인하고 사용하는 것이 좋다.

 

public void uploadImage(String uid, String filePath){
Optional<User> user = userRepository.findById(uid);
    // #1
    if (user.isPresent()){
        user.get().updateUserProfileUrl(filePath);
    }else{
        throw new CustomException(ErrorCode.NOT_FOUND_USER);
    }
}

 

public void uploadImage(String uid, String filePath){
Optional<User> user = userRepository.findById(uid);
    // #2
    user.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_USER))
                .updateUserProfileUrl(filePath);
}

#1#2는 같은 기능의 코드지만 가독성 측면에서 #2형태로 되도록이면 사용하는 것이 좋다.

 

 

사용 시 주의할 점

  • Optional을 필드의 타입으로 사용하지 말자. Optional은 반환 타입을 위해 설계된 타입이다.
  • orElse() 메서드는 객체가 있던 없던 무조건 메서드의 인자가 평가된다. orElseGet() 메서드는 값이 없을 때만 수행된다. 따라서 NULL값 대신 기본값을 리턴하고 싶을 때 객체의 생성비용이 큰 경우라면 orElseGet()을 사용하자.
  • 빈 컬렉션이나 배열을 반환하는 경우는 Optional을 사용하지말자. (그냥 빈 컬렉션이나 배열을 리턴하는 것이 더 좋다.)

 

 

 

 

 

 

 

 

참고

https://www.latera.kr/blog/2019-07-02-effective-optional/

+ Recent posts