랜덤 생성기: 작동 원리와 사용 시기

· 13분 읽기

랜덤 생성기는 어디에나 있습니다. 재생 목록을 섞거나, 비밀번호를 생성하거나, 시뮬레이션을 실행하거나, 비디오 게임을 할 때마다 난수 생성기가 뒤에서 작동하고 있습니다. 하지만 정확한 명령을 따르는 결정론적 기계인 컴퓨터가 어떻게 무작위성을 생성하는지 궁금해 본 적이 있나요? 그 답은 여러분이 예상하는 것보다 더 흥미롭고 (그리고 더 미묘합니다).

이 가이드는 랜덤 생성기의 과학과 공학을 탐구합니다. 진정한 난수와 의사 난수의 차이, 인기 있는 알고리즘의 작동 방식, 암호학적 등급의 무작위성이 필요한 시기, 그리고 일상 생활에 영향을 미치는 실용적인 응용 프로그램을 다룰 것입니다. 올바른 랜덤 함수를 선택하는 개발자이든, 확률에 대해 배우는 학생이든, 아니면 단순히 사물이 어떻게 작동하는지 궁금한 사람이든, 이 가이드가 도움이 될 것입니다.

무작위성이란 무엇인가? 심층 분석

무작위성은 직관적으로 보입니다 — 예측 불가능성, 혼돈, 패턴의 부재입니다. 하지만 무작위성을 정확하게 정의하는 것은 놀랍도록 어렵고, 수학자들은 수세기 동안 이에 대해 논쟁해 왔습니다.

가장 엄격한 의미에서, 시퀀스는 이전의 모든 값에 대한 완전한 지식이 있어도 어떤 알고리즘도 추측보다 더 나은 다음 값을 예측할 수 없다면 진정으로 무작위입니다. 이것을 콜모고로프 무작위성이라고 합니다 — 시퀀스가 더 짧은 설명으로 압축될 수 없다면 무작위입니다. 예를 들어, 파이의 숫자는 무작위성에 대한 모든 통계적 테스트를 통과하지만, 완전히 결정론적입니다 (충분한 계산으로 어떤 숫자든 계산할 수 있습니다).

실용적인 목적을 위해, 우리는 무작위성의 세 가지 속성에 관심을 갖습니다:

다른 응용 프로그램은 이러한 속성의 다른 수준을 요구합니다. 주사위 굴리기 게임은 균등성과 독립성이 필요하지만, 반드시 예측 불가능성이 필요한 것은 아닙니다. 비밀번호 생성기는 세 가지 모두가 필요합니다. 응용 프로그램에 필요한 무작위성의 종류를 이해하는 것이 올바른 생성기를 선택하는 첫 번째 단계입니다.

진정한 무작위 vs. 의사 무작위: 근본적인 차이

모든 랜덤 생성기는 두 가지 범주로 나뉘며, 이 구분은 정확성과 보안 모두에 매우 중요합니다.

진정한 난수 생성기(TRNG)

진정한 난수 생성기는 근본적으로 예측할 수 없는 물리적 현상에서 무작위성을 도출합니다:

TRNG의 핵심 속성은 출력이 재현 불가능하다는 것입니다. 동일한 장비와 조건에서도 매번 다른 시퀀스를 얻게 됩니다. 이것은 재현성이 치명적인 결함이 될 암호학적 응용 프로그램에 필수적입니다.

의사 난수 생성기(PRNG)

PRNG는 알고리즘입니다 — 무작위로 보이지만 초기 상태(시드라고 함)가 주어지면 완전히 예측 가능한 숫자 시퀀스를 생성하는 결정론적 수학 공식입니다. PRNG에 동일한 시드를 제공하면 매번 정확히 동일한 시퀀스를 생성합니다.

이것은 약점처럼 들릴 수 있지만, 실제로는 많은 응용 프로그램의 기능입니다:

과제는 출력이 진정한 무작위성과 통계적으로 구별할 수 없는 PRNG를 설계하는 것입니다 — 균등성, 독립성 및 패턴 부재에 대한 모든 알려진 통계적 테스트를 통과하는 것입니다.

🎲 생성기를 사용해 보세요

난수 생성기 → 비밀번호 생성기 →

의사 난수 생성기(PRNG)의 작동 원리

핵심적으로 PRNG는 각 호출마다 변환하는 내부 상태를 유지하여 출력을 생성하고 다음을 위해 상태를 업데이트합니다. PRNG의 품질은 변환이 패턴과 상관관계를 얼마나 잘 피하는지에 달려 있습니다.

선형 합동 생성기(LCG)

가장 간단하고 오래된 PRNG 계열인 LCG는 다음 공식을 사용합니다:

state = (a × state + c) mod m
output = state

여기서 a(승수), c(증분), m(모듈러스)은 신중하게 선택된 상수입니다. 예를 들어, 고전적인 MINSTD 생성기는 a = 16807, c = 0, m = 2³¹ - 1을 사용합니다. LCG는 매우 빠르지만(곱셈과 모듈로) 잘 알려진 약점이 있습니다: 순차적 값은 고차원으로 플롯할 때 패턴을 보이고, 하위 비트는 짧은 주기로 순환합니다. 대부분의 최신 응용 프로그램은 LCG를 넘어섰습니다.

메르센 트위스터(MT19937)

메르센 트위스터는 1997년 도입 이후 많은 언어와 시스템에서 기본 PRNG였습니다. 624개의 32비트 정수 상태를 유지하며 2¹⁹⁹³⁷ - 1(메르센 소수, 따라서 이름)의 주기를 갖습니다. 그 주기는 천문학적으로 길며 — 관측 가능한 우주의 원자 수보다 훨씬 많습니다.

알고리즘은 다음과 같이 작동합니다:

  1. 시드에서 624개의 상태 값 초기화
  2. 각 난수에 대해 비트 시프트와 XOR 연산을 통해 상태 값을 추출하고 "템퍼링"
  3. 트위스트 변환을 사용하여 주기적으로 전체 상태 배열 재생성

메르센 트위스터는 대부분의 통계적 테스트를 통과하며 시뮬레이션, 게임 및 범용 사용에 탁월합니다. 그러나 암호학적으로 안전하지 않습니다 — 624개의 출력을 관찰하면 전체 내부 상태를 재구성하고 모든 미래 값을 예측할 수 있습니다.

Xoshiro256** 및 최신 PRNG

xoshiro256**(많은 최신 언어에서 사용) 및 PCG(순열 합동 생성기)와 같은 최신 PRNG는 이전 생성기의 단점을 해결합니다. 다음을 제공합니다:

JavaScript의 Math.random()

JavaScript에서 Math.random()을 호출하면 최신 엔진(V8, SpiderMonkey, JavaScriptCore)은 좋은 통계적 속성을 가진 빠른 PRNG인 xorshift128+를 사용합니다. 0(포함)과 1(제외) 사이의 부동 소수점 숫자를 생성합니다. 게임, 셔플 및 무작위 선택에는 완벽하지만, 보안에 민감한 목적으로는 절대 사용해서는 안 됩니다.

// min과 max 사이의 기본 난수(포함)
function randomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

// 배열에서 무작위 요소
function randomChoice(array) {
  return array[Math.floor(Math.random() * array.length)];
}

// 배열 셔플(Fisher-Yates 알고리즘)
function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
  return array;
}

암호학적 무작위성: 보안이 중요할 때

보안 응용 프로그램 — 비밀번호, 암호화 키, 세션 토큰, 논스 — 의 경우 일반 PRNG는 위험할 정도로 부적절합니다. 난수를 예측할 수 있는 공격자는 전체 보안 모델을 손상시킬 수 있습니다.

CSPRNG를 다르게 만드는 것은 무엇인가?

암호학적으로 안전한 의사 난수 생성기(CSPRNG)는 중요한 속성을 추가합니다: 전방 및 후방 비밀성. 공격자가 현재 내부 상태를 발견하더라도 이전 출력을 결정할 수 없습니다(후방 비밀성). 그리고 상태를 모르고 과거 출력에서 미래 출력을 예측하는 것은 계산적으로 불가능합니다.

CSPRNG는 다음을 통해 이를 달성합니다:

일반적인 CSPRNG

실제로 암호학적 무작위성 사용하기

브라우저에서 Web Crypto API는 암호학적 등급의 무작위성을 제공합니다:

// 암호학적으로 안전한 난수 정수 생성
function secureRandomInt(min, max) {
  const range = max - min + 1;
  const bytesNeeded = Math.ceil(Math.log2(range) / 8);
  const maxValid = Math.floor(256 ** bytesNeeded / range) * range - 1;

  let value;
  do {
    const array = new Uint8Array(bytesNeeded);
    crypto.getRandomValues(array);
    value = array.reduce((acc, byte, i) => acc + byte * (256 ** i), 0);
  } while (value > maxValid); // 편향된 값 거부

  return min + (value % range);
}

// 안전한 무작위 비밀번호 생성
function generatePassword(length = 16) {
  const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*';
  const array = new Uint32Array(length);
  crypto.getRandomValues(array);
  return Array.from(array, x => chars[x % chars.length]).join('');
}

암호학적 등급의 무작위성을 위해 Web Crypto API를 사용하는 비밀번호 생성기로 안전한 비밀번호를 생성해 보세요.

엔트로피: 무작위성의 연료

무작위성의 맥락에서 엔트로피는 시스템의 진정한 예측 불가능성의 양을 측정합니다. 비트로 측정됩니다 — 1비트의 엔트로피는 공격자가 예측할 수 없는 하나의 이진 선택을 의미합니다.

엔트로피는 어디에서 오는가?

운영 체제는 여러 소스에서 지속적으로 엔트로피를 수집합니다:

We use cookies for analytics. By continuing, you agree to our Privacy Policy.