[JAVA] Optional 알아보기

드코딩·2024년 7월 24일
0

JAVA

목록 보기
3/3
post-thumbnail

Optional은 시작하면 자바 8부터 지원하기 시작했다.

처음은에는 없었다가 생겼다는 것은 무언가 불편한 걸 해결해주기 위해서 등장했을 것이다.

요녀석은 주로 NPE(NullPointException) 발생 방지를 위해 사용한다.

다른 언어에서는 잘 모르겠지만, 특히 객체지향 세상에서 Null 은 쉽게 오류를 발생한다.

메서드가 반환할 값이 없음 을 명백하게 표현할 필요가 있고, null을 반환하면 에러를 유발할 가능성이 높은 상황에서 메서드의 반환 타입으로 Optional 을 사용하자는 것이 Optional 을 사용하는 주 목적

return Null 을 대체하고자 Optional이 등장했다.

반환해주는 메서드에서 Null을 반환하는 것을 대체해준다면 받는 입장에서는
NPE를 걱정하지 않고 코드를 작성할 수 있다.

Optional 메서드

  • isPresent() : 옵셔널 객체가 null인지 아닌지 boolean 타입으로 반환
  • get() : null이 아니라면 객체를 꺼내서 반환하고 아니라면 null이라면 NoSuchElementException()
    을 발생시킨다. 그래서 isPresent() 랑 콤보로 자주 사용하여 예외 처리하는데 개인적으로 아래 더 좋은 메서드가 있다고 생각한다.
  • orElseGet() : orElseGet() 설명에 앞서 아래 사진의 Supplier는 파라미터를 함수로 받아서 처리해주는 기능이다. 그래서 orElseGet() 의 경우는 예외 객체를 만들어서 처리하는 것보다는 Null 인경우
    파라미터로 지정해준 메서드를 실행해서 객체를 생성해서 반환해주겠다는 의미다.
  • orElse() : 파라미터를 기존에 있는 객체를 전달해서 null이라면 파라미터로 전달한 객체가 반환되는 메서드
  • orElseThrow() : 예외를 처리할 때는 orElseThrow() 를 사용하도록 하자.
    공식 문서에 정의된 내용과 파라미터 명 또한 exception Supplier로 네이밍 해두었다.
    예외를 처리할 예외처리 객체를 파리미터로 전달하여 예외를 처리한다.

이뿐만 아니라 더 많은 메소드들이 존재한다.
하지만 주로 orElseThrow() 를 사용하고 비슷한 듯 다른 orElseGet() 을 정리해보았다.

💡 함수형 메소드?

주로 옵셔널에서는 아래와 같은 함수형 메소드가 사용된다.

  • 메소드 참조 연산 Or 생성자 참조 연산 : 생성할 클래스명::new
  • 람다식 : () → (new 생성자())

문법 뜯어보기

  • public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
    여기서 이문법이 잘 이해가 안된다.

    하나씩 뜯어보자

    • <X extends Throwable> : 제네릭 타입 매개변수를 정의하는 부분으로, X가 Throwable 클래스 또는 그 서브클래스여야 함을 의미한다.
    • T : 반환 값은 제네릭 타입으로 지정해서 유연하게 객체를 반환한다.
    • orElseThrow : 메서드명
    • Supplier : 서플라이어는 @FunctionalInterface 어노테이션을 가지고 있는 인터페이스다.
      해당 어노테이션을 가지고 있는 함수형 인터페이스를 제공한다. 그래서 람다식 , 메소드 참조,생성자 참조 연산이 가능하다.
    • ? : 제네릭의 와일드카드로 , 기본 제네릭과는 다르게 extends,super를 사용하여 타입의 상속관계를 명시적으로 정의하여 유연하게 사용가능하다.
    • <? extends X> 최대 상위 모델이 X를 넘을 수 없다는 뜻으로 예를 들어 NoSuchElementException 을 X 자리에 둔다면 ? 에 사용되는 객체는 NoSuchElementException 이거나 하위타입의 객체여야한다.

보통 Repository를 옵셔널로 처리해서하는데 Service에서도 할 수 있고 Controller에서도 가능한데
왜 레포지토리에서 하는게 좋을까?
최초에 객체가 Null임을 알 수 있는 영역은 레포지토리이다.
여기서 처리하지 않고 Service , Controller 둘 중 하나에 처리한다면 사용할 수 없는 데이터를 가지고
이동하느 시간을 갖기 때문에 최대한 빨리 처리하기위해 최초에 처리하는게 좋다.

그리고 DB 데이터의 조회 값이 Null인 경우 이 데이테가 있는지 없는지는 데이터를 관리하는 클래스 레포지토리 책임이 아닐까?

Optional에대한 개인적인 생각

사실 Optional이 없더라도 null 타입을 잘 처리할 수 있다.
그리고 Optional을 모르는 개발자가 봤을 때 이게 클린코드일 수 있을까?
라는 의문도 들긴했다. 하지만 모르더라도 코드가 짧아지고 메서드명에서 쉽게 유추하고
납득할 수 있다는 장점이 있다고 생각한다.

또한 JPA를 사용할 때 편리할 것 같다.
JPA 는 없는 값을 조회할 때 자바 세상에서는 Null을 반환해야 하는데 이때 Optional로 내가 Repository에서 처리해주면 받는 Service단에서는 비즈니스 로직만 수행한다면 편리하지 않을까? 라는 생각도 들었다.
(사실 if문으로 null처리도 가능하긴 하다.)


⭐틀린 내용 수정,지적은 언제나 환영합니다.⭐

0개의 댓글

관련 채용 정보