라이브러리를 익히고 사용하자

2021-07-30

랜덤난수 라이브러리

무작의 정수 하나를 생성하고 싶다고 해보자.

값의 범위는 0부터 명시한 수 사이다.

static Random rnd = new Random();

static int random(int n) {
  return Math.abs(rnd.nextInt()) % n; 
}

이 코드는 세 가지 문제점이 있다.

  • n이 크지 않은 제곱수라면 얼마 지나지 않아 같은 수열이 반복된다.

  • n이 2의 제곱수가 아니라면 몇몇 숫자가 평균적으로 더 자주 반환된다.

    public static void main(String[] args) {
      int n = 2 * (Integer.MAX_VALUE / 3);
      int low = 0;
      for (int i = 0; i < 1000000; i++) {
        if(random(n) < n/2)
          low++;
        System.out.println(low);
      }
    }
    

    random 메서드가 이상적으로 작동한다면 약 50만개가 출력돼야 하지만, 666,666에 가까운 값을 얻는다.

    이 뜻은 무작위로 생성된 수 중에서 2/3이 중간값보다 낮은 쪽으로 쏠린 것이다.

  • 지정한 범위 바깥의 수가 종종 튀어나올 수 있다.

    이 이유는 rnd.nextInt()가 Math.abs()를 이용해 음수가 아닌 정수로 매핑하기 때문이다.

    Integer의 범위는 -2^31 부터 2^31 - 1 인데 Math.abs(-2^31)을 하면 -2^31이 나오는 오류가 있다.

이런 결함을 해결하려면 의사난수 생성기, 정수론, 2의 보수 계산 등에 조예가 있어야 하지만, Random.nextInt(int)가 이미 해결해 놨다.

알고리즘을 잘하는 개발자가 설계와 구현과 검증에 시간을 들여 개발했고, 이 분야의 여러 전문가가 잘 동작함을 검증해줬다.

혹시 버그가 발견되더라도 다음 릴리스에서 수정 될 것이다.

표준 라이브러리를 사용하면 그 코드를 작성한 전문가의 지식과 여러분보다 앞서 사용한 다른 프로그래머들의 경험을 활용할 수 있다.

표준 라이브러리의 장점

  • 핵심적인 일과 크게 관련 없는 문제를 해결하느라 시간을 허비하지 않아도 된다.
  • 노력하지 않아도 성능이 지속해서 개선된다
  • 기능이 점점 맗아진다.
  • 우리가 작성한 코드가 많은 사람들에게 낯익은 코드가 된다.
    • 자연스럽게 다른 개발자들이 더 읽기 좋고, 유지보수하기 좋고, 재활용하기 쉬운 코드가 된다.

따라서 직접구현하기 보다는 표준 라이브러리의 기능을 사용하고, 기능이 없다면, 메이저 릴리스마다 주목할 만한 기능이 추가 되니, 한번 씩은 읽어보자.

라이브러리가 너무 방대하여 모든 API 문서를 공부하긴 힘들지만, 적어도 java.lang ,java.util ,java.io 와 그 하위 패키지들에는 익숙해지는게 좋다.

또한 컬렉션 프레임워크와 스트림 라이브러리와, java.util.concurrent 의 동시성 기능 관련 패키지를 알아두면 큰 도움 된다.

정리

때로는 라이브러리가 필요한 기능을 충분히 제공하지 못할 수 있다.

우선은 라이브러리를 사용하려고 시도해보자.

자바 표준 라이브러리에서 원하는 기능을 찾이 못하면, 그 다음으로 고품질 서드파티 라이브러리를 찾아보자.

구글의 구아바 라이브러리가 대표적이다.

서드파티에도 없다면, 다른 선택이 없으니 직접 구현하자.