코드 개선 (refactoring)/Java

Optional 제대로 사용하기

가지코딩 2025. 4. 19. 23:12

Java의 Optional은 NPE(NullPointerException)를 방지하고자 등장한 도구이다.

하지만 잘못 사용하면 오히려 코드가 더 복잡해지고, 불필요한 객체 생성으로 인해 성능저하가 발생할 수 있다.


수정 전 코드

  • Java 에 익숙하지 않아서, "null이 반환될 수도 있는 경우라면 Optional을 써야 한다" 라고 생각했다.
  • Optional.empty() 를 반환하고, 호출부에서 isParent() 등으로 체크할 수 있으니 더 안전한 코드라고 생각한 것이다.
public Optional<int[]> getData() {
    if (/* 데이터가 있음 */) {
        return Optional.of(array);
    } else {
        return Optional.empty();
    }
}

 

 

이 코드에는 다음과 같은 문제가 있다.

  • 배열에 Optional은 과하다
    • 배열은 본래 참조 타입이다.
    • 값을 담지 못하는 상황이라면, 빈 배열이나 null로도 충분히 표현할 수 있다.
  • 성능 저하
    • Optional도 객체이기 때문에, 매 호출마다 불필요한 객체가 생성된다.
    • 특히 반복 호출 시, 불필요한 힙 메모리 사용과 GC 부담이 생긴다.
  • 코드의 의미가 애매해짐
    • Optional.empty()와 Optional.of(new int[0])는 둘 다 비어있는 것처럼 보이지만, 의미는 전혀 다르다.
    • 호출부에서 혼란을 줄 수 있다.

수정 후 코드

  • Optional<int[]> 대신 int[]를 직접 반환한다.
  • 비어 있음을 표현할 때는 null 대신 빈 배열을 반환
  • 호출부에서도 의미를 명확하게 판단 가능하다. if (result.length == 0)
public int[] getData() {
    if (/* 데이터가 있음 */) {
        return array;
    } else {
        return new int[0];  // 빈 배열 반환
    }
}

 

호출부 예시

int[] result = getData();
if (result.length == 0) {
    System.out.println("데이터가 없습니다.");
} else {
    System.out.println("데이터 처리 시작");
}

Optional은 언제 쓰는 게 좋을까?

 

상황 Optional 사용 여부
단일 값 (Integer, String 등)을 반환 ✅ 적절
배열, 리스트 등 컬렉션 반환 ❌ 빈 배열/리스트 반환이 더 나음
기본형 값 (int 등) ✅ OptionalInt, OptionalDouble 사용 가능
복잡한 조건 분기나 의도 명확성이 중요한 경우 ✅ 좋음