Random Class는 어떻게 난수를 생성할까

DeadWhale·2023년 2월 26일
0

JAVA

목록 보기
7/10
post-thumbnail

JAVA의 랜덤 생성 방법은 몇가지 있다.

java.util 패키지의 Random 클래스 사용

javaCopy code
import java.util.Random;

Random rand = new Random();
int randomNumber = rand.nextInt();
  1. 난수를 생성하기 위한 가장 기본적인 클래스 중 하나.
  2. 매번 다른 시드 값을 사용하여 의사 난수를 생성.
  3. 메서드를 호출할 때 인자로 최대값을 전달하면 0부터 최대값-1까지의 범위 내에서 난수를 생성.
  4. 난수 생성 알고리즘은 선형 합동 생성기(Linear Congruential Generator, LCG).

Math.random() 메서드 사용

javaCopy code
double randomNumber = Math.random();
  • java.lang.Math 클래스의 static 메서드 중 하나.
  • 0 이상 1 미만의 double 타입의 의사 난수를 생성.
  • 내부적으로 java.util.Random 클래스를 사용합니다.
  • Random 클래스와 마찬가지로 시드 값이 바뀌면 다른 의사 난수가 생성된다.

ThreadLocalRandom 클래스 사용

javaCopy code
import java.util.concurrent.ThreadLocalRandom;

int randomNumber = ThreadLocalRandom.current().nextInt();
  • java.util.concurrent 패키지에 포함된 클래스.
  • 다중 스레드 환경에서 안전하게 의사 난수를 생성할 수 있도록 설계되어 있다.
  • Random 클래스와 마찬가지로 선형 합동 생성기 알고리즘을 사용하지만,
    다른 시드 값을 사용하여 난수를 생성합니다.
  • 메서드를 호출할 때 인자로 최소값과 최대값을 전달하면 해당 범위 내에서 난수를 생성한다.

예전에 어디서인가 들은 대화인대 기계가 절대하지 못하는 것 중 하나가 난수 생성이였다.

사람에게 1~10사이의 수를 말해줘 하면 매번 난수가 나올 수 있지만

프로그램의 난수는 “의사 난수”로서 결정론적인 알고리즘에 의해 생성된 수열이다

결국 예측 가능하다는 말이다.

이런 알고리즘 외에 외부 자연 현상을 기반을 생성되는 진짜 난수도 있기는 하다.

  • 방사선 붕괴
    • 방사선 물질이 방사선을 방출하면서 일정한 시간 간격으로 핵심이 붕괴된다.
      이 때 붕괴 시간이 불확실해 이 측정값으로 진짜 난수를 생성할 수 있다.
  • 전기잡음
    • 전기회로에서 발생하는 불규칙한 전압 변화로 불규칙성 + 무작위성을 가질 수 있다.
  • 대기 진동
    • 바람이나 대기의 마찰로 인해 발생하는 진동으로 무작위성을 가질수 있다.

그렇다면 Random 클래스는 어떻게 어떻게 난수를 발생 시키는 걸까?

Random 클래스는 시드 값을 기반으로

선형 합동 생성기 (Linear Congruential Generator, LCG) 알고리즘을 사용해서

의사 난수로 생성한다.

이 알고리즘은 의사난수를 생성할 수 있지만. 결국 패턴 , 규칙성이 파악 될 수 있다.

시드값이란?
난수 생성 알고리즘의 초기값을 의미한다 ( 시드머니 같이 )
시드 값을 지정하지 않으며 시스템 시간을 기반으로 시드값을 설정한다

시드값을 지정 : Random rand = new Random(1);
시간을 시드값으로 활용 : Random rand = new Random();

시드 값이 같을 경우 환경이 같은 경우 언제나 같은 값을 반환하기 때문에 주의해 사용해야 한다.

public static void main(String[] args) {
        Random rand = new Random(1);
        System.out.println(rand.nextInt()); // -1155869325
        System.out.println(rand.nextInt()); // 431529176
        System.out.println("==============================");
        Random rand1 = new Random();
        System.out.println(rand1.nextInt());
        System.out.println(rand1.nextInt()); 
}
1번 실행 결과 
-1155869325
431529176
==============================
-1095874602
1776211941

2번 실행 결과 
-1155869325
431529176
==============================
-616803561
-1057413960

Math.random **과 Random의 차이점은?**

  1. Random 클래스는 객체를 생성 하고 난수를 발생 계산하는 방식이지만
    Math.random()은 Math클래스의 static 메소드여서 객체의 생성없이 바로 호출할 수 있다.
  2. Random클래스는 정수,실수 타입의 난수를 생성 할 수 있다.(int,long,float,double)
    Math.random은 0 < 값 < 1을 반환한다. ( ex = 0.9491987276149608 )
  3. Random클래스는 보안적인 측면에서 안전하게 난수를 생성할 수 있도록 설계되었다.
    시드값 지정, SecureRandom 를 객체로 전달해 난수를 생성하는 등의 방식이 있지만
    Math.Random은 단순히 Random클래스의 LCG 알고리즘을 활용하기 때문에. 결국 예측이 가능해진다.

그렇다면 ThreadLocalRandom는 ?

Java 7에서 추가된 난수 생성 클래스이다
Random과 Math.random과 동일하게 의사 난수를 발생하지만

내부의 static ThreadLocal 인스턴스를 활용해 각 스레드마다 독립적인 난수를 생성할 수 있다.

서로의 영향을 주지 않고 독립적으로 생성할 수 있다.

Random 클래스와 동일한 메소드들을 활용 할 수 있다.

import java.util.concurrent.ThreadLocalRandom;

int randomNum = ThreadLocalRandom.current().nextInt(0, 100);
  • 0~99 까지의 값 중 하나를 정수형태로 받는 방식
  • current()메소드를 통해 독립적인 스레드 객체를 반환한다.
  • 병렬 스레드 환경에서 안정하게 난수를 생성하기 위해 있는 클래스이다.
    • 예시
    • 게임 로직 (아이템 등, 데미지등을 처리할때.)
    • 웹 서비스 ( 토큰 생성 로직에서 난수가 필요할 경우 )
    • 암호화
    • 머신 러닝

등이 난수가 필요로 하면서 쓰레드 세이프가 필요한 기능들이다.


물론 일반적인 환경에서는 의사 난수로 충분하다.

다만 보안이 필요할 경우 SecureRandom 클래스를 제공해 암호학적으로 안전한

난수를 만들어낼 수 있다. Random 클래스와 동일한 메소드를 제공하기 때문에.

SecureRandom

Java에서 제공한 진짜 난수 생성기로 보안 관련 애플리케이션에서 사용된다.

java.security.SecureRandom 패키지에서 제공하는 클래스로

import java.security.SecureRandom;

SecureRandom sr = new SecureRandom();
byte[] bytes = new byte[16];
sr.nextBytes(bytes);

System.out.println(Arrays.toString(bytes));

결과
[89, -96, -39, -98, 81, 111, -66, -99, -65, -106, 24, 5, 5, -101, 59, -22]

이 코드는 16바이트 크기의 난수를 생성하는 코드이다.

내부적으로 랜덤한 데이터 소스를 사용해 안전한 난수를 생성한다 .

랜덤 데이터 소스의 예시는 운영체제에서 제공하는 하드웨어의 물리적인 속성
리눅스, 유닉스 기반 운영 체제에서 제공하는 /dev/random과 /dev/urandom 디바이스가 있다.

하드웨어의 물리적 속성은 CPU, 메모리 , 마우스 움직임 , 키보드 타이밍같은 방식등이 있다.

위에서 말했을때에 진짜 난수의 예시는 대기진동, 전자기파등이 있었는데

SecureRandom 의 진짜 난수와는 차이점이 있지만. 완전히 예측할 수 없는 절대적인 난수를 불가능하다


예전에 본 어느 문장에서 생각이 비롯되 글을 쓰게 되었다.
결국 완전한 난수는 프로그램만으로는 불가능하지만
사람의 인지 수준에서는 난수라 판단 하기로 했다!

0개의 댓글