컴퓨터에서 "랜덤(random)"이라는 개념은 매우 중요합니다.
게임에서 무작위 아이템을 생성할 때, 암호화에서 보안 키를 만들 때,
머신러닝에서 데이터 샘플을 무작위로 추출할 때 랜덤 값(난수)이 필요합니다.
하지만 컴퓨터가 실제로 "완전한 랜덤"을 만들 수 있을까요?
사실, 대부분의 컴퓨터 난수는 완전히 랜덤하지 않습니다.
이번 글에서는 랜덤 알고리즘의 원리, 난수 생성 방식, 그리고 진정한 랜덤의 가능성을 탐구하고,
실제로 사용할 수 있는 가장 안전한 난수 생성 방법을 코드 예제와 함께 소개하겠습니다. 🚀
1. 난수란 무엇인가? (Random Number의 정의)
💡 난수(Random Number)란?
- 어떠한 규칙도 없이 예측할 수 없는 수.
- 난수는 완전한 무작위성(True Randomness)을 가져야 하지만,
컴퓨터는 규칙적인 알고리즘에 의해 동작하기 때문에 완전한 랜덤을 생성하기 어렵다.
📌 난수의 두 가지 종류
종류 설명 예제
의사 난수(Pseudorandom Number, PRNG) | 알고리즘을 이용한 난수 생성 (완전한 랜덤이 아님) | 게임, 시뮬레이션 |
진정한 난수(True Random Number, TRNG) | 물리적 현상을 이용한 완전한 난수 | 암호화, 보안 키 생성 |
✅ 결론: 일반적인 컴퓨터 난수는 알고리즘을 기반으로 생성되는 "의사 난수"이며, 완전한 랜덤이 아님.
2. 의사 난수 생성 (PRNG: Pseudorandom Number Generator)
💡 PRNG란?
- 수학적 알고리즘을 이용해 난수를 생성하는 방식.
- 일정한 패턴을 가지고 있지만, 매우 예측하기 어려운 방식으로 설계됨.
📌 의사 난수 생성 과정
1️⃣ 초기값(Seed) 설정 → 난수를 생성할 시작 값
2️⃣ 재귀적 연산 수행 → 난수 패턴을 만들기 위한 반복 계산
3️⃣ 출력 값 생성 → 난수처럼 보이는 숫자 출력
1️⃣ 대표적인 PRNG 알고리즘
(1) 선형 합동 생성기 (LCG, Linear Congruential Generator)
- 가장 오래된 난수 생성 알고리즘 중 하나
- 다음과 같은 수식을 이용해 난수를 생성 \[X_{n+1}=(aX_n+c)\mod m\]
- $X_n $ : 현재 난수
- $a,c,m$ : 미리 정의된 상수
📌 LCG의 특징
- 빠르고 간단하지만, 패턴이 반복되는 문제가 있음.
- 특정 초기값(Seed)을 사용하면 동일한 난수열이 반복됨.
(2) 메르센 트위스터 (Mersenne Twister, MT19937)
- 현대적인 PRNG 알고리즘 중 하나로, 널리 사용됨.
- 주기 길이가 매우 길고 $(2^{19937}-1)$ , 통계적으로 우수한 난수를 생성.
- Python의 random 라이브러리에서 기본적으로 사용됨.
📌 MT19937의 장점
- 난수 패턴이 반복되지 않고, 매우 균등한 분포를 가짐.
- 빠른 계산 속도로 대규모 난수 생성이 가능.
✅ 결론: PRNG는 실제 난수처럼 보이지만, 완전히 랜덤하지 않으며 예측 가능성이 존재.
3. 진정한 난수 생성 (TRNG: True Random Number Generator)
💡 TRNG란?
- 자연에서 발생하는 물리적 현상을 이용해 난수를 생성하는 방식.
- PRNG와 달리 예측할 수 없는 진짜 랜덤 값을 생성.
📌 TRNG의 주요 원리
방식 설명 예제
열 소음(열잡음) 기반 | 전자 회로의 미세한 전압 변동 이용 | Intel의 하드웨어 난수 생성기 |
방사성 붕괴 기반 | 원자핵이 불규칙하게 붕괴하는 속도 활용 | 랜덤닷오알지(Random.org) |
양자 난수 발생기 | 양자역학적 불확실성을 이용 | 양자 컴퓨팅 연구소 |
✅ 결론: TRNG는 완전한 랜덤성을 가지지만, 하드웨어 비용이 높고 속도가 느린 단점이 있음.
4. 실제 코드로 난수 생성 (PRNG vs TRNG 비교)
Python: PRNG (의사 난수)와 TRNG (진정한 난수) 비교
import random
import os
import secrets
# PRNG (의사 난수, 메르센 트위스터)
print("PRNG 난수:", random.randint(0, 100))
# TRNG (운영체제 하드웨어 기반 난수)
trng_num = int.from_bytes(os.urandom(4), "big")
print("TRNG 난수 (os.urandom()):", trng_num)
# 보안이 필요한 난수 생성 (secrets 사용)
secure_random = secrets.randbelow(100)
print("TRNG 난수 (secrets):", secure_random)
📌 설명:
- random.randint() → PRNG, 패턴이 존재할 가능성이 있음.
- os.urandom(4) → TRNG, 운영체제에서 하드웨어 기반 난수를 가져옴.
- secrets.randbelow(100) → 암호화에 적합한 난수 생성.
✅ 결론: 일반적인 난수는 random, 보안이 필요한 난수는 secrets와 os.urandom()을 사용해야 함.
5. 결론: 완벽한 랜덤은 가능한가?
✔ 컴퓨터 난수는 대부분 PRNG(의사 난수)로 생성되며, 완전한 랜덤이 아님.
✔ 보안이 중요한 경우, 운영체제의 TRNG(진정한 난수)를 사용해야 함.
✔ TRNG는 물리적 원리를 기반으로 난수를 생성하므로, 암호화와 보안에 적합.
✔ 가장 안전한 난수를 원한다면, /dev/random, SecureRandom, secrets를 활용해야 함.
👉 여러분은 컴퓨터에서 완전한 랜덤이 가능하다고 생각하시나요? 🤔
👉 PRNG와 TRNG 중 어느 방식이 더 중요하다고 생각하시나요? 🚀
'컴퓨터과학 > 알고리즘' 카테고리의 다른 글
유전 알고리즘(Genetic Algorithm)이란? : 자연에서 배운 최적화 기법 (0) | 2025.03.12 |
---|---|
프림 알고리즘(Prim's Algorithm) - Minimum Spanning Tree (MST) (0) | 2025.01.25 |
크루스칼 알고리즘(Kruskal's Algorithm) - Minimum Spanning Tree (MST) (0) | 2025.01.25 |
깊이 우선 탐색(DFS) - 탐색 알고리즘 (0) | 2025.01.23 |
너비 우선 탐색(BFS) - 탐색 알고리즘 (1) | 2025.01.22 |