Open
Description
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;
}
- 위 코드는 세가지 문제가 있음
- n이 그리 크지 않은 2의 제곱수라면 얼마 지나지 않아 같은 수열이 반복
- n이 2의 제곱수가 아니라면 몇몇 숫자가 평균적으로 더 자주 반환
- 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);
}

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