벤티의 개발 로그

[Java] 'Random'은 정말 '랜덤'할까? 본문

카테고리 없음

[Java] 'Random'은 정말 '랜덤'할까?

sonsh75 2025. 6. 22. 17:25

'랜덤'

나는 어릴 때부터 야구와 축구를 좋아했다. 고등학교에 다닐 때까지는 야구를 많이 봤고, 대학교 때부터는 축구를 많이 봤다. 지금은 경기를 보는 것 자체를 좋아하지만, 과몰입(?) 했었던 예전에는 노트에 내가 좋아하는 팀의 경기 결과를 기록하기도 했다.

수리 (참고로 저는 한화 팬이 아닙니다)

 

모든 스포츠가 그렇겠지만, 특히 야구의 경우에는 불확실성이 정말 큰 스포츠로, 내가 야구를 좋아했을 때는 '데이터 야구'라는 말이 돌 정도로 '야구'와 '확률'을 접목하려는 시도가 많았고, 이에 성공한 팀이 좋은 성적을 거두었다.

 

내가 지금 가장 많이 하는 게임인 피크민도 '랜덤'이라는 요소가 강하게 작용하고, 당장 어제 강남역 근처의 보드게임 카페도 다녀왔다. 그리고, 이는 취미에만 국한되지는 않았다. 왜냐하면 내가 받은 업무에도 '랜덤'이라는 요소가 강하게 작용했기 때문이다.

 

일일 보고, 그 후...

 

[Database] Lock, Lock, Lock

첫 업무출근 3일 차에 첫 업무를 받게 되었다. 아직 코드 분석도 완벽하게 끝내지 못했고, 이제 겨우 프로젝트 코드가 어떻게 돌아가는지 이해한 후였다. 업무를 분석하면서 생각해 볼 것이 굉장

ventilog.tistory.com

 

지난번에 작성한 글로 팀장님께 일일 보고를 드렸더니, '난수는 어떻게 발생시키고 있나요?'라는 질문을 받아, 'Random 클래스를 이용해서 발생시키고 있습니다'라고 답변했다.

잘 모르죠?

 

돌아온 질문이었다. 다행히 내가 스턴에 걸린 상태로 회의를 끝내지 않도록 힌트들을 주셨다. 그래서 힌트들을 중 하나를 조사한 내용으로 이번 글을 작성해봤다.

 

랜덤하지 않은 'Random'

스포일러가 매우 강한 소제목이지만, 이 글의 결론이다.

Java 공식 문서: Random 클래스

 

그렇다. Java에서 제공하는 Random 클래스에서 발생하는 난수들은 Random 하지 않다. 이 내용은 무려 공식 문서에 언급된 내용이다. 위 사진에 드래그된 영역의 문장 표현 중 일부를 옮겨 적으면 다음과 같다.

An instance of this class is used to generate a stream of PSEUDORANDOM numbers.

 

강조 표시한 표현에 쓰인 Pseudo는 '가짜'라는 표현으로 쓰이는 그 의미가 맞다. 즉, Java에서 제공하는 Random 클래스는 사실 난수처럼 보이는 값들을 일정한 순서로 반복해서 발생시키고 있었던 것이다. 그리고 이 사실을 다르게 생각해 보면, 공격자가 난수를 발생시킬 때 사용하는 Seed 값을 알기만 한다면 언제든지 자신이 원하는 대로 값을 조정할 수 있다고 할 수 있다.

 

그렇다면 Random이 위험한 것은 알았으니, 다른 방법을 찾아봐야 했다. 조사 결과, 내가 찾은 2가지 대안을 아래에 적었다.

 

대안 1: SecureRandom 클래스

아래 Random 클래스 공식 문서의 마지막 문장에 이런 표현이 있다.

Consider instead using SecureRandom to get a cryptographically secure...

 

바로 SecureRandom 클래스의 이용을 고려해 보라는 것이었다.

Java 공식 문서: SecureRandom 클래스

 

공식 문서에도 나와 있듯이, 좀 더 강력한 난수 생성기를 제공한다고 한다. 그리고 조사해 보니, Random 클래스와의 차이점들은 아래와 같았다.

 

1. 보안 수준이 Random 클래스에 비해 매우 높아 암호나 키 생성, 토큰에 적합하다.

2. 암호학적 난수 생성 알고리즘인 SHA1PRNG 등등을 사용한다.

3. 시드가 공개되지 않는다면, 예측이 거의 불가능하다.

4. 다만, 속도가 상대적으로 느리다.

5. 대신, Random 클래스(일반적으로 48비트)에 비해 더 많은 비트(128비트 등등)를 사용해 난수를 생성하므로 상대적으로 안전하다.

 

여기까지만 살펴보면, SecureRandom 클래스를 사용하는 것이 상대적으로 안전해 보일 수 있겠지만, 결과적으로 쓰지 않았다. 왜냐하면 위에 작성한 Random 클래스 공식 문서의 마지막 문장의 뒷부분이 아래와 같기 때문이었다.

Consider instead using SecureRandom to get a cryptographically secure pseudo-random number generator for use by security-sensitive applications.

 

그렇다. 결국 SecureRandom 클래스도 'PSEUDORANDOM' 난수 생성기였다. 물론 Random 클래스에 비해 안전하다고는 하지만, 마음에 걸려 아래 대안을 사용하기로 했다.

 

대안 2: '시간'과 조합

 

바로 '시간'이었다. 실제로 Random 클래스의 기본 Seed도 시스템의 현재 시각이라고 한다. 따라서 이 정보만을 Seed로 사용할 경우 기존에 내가 보고드렸던 내용과 큰 차이가 없다고 생각해서, 여기에 '어떤 정보'를 조합하여 가공시킨 결괏값을 Seed로 사용하기로 했다. (어떤 정보인지는 자세하게 밝힐 수 없다.)

 

실제로 테스트 후 로그를 통해 결과를 분석하니, 이전에 비해 난수가 발생하는 순서나 값이 훨씬 다양하고 예측할 수 없게 변한 것을 확인할 수 있었다!

 

다른 대안은 없을까?

이번 기회를 통해 Random 클래스에 대해 정확하게 공부할 수 있었다. 😊

 

다만 2차 보고를 드린 후, 더 안전한 다른 대안은 없는지 궁금해졌다. 왜냐하면 조사 과정에서 OS에 따라 기본 Seed가 다르다는 내용도 봤기 때문이다. 현재 진행하는 프로젝트의 서버 Spec까지는 모르기 때문에, 과연 내가 선택한 대안이 안전한 지에 대한 의문이 들었다.

 

따라서 이 내용에 대해서는 앞으로도 꾸준히 업데이트를 진행할 것 같다!