Skip to content

아이템 59. 라이브러리를 익히고 사용하라 #142

Open
@JoisFe

Description

@JoisFe

Discussed in https://github.com/orgs/Study-2-Effective-Java/discussions/136

Originally posted by JoisFe February 22, 2023

아이템 59. 라이브러리를 익히고 사용하라

  • 무작위 정수 하나 생성 하는 코드를 만들어보자
    static Random rnd = new Random();
    
    static int random(int n) {
        return Math.abs(rnd.nextInt()) % n;
    }
  • 위 코드는 세가지 문제가 있음
  1. n이 그리 크지 않은 2의 제곱수라면 얼마 지나지 않아 같은 수열이 반복
  2. n이 2의 제곱수가 아니라면 몇몇 숫자가 평균적으로 더 자주 반환
  3. n 값이 크면 이 현상이 더 두드러짐

예시 코드

  • 신중히 선택한 범위에서 무작위 수를 백만개를 생성한 후 그 중 중간 값보다 작은 게 몇개 인지 출력
static int random(int n) {
        return Math.abs(rnd.nextInt()) % n;
    }
    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);
    }
image
  • random 메서드가 이상적으로 동작한다면 약 50만 개 출력되어야 함
  • 실제로 666,666에 가까운 결과를 확인할 수 있음
  • 무작위로 생성된 수 중 2/3 가량이 중간값보다 낮은 쪽으로 쏠렸음
  • 가장 위 코드의 3번째 문제점 즉 지정한 범위 '바깥'의 수가 종종 튀어나올 수 있음
  • rnd.nextInt()가 반환한 값을 Math.abs를 이용해 음수가 아닌 정수로 매핑하기 때문

위 문제의 해결법?

  • 의사난수 생성기, 정수론, 2의 보수 계산 등 조예가 깊어야 함
  • 이러한 개념들을 알기엔 쉽지 않음

다른 해결법

  • Random.nextInt(int)가 이미 해결
  • 이 메서드의 자세한 동작 방식은 몰라도 됨 (궁금하다면 API 문서나 소스코드를 보면 됨)
  • 이 메서드 경우 알고리즘에 능통한 개발자가 설계와 구현과 검증에 시간을 들여 개발
  • 이 분야의 여러 전문가들이 잘 동작함을 검증함
  • 또한 해당 라이브러리가 릴리스된 후 20년 간 수백만의 개발자들이 열심히 사용했지만 버그가 보고된 적 없음
  • 만약 버그가 발견되더라도 수정될 것

표준 라이브러리 사용의 장점

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

Random 의 문제점

  • 자바 7 버전 부터는 Random을 더 이상 사용하지 않는 것이 좋음
  • ThreadLocalRandom으로 대체하면 대부분 잘 동작
  • Random 보다 더 고품질의 무작위 수를 생성, 속도도 더 빠름
  • 포크-조인 풀이나 병렬 스트림에서는 SplittableRandom을 사용하는 것을 추천

2. 핵심적인 일과 크게 관련 없는 문제를 해결하느라 시간을 허비하지 않아도 된다.

3. 따로 노력하지 않아도 성능이 지속해서 개선 됨

  • 사용자가 많고 업계 표준 벤치마크를 사용해 성능을 확인할 수 있기 때문에 표준 라이브러리 제작자들은 더 나은 방법을 꾸준히 모색함
  • 자바 플랫폼 라이브러리의 많은 부분이 수 년에 걸쳐 지속해서 다시 작성되며 때론 성능이 극적으로 개선

4. 기능이 점점 많아짐

  • 라이브러리에 부족한 부분이 있다면 개발자 커뮤니티에서 이야기가 나오고 논의된 후 다음 릴리스에 해당 기능이 추가되곤 함

5. 표준 라이브러리를 활용해 작성한 코드가 많은 사람에게 낯익은 코드가 됨

  • 자연스럽게 다른 개발자들이 더 읽기 좋고 유지보수하기 좋고 재활용하기 쉬운 코드가 됨

그럼에도 불구하고 직접 구현하는 경우

  • 위 표준 라이브러리 사용의 많은 장점들이 있음에도 많은 프로그래머가 직접 구현해서 하는 경우가 많음

대부분 라이브러리에 그런 기능이 있는지 모르기 때문

  • 라이브러리가 너무 방대하여 모든 API 문서를 공부하기 벅차겠지만 자바 프로그래머라면 적어도 java.lang, java.util, java.io 와 그 하위 패키지들에는 익숙해져야함
  • 다른 라이브러리 경우 필요할 때마다 익히면 됨

라이브러리가 필요한 기능을 충분히 제공하지 못하는 경우

  • 더 전문적인 기능을 요구할수록 이러한 현상이 발생할 가능성이 큼
  • 우선은 라이브러리를 사용하려고 시도하는 습관이 중요하다
  • 만약 라이브러리에서 원하는 기능을 제공하지 못한다면 대안을 사용
  • 자바 표준 라이브러리가 가장 높은 우선순위로 두고, 원하는 기능을 찾지 못한다면 고품질의 서드파티 라이브러리를 찾자 (구글의 Guava가 대표적인 예)

정리

  • 표준 라이브러리 사용의 장점들을 보면 이미 잘 만들어진 바퀴를 사용하면 되지 바퀴를 만들려고 고생할 필요가 없다. 라는 명언이 생각이 났는데 책에서도 이 예시를 들었음
  • 아주 특별한 나만의 기능이 아니라면 누군가 이미 라이브러리 형태로 구현해 놓았을 가능성이 큼
  • 그러니 해당 기능을 제공하는 라이브러리가 있는지 없는지 먼저 찾아보자
  • 코드 품질에도 규모의 경제가 적용 됨 즉 라이브러리 코드는 개발자 각자가 작성하는 것 보다 주목을 훨씬 많이 받으므로 코드 품질도 그만큼 높을 가능성이 큼

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions