본문 바로가기
Java

Java Random 클래스(Feat ThreadLocalRandom, SecureRandom)

by 에어컨조아 2022. 6. 15.

TDD 학습을 진행하던 도중 Random으로 값을 뽑아야 할 일이 생겼습니다.
JAVA 에서는 Random에 대한 다양한 클래스들을 제공하고 있는데요!
이에 대해 하나씩 살펴보는 시간을 가져볼까 합니다.

우선 첫번째로 알아볼 Random 클래스 입니다.

Untitled

JAVA 1.0때부터 존재했었는데요! 역사가 있는 클래스 입니다.
본문 내용을 읽어보면 아래와 같은 내용을 확인하실 수 있습니다.

Untitled (1)

대략 요약하자면 이렇습니다.

  • Random은 다중 스레드 환경에서는 스레드간 경합이 발생하여 성능저하가 발생하니 ThreadLocalRandom을 사용하는 것이 좋습니다.
  • Random에서 만드는 의사난수는 보안적으로 안전하지 않으니 SecureRandom을 사용해야 합니다.

그럼 하나씩 살펴보도록 하겠습니다.

Random vs ThreadLocalRandom

JAVA 1.0때 존재했던 Random과 달리 ThreadLocalRandom은 JAVA 7부터 추가되었습니다.
앞서 알아본 다중 스레드 환경에 성능저하가 발생할 수 있다는 이유로 이를 해소하기 위해 만든 클래스 인데요!
Random 클래스에서 어떠한 이유로 성능저하가 발생했는지 이를 어떻게 해결했는지 알아보겠습니다.

Random은 별도의 seed를 설정하지 않으면 기본적으로 현재 컴퓨터 시간을 기준으로 난수를 생성합니다. 실제 난수를 생성하기위해 사용하는 Random 클래스의 next 메서드를 확인해보겠습니다.

Untitled (2)

AtomicLong을 사용하여 원자성을 보장하고 반복문을 돌아 중복되지 않도록 처리하고 있습니다.

즉 Multi-Thread 환경일 경우 동시에 여러 스레드에서 난수요청이 들어온다면 해당 반복문을 통해 중복된 난수를 생성하지 않도록 처리하는 부분이라 보면 될 것 같습니다.

그렇다면 이렇게 동시에 요청하는 스레드들이 많으면 많을 수록 스레드들간의 경합이 발생되고, 이는 곳 성능저하를 가져오게 될 것이었습니다.

조금 더 자세하게 알고 싶다면 선형 합동 생성기(Linear Congruential Generator)알고리즘에 대해서 알아보면 좋을 것 같습니다😀

JAVA 7에서는 이러한 문제를 해결하기 위해 ThreadLocal 개념을 도입하여 ThreadLocalRandom 클래스를 만들게 됩니다.

Untitled (3)

ThreadLocalRandom은 스레드 별로 별도의 인스턴스를 가지게 되며, 각기 동작하도록 고안된 클래스 입니다. 따라서 전역으로 모든 스레드에서 접근 가능한 Random에서 발생한 경합과 충돌 문제가 발생하지 않으므로 성능이 향상되는 것을 확인할 수 있습니다.

아래 이미지는 1000개의 스레드를 사용하여 경합을 발생시켰을 경우 성능비교입니다.

Untitled (4)

Untitled (5)

Random에 비해 ThreadLocalRandom의 성능이 약간 더 좋은 것을 확인하실 수 있습니다.
이를 통해 스레드의 갯수가 증가함에 따라 차이가 더 벌어질 것이라는 것을 유추해볼 수 있습니다.
하지만 JAVA 8 버전 이후에는 스레드별 인스턴스를 만드는 방법이 아닌 스레드별 Seed를 각각 설정할 수 있도록 하여 성능을 보완시켰다고 합니다.

Random vs SecureRandom

Untitled (6)

SecureRandom도 Random을 상속받아 구현하고 있는 것을 확인할 수 있습니다.

Random은 선형 합동 생성기 알고리즘(LCG)를 사용하지만, SecureRandom은 중복이 발생하기 더 힘들고 보안적으로 좀 더 안전한 CSPRNG알고리즘을 사용한다고 합니다.

보다 자세한 내용은 알고리즘 내용임으로 주제 및 학습 범위을 넘어서는 부분인 것 같아 둘의 비교는 여기까지 하도록 하겠습니다.

정리

JAVA에서 제공해주는 다양한 Random 클래스들을 알아보았습니다.

Random을 사용할 일이 생긴다면 ThreadLocalRandom, SecureRandom을 사용하는 것이 더 좋다는 것을 알았습니다. 또한 상황에 맞게 멀티 스레드 환경이며 성능을 중요시 하는 곳에서는 ThreadLocalRandom을, 랜덤값의 보안이 중요하다면 SecureRandom을 사용하여 상황에 맞게 적절한 클래스를 선택해야 될 것 같습니다.

Reference

https://www.baeldung.com/java-thread-local-random#threadlocalrandom-example

https://www.techiedelight.com/difference-java-util-random-java-security-securerandom/

'Java' 카테고리의 다른 글

정규표현식 (개념정리, Dangling meta character)  (0) 2022.06.15
java Stream API는 for-loop보다 정말 느릴까?  (0) 2022.06.15
CQRS 패턴  (0) 2022.06.15
Optional orElse, orElseGet 차이  (0) 2022.06.15
Java Comparable vs Comparator  (0) 2022.06.15

댓글