카테고리:

업데이트:

1. 성능 최적화의 잘못된 추론

아래와 같은 코드의 문제점은 무엇일까요?

  try {
    int i = 0;
    while(true)
      range[i++].climb();
  } catch (ArrayIndexOutOfBoundsException e) {

  }

언뜻 봐서는 무슨 기능을 하는지 알 수 없습니다.

사실 이 코드는 배열의 원소를 순회하는 코드인데 우리가 흔히 아는 경계 검사 방식이 아닌 예외를 이용한 방식을 사용하고 있습니다.

예외를 써서 루프를 종료한 이유는 배열에 접근할 때마다 경계를 넘지 않는지 검사하는 부분을 생략하여 성능 향상을 시키기 위한 것으로 보입니다.

하지만 이는 세 가지의 문제점이 있습니다.

  1. 예외는 예외 상황에 쓸 용도로 설계되었고, 성능 최적화를 위해 예외를 사용하는 것은 잘못된 사용법이다.

  2. 코드를 try-catch 블록 안에 넣으면 JVM이 적용할 수 있는 최적화가 제한된다.

  3. 배열을 순회하는 표준 관용구는 앞서 걱정한 중복 검사를 수행하지 않는다.

그리고 만약, 위 코드의 반복문 내부에서 뜻하지 않은 ArrayIndexOutOfBoundsException이 발생했을 경우에는 정상적인 반복문 종료 상황으로 오해되고 넘어가므로 문제가 될 수 있습니다.

그래서 예외는 일상 제어 흐름용이 아닌 오직 예외 상황에서만 사용해야 합니다.

2. 올바른 작성법

위의 코드와 같이 일상 제어 흐름에서는 예외를 이용한 방법이 아닌 IteratorhasNext()와 같은 상태 검사 메서드나 Optional 그리고 특정 값(null) 중 하나를 반환하는 방법이 있습니다.

3가지 중 하나를 선택하는 지침은 다음과 같습니다.

  1. 외부 동기화 없이 여러 스레드가 동시에 접근할 수 있거나 외부 요인으로 상태가 변할 수 있다면 Optional이나 특정 값을 사용한다.

  2. 성능이 중요한 상황에서 상태 검사 메서드가 상태 의존적 메서드의 작업 일부를 중복 수행한다면 Optional이나 특정 값을 선택한다.

  3. 다른 모든 경우에는 상태 검사 메서드를 사용한다.

  4. 특정 값은 검사하지 않고 지나쳐도 문제를 발견하기 어려운 단점이 있다.

3. 정리

이번 포스트는 일상 제어 흐름에서 예외를 잘못 사용하여 발생하는 문제와 그의 해결법을 알아보았습니다.

예외는 예외 상황에서만 쓸 의도로 설계되었으므로 정상 제어 흐름에서 사용하지 않도록 합시다.

            
              📕 개인 기록용 블로그입니다.
              😊 오타나 잘못된 정보가 있을 경우 댓글이나 메일로 말씀해주시면 바로 수정하겠습니다! 😊
          

댓글남기기