자바스크립트 환경에서 랜덤 값을 도출해야 하는 요구사항은 빈번하게 발생합니다. 기본적인 확률 계산부터 암호학적으로 안전한 토큰 생성까지, 목적에 따라 적합한 API와 연산 방식을 선택해야 합니다.
기본 부동소수점 난수 추출
가장 기초적인 난수 생성은 내장 객체인 Math의 메서드를 활용합니다. 이 메서드는 0 이상 1 미만의 부동소수점을 반환합니다.
// 0부터 1 사이의 부동소수점 난수 할당
const baseFraction = Math.random();
이 결과값은 자체적으로 사용되기보다는, 특정 범위의 정수를 만들거나 배열을 셔플링하는 등 다른 연산의 시드(Seed) 또는 배수로 활용되는 경우가 많습니다.
지정된 구간의 정수 난수 도출
최소값과 최대값이 정해진 구간 내에서 정수 형태의 랜덤 값을 얻으려면, 기본 난수 함수의 결과에 산술 연산과 버림 처리를 적용해야 합니다.
/**
* 주어진 최소값과 최대값 사이의 정수 난수를 반환합니다.
* @param {number} lowerBound - 최소값 (포함)
* @param {number} upperBound - 최대값 (포함)
* @returns {number}
*/
const pickIntegerInRange = (lowerBound, upperBound) => {
const rangeSpan = upperBound - lowerBound + 1;
return Math.trunc(Math.random() * rangeSpan) + lowerBound;
};
// 5 이상 20 이하의 정수 난수 추출
const targetValue = pickIntegerInRange(5, 20);
위 코드에서는 소수점 이하를 절사하는 Math.trunc()를 사용하여 정수 변환을 수행했으며, 최소값을 더함으로써 시작점을 조정했습니다.
커스텀 UUID 포맷 문자열 구성
데이터베이스의 기본 키나 세션 식별자로 쓰이는 UUID(Universally Unique Identifier)를 만들어야 할 때가 있습니다. 엄격한 암호학적 보장이 필요 없는 내부용 식별자라면, 난수와 비트 연산을 조합해 RFC 4122 버전 4 포맷을 모방할 수 있습니다.
const buildPseudoUuid = () => {
const pattern = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
return pattern.replace(/[xy]/g, (match) => {
const hexDigit = (Math.random() * 16) | 0;
// 'y' 자리는 8, 9, a, b 중 하나여야 함 (비트 마스킹 적용)
const mappedValue = match === 'x' ? hexDigit : (hexDigit & 0x3) | 0x8;
return mappedValue.toString(16);
});
};
const sessionId = buildPseudoUuid();
정규표현식을 이용해 템플릿 문자열의 특정 문자를 치환하며, 비트 AND(&)와 OR(|) 연산자를 통해 UUID 사양에 맞는 변형(variant) 비트를 강제로 주입합니다.
암호학적 안전성이 보장되는 난수 생성
인증 토큰, 암호화 키, 보안 세션 ID 등을 발행할 때는 예측 불가능성이 절대적으로 요구됩니다. 이때는 Math 객체 대신 웹 암호화 API(Web Crypto API)를 사용해야 합니다.
const generateSecureToken = () => {
const storage = new Uint32Array(1);
// 브라우저의 암호화 모듈을 통해 무작위 비트 채우기
self.crypto.getRandomValues(storage);
return storage[0];
};
const secureToken = generateSecureToken();
crypto.getRandomValues()는 운영체제 수준에서 수집한 엔트로피를 기반으로 하여, 의사 난수 생성기(PRNG)인 Math.random()과 달리 암호학적으로 안전한 난수 생성기(CSPRNG)의 특성을 가집니다. 타입드 배열(Uint32Array)을 버퍼로 전달하여 안전한 비트열을 채워 넣습니다.