🔢 랜덤 알고리즘의 원리
컴퓨터는 어떻게 랜덤을 만들까?
들어가며: 랜덤은 정말 랜덤일까?
"랜덤"이라는 단어를 들으면 무엇이 떠오르시나요? 주사위를 굴리거나, 동전을 던지거나, 복권 번호를 뽑는 장면?
컴퓨터에서의 랜덤은 조금 다릅니다. 컴퓨터는 기본적으로 결정론적(deterministic)인 기계입니다. 같은 입력에는 항상 같은 출력을 내놓습니다. 그렇다면 어떻게 "무작위"를 만들어낼 수 있을까요?
이 글에서는 컴퓨터가 랜덤 숫자를 생성하는 원리를 쉽게 설명합니다.
의사 난수 (Pseudo-Random Numbers)
📖 정의
의사 난수(Pseudo-random number)는 수학적 알고리즘으로 생성되는 숫자 시퀀스입니다. "의사(pseudo)"라는 말은 "진짜처럼 보이지만 진짜는 아닌"이라는 의미입니다.
어떻게 작동하나요?
의사 난수 생성기(PRNG: Pseudo-Random Number Generator)는 시드(seed)라는 초기값을 받아서 수학적 공식에 따라 숫자를 생성합니다. 같은 시드를 넣으면 항상 같은 숫자 시퀀스가 나옵니다.
간단한 PRNG 예시 (선형 합동 생성기)
// 선형 합동 생성기 (Linear Congruential Generator)
// X(n+1) = (a * X(n) + c) mod m
let seed = 12345; // 시드값
const a = 1103515245;
const c = 12345;
const m = 2 ** 31;
function nextRandom() {
seed = (a * seed + c) % m;
return seed / m; // 0~1 사이 값 반환
}
이 공식은 매우 단순하지만, 많은 프로그래밍 언어의 초기 랜덤 함수가 이와 비슷한 방식을 사용했습니다.
✅ 장점
- 매우 빠른 생성 속도
- 재현 가능 (디버깅에 유용)
- 메모리 효율적
❌ 단점
- 시드를 알면 예측 가능
- 패턴이 반복될 수 있음
- 보안에 취약
진성 난수 (True Random Numbers)
진정한 랜덤은 물리적 현상에서 옵니다. 자연에는 본질적으로 예측 불가능한 현상들이 있습니다.
🌡️ 열 잡음
전자 회로의 저항에서 발생하는 미세한 전압 변동. 양자역학적 현상으로 완전히 예측 불가능합니다.
⚛️ 방사성 붕괴
원자핵의 붕괴 시점은 양자역학적으로 완전히 무작위입니다. 가장 완벽한 랜덤 소스 중 하나입니다.
💡 광자 도착 시간
광자가 센서에 도착하는 정확한 시간은 예측 불가능합니다. 양자 난수 생성기에서 사용됩니다.
🌪️ 대기 잡음
라디오 주파수의 대기 잡음. random.org 같은 서비스가 이것을 사용합니다.
암호학적 난수 생성기 (CSPRNG)
🔐 CSPRNG란?
CSPRNG(Cryptographically Secure Pseudo-Random Number Generator)는 의사 난수 생성기의 속도와 진성 난수의 보안성을 결합한 것입니다.
핵심 원리
- 엔트로피 수집: 하드웨어에서 무작위 데이터(마우스 움직임, 키보드 입력 타이밍, 디스크 I/O 등) 수집
- 엔트로피 풀: 수집된 무작위 데이터를 안전하게 저장
- 암호학적 확장: 엔트로피 풀의 데이터를 암호학적 알고리즘으로 확장하여 난수 생성
운영체제별 CSPRNG
| 운영체제 | API |
|---|---|
| Windows | CryptGenRandom, BCryptGenRandom |
| Linux | /dev/urandom, getrandom() |
| macOS | /dev/urandom, SecRandomCopyBytes |
| 브라우저 | crypto.getRandomValues() |
Web Crypto API 자세히 보기
랜덤 선택기가 사용하는 Web Crypto API는 브라우저에서 제공하는 암호학적 API입니다.
사용 방법
// 1. 랜덤 바이트 배열 생성
const randomBytes = new Uint8Array(16);
crypto.getRandomValues(randomBytes);
// 결과: [142, 87, 203, 51, ...]
// 2. 랜덤 32비트 정수
const randomInt = new Uint32Array(1);
crypto.getRandomValues(randomInt);
console.log(randomInt[0]); // 0 ~ 4294967295 사이의 값
// 3. 0~max 사이의 랜덤 인덱스 (랜덤 선택기 방식)
function getSecureRandomIndex(max) {
const array = new Uint32Array(1);
crypto.getRandomValues(array);
return array[0] % max;
}
// 사용 예시: 5개 중 하나 선택
const selectedIndex = getSecureRandomIndex(5); // 0, 1, 2, 3, 4 중 하나
왜 Math.random() 대신 이것을 쓸까?
| 특성 | Math.random() | crypto.getRandomValues() |
|---|---|---|
| 예측 가능성 | 이론적으로 가능 | 불가능 |
| 보안 용도 | ❌ 부적합 | ✅ 적합 |
| 속도 | 매우 빠름 | 빠름 |
| 엔트로피 소스 | 알고리즘 | OS + 하드웨어 |
랜덤의 "품질" 측정
랜덤 숫자가 정말 랜덤한지 어떻게 알 수 있을까요? 여러 가지 통계적 테스트가 있습니다.
📊 균등 분포 테스트
모든 값이 비슷한 빈도로 나타나는지 확인합니다. 예를 들어 0~9 사이의 숫자를 10,000번 생성했을 때, 각 숫자가 약 1,000번씩 나와야 합니다.
🔗 연속성 테스트
연속된 숫자들 사이에 상관관계가 없어야 합니다. 1 다음에 2가 더 자주 나온다면, 그것은 좋은 랜덤이 아닙니다.
📈 런 테스트 (Run Test)
연속으로 증가하거나 감소하는 시퀀스(런)의 길이가 적절해야 합니다. 너무 긴 런이나 너무 짧은 런이 많으면 문제가 있습니다.
🎯 NIST 테스트 스위트
미국 국립표준기술연구소(NIST)가 개발한 포괄적인 랜덤성 테스트 세트. 15가지 이상의 통계적 테스트를 포함합니다.
재미있는 사실들
온라인 카지노의 랜덤
합법적인 온라인 카지노는 CSPRNG를 사용해야 하며, 독립 기관의 인증을 받아야 합니다. 부정행위를 방지하기 위해 랜덤 생성 로그를 모두 보관해야 합니다.
양자 컴퓨터와 랜덤
양자 컴퓨터는 양자역학의 불확정성을 이용하여 진정한 랜덤을 생성할 수 있습니다. 현재의 암호학적 랜덤보다 훨씬 더 "진짜" 랜덤입니다.
게임에서의 "가짜" 랜덤
일부 게임은 의도적으로 "진짜" 랜덤을 사용하지 않습니다. 플레이어가 너무 운이 나쁘면 몰래 확률을 높여주는 "자비 시스템"을 구현하기도 합니다. 이것을 "pity system"이라고 합니다.
스마트폰의 엔트로피
스마트폰은 가속도계, 자이로스코프, 터치 입력, 카메라 노이즈 등 다양한 소스에서 엔트로피를 수집합니다. 실제로 스마트폰을 흔들면 더 많은 엔트로피가 수집됩니다!
결론
컴퓨터의 랜덤은 수학과 물리학이 만나는 흥미로운 영역입니다. 단순한 의사 난수부터 양자역학을 이용한 진성 난수까지, 다양한 방법으로 "무작위"를 구현할 수 있습니다.
랜덤 선택기는 Web Crypto API를 사용하여 가장 안전하고 공정한 랜덤을 제공합니다. 일상의 작은 선택에도 카지노 수준의 공정성을 적용하는 것이죠!