Abseil Random Seeding·Entropy
#기본은 OS entropy
absl::BitGen bg;는 OS의 entropy source(/dev/urandom, Windows BCryptGenRandom)에서 시드를 받는다. 사용자가 시드 코드를 쓰지 않는 것이 권장 방식이다.
#include "absl/random/random.h"
absl::BitGen bg; // 자동 시드 — 매 프로세스, 매 객체 다른 시퀀스OS entropy는 cryptographically strong하므로 시드 자체는 예측 불가 다. 다만 BitGen 자체가 cryptographic이 아니라는 점은 별개다(시드만 안전).
#결정적 재현 — SeedSeq
테스트 또는 재현 가능한 시뮬레이션에는 명시 시드를 쓴다.
absl::SeedSeq seed{1, 2, 3, 4};absl::BitGen bg(seed);
absl::SeedSeq same{1, 2, 3, 4};absl::BitGen bg2(same);// bg와 bg2는 동일 시퀀스absl::SeedSeq는 std::seed_seq 호환 컨셉이다. 정수 시퀀스로 초기화하고, 엔진이 내부적으로 큰 entropy pool을 채울 만큼 stretch한다.
#SeedGen — sequence 헬퍼
여러 BitGen을 같은 base seed에서 파생할 때.
absl::SeedSeq seed{42};absl::BitGen bg1(seed);absl::BitGen bg2(seed); // bg1과 동일 시퀀스 ❌ 보통 원하지 않음각 BitGen이 독립 이어야 하면 base seed를 stretch 한 뒤 나눠 쓴다.
absl::SeedSeq base{42};std::vector<std::uint32_t> spread(8);base.generate(spread.begin(), spread.end());
absl::BitGen bg1(absl::SeedSeq(spread.begin(), spread.begin() + 4));absl::BitGen bg2(absl::SeedSeq(spread.begin() + 4, spread.end()));// bg1, bg2 독립#시드 누출 — 회피
시드 값을 로그에 남기는 것은 예측 가능성 을 만든다.
// 회피 — 시드 노출absl::SeedSeq seed{absl::ToUnixNanos(absl::Now())}; // 현재 시각 — 추측 가능LOG(INFO) << "seed = " << seed_value;
// Good — OS entropy 그대로absl::BitGen bg;시뮬레이션 재현성을 위해 시드를 저장해야 하면 별도 채널(설정 파일, 안전 저장소)로 관리하고 로그에는 hash나 ID만 남긴다.
#비-cryptographic 한계
BitGen의 시드가 안전하더라도, 출력으로부터 상태를 역추적할 수 있다. 충분한 출력을 본 공격자는 다음 출력을 예측한다.
| 용도 | BitGen 사용 가능? |
|---|---|
| 게임 로직 random | ✓ |
| 캐시 키 무작위화 | ✓ |
| A/B 테스트 분기 | ✓ |
| 부하 시뮬레이션 | ✓ |
| 토큰 생성 | ✗ — 예측 가능 |
| 세션 ID | ✗ — 예측 가능 |
| 암호 키 | ✗ — 예측 가능 |
| Nonce | ✗ — 예측 가능 |
암호학적 random이 필요하면 boringssl::RAND_bytes 또는 getrandom(2)을 직접 호출한다.
// 토큰 생성 — BitGen 절대 안 됨unsigned char token[32];ABSL_CHECK_EQ(RAND_bytes(token, sizeof(token)), 1);#thread별 BitGen
thread_local은 자동 시드 BitGen과 잘 맞는다.
thread_local absl::BitGen tls_bg;
int RandomShard(int n) { return absl::Uniform(tls_bg, 0, n);}각 스레드가 독립 entropy로 시드된 BitGen을 가진다. 락 없음, 시퀀스 충돌 없음.
#분산 시뮬레이션의 재현성
여러 worker가 같은 시뮬레이션을 재현하려면 worker ID + base seed로 결정.
absl::BitGen MakeWorkerGen(int64_t base_seed, int worker_id) { absl::SeedSeq seed{ static_cast<std::uint32_t>(base_seed >> 32), static_cast<std::uint32_t>(base_seed & 0xffffffff), static_cast<std::uint32_t>(worker_id), }; return absl::BitGen(seed);}같은 base_seed로 시뮬레이션을 두 번 돌리면 모든 worker가 동일 시퀀스를 본다.
#seed 자료형 호환
absl::SeedSeq는 표준의 std::seed_seq와 동등하게 동작하므로 std 엔진에도 쓸 수 있다.
absl::SeedSeq seed{1, 2, 3};std::mt19937 mt(seed); // OKabsl::BitGen bg(seed); // OK반대로 std::seed_seq도 absl::BitGen에 넣을 수 있다. 두 시스템이 호환된다.
#작은 예시 — 재현 가능한 부하 테스트
ABSL_FLAG(int64_t, sim_seed, 0, "0 → OS entropy; non-zero → reproducible");
absl::BitGen MakeSimGen() { int64_t s = absl::GetFlag(FLAGS_sim_seed); if (s == 0) { return absl::BitGen{}; // 자동 entropy } return absl::BitGen(absl::SeedSeq{ static_cast<std::uint32_t>(s >> 32), static_cast<std::uint32_t>(s & 0xffffffff), });}
int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); absl::BitGen bg = MakeSimGen();
LOG(INFO) << "sim_seed = " << (absl::GetFlag(FLAGS_sim_seed) == 0 ? "ENTROPY" : absl::StrCat(absl::GetFlag(FLAGS_sim_seed)));
RunSimulation(bg);}Flag 하나로 production-스타일과 재현 가능 모드를 토글한다.
#코드 리뷰 체크리스트
// 회피 — 약한 시드std::mt19937 bg(static_cast<unsigned>(std::time(nullptr)));
// Good — OS entropyabsl::BitGen bg;// 회피 — 매 호출 새 BitGenint Pick() { absl::BitGen bg; // ❌ 매번 시드 갱신 = 비싸고 thread 충돌 가능 return absl::Uniform(bg, 0, 100);}
// Good — thread_localthread_local absl::BitGen bg;int Pick() { return absl::Uniform(bg, 0, 100); }// 회피 — 토큰 생성에 BitGenstd::string Token() { absl::BitGen bg; return absl::StrCat(absl::Uniform<uint64_t>(bg, 0, ~0ull)); // ❌ 예측 가능}
// Good — 암호학적 randomstd::string Token() { unsigned char b[16]; RAND_bytes(b, sizeof(b)); return absl::BytesToHexString({reinterpret_cast<char*>(b), sizeof(b)});}#정리
- 기본 —
absl::BitGen bg;로 OS entropy 시드. 시드 코드를 쓰지 않는 것이 안전. - 결정적 재현 —
absl::SeedSeq로 명시 시드. 시뮬레이션·테스트 한정. - 여러 BitGen 독립 — base seed를 stretch 후 나눠 분배.
- 시드 값은 로그에 남기지 않음(예측 가능성을 만든다).
- 토큰·세션·암호 키 — BitGen 사용 금지.
RAND_bytes/getrandom사용.
#다음 장 예고
Part 9-01: int128 / uint128 — 128비트 정수.
#관련 항목
Abseil Code Review · 48 of 79
- 1 Abseil Code Review — Google production-grade C++ 라이브러리 분석
- 2 Abseil 개요 — Google이 std를 보완한 이유
- 3 Abseil 설계 철학 — std 호환과 추가 기능의 균형
- 4 Abseil 빌드와 의존성 — Bazel vs CMake
- 5 Abseil LTS vs HEAD 릴리스 모델 분석
- 6 Abseil Versioning과 ABI 호환성 정책
- 7 Abseil 매크로 — ABSL_HAVE_*·ABSL_ATTRIBUTE_*
- 8 Abseil ABSL_PREDICT_TRUE/FALSE — branch hint
- 9 absl::LogSeverity — 로그 레벨 타입
- 10 Abseil type_traits — negation·conjunction·void_t
- 11 Abseil Conformance·Policy 분석
- 12 Abseil Memory utilities 분석
- 13 Abseil raw_logging — heap-free 로깅
- 14 Abseil thread_annotations — clang TSA 통합
- 15 absl::Status — exception-free error handling
- 16 absl::StatusOr<T> — 값 또는 에러
- 17 absl status_macros — ASSIGN_OR_RETURN·RETURN_IF_ERROR
- 18 absl::Status payload — 구조화된 에러 컨텍스트
- 19 absl::Status ↔ exception 변환 패턴
- 20 absl::string_view — non-owning 문자열 참조
- 21 absl::string_view 함정 — dangling·c_str·임시 객체
- 22 absl::StrCat — 가변 인자 문자열 연결과 AlphaNum
- 23 absl::StrSplit — Delimiter·Predicate·컨테이너 변환
- 24 absl::StrJoin — 컨테이너 결합과 Formatter
- 25 absl::StrFormat — type-safe printf·FormatSpec
- 26 Abseil ASCII 함수 — locale-free 분류·대소문자 변환
- 27 Abseil Escape — CEscape·HexEscape·Base64
- 28 absl::flat_hash_map — Swiss Table 기반 hash map
- 29 absl::flat_hash_set — set 버전 Swiss Table
- 30 absl::node_hash_map — stable pointer가 필요할 때
- 31 absl::btree_map — sorted·cache-friendly B-tree
- 32 absl::FixedArray — 런타임 크기 stack 배열
- 33 absl::InlinedVector — small buffer optimization
- 34 Abseil Swiss Table internals — control byte·SIMD probing
- 35 absl::Mutex — reader-writer·fairness·deadlock 검출
- 36 absl::Mutex Conditional Critical Section — Await로 cv 없애기
- 37 absl::Notification — once-only signal
- 38 absl::BlockingCounter·Barrier — 다중 thread 조율
- 39 absl::Mutex annotations — clang thread-safety로 race를 컴파일 타임에
- 40 absl::Time·Duration 분석 — 단단한 type
- 41 absl::Time Format·Parse
- 42 absl::CivilTime 분석
- 43 absl::time_zone 분석
- 44 absl::Time mocking — 테스트 친화 시간
- 45 absl::BitGen — 모던 난수 생성기
- 46 Abseil Random Distributions — Uniform·Exponential
- 47 Abseil Mocking Random — 테스트 결정성
- 48 Abseil Random Seeding·Entropy
- 49 absl::int128·uint128 분석
- 50 absl::bits — popcount·countl_zero
- 51 absl::optional vs std::optional
- 52 absl::variant 분석
- 53 absl::span 분석
- 54 absl::any 분석
- 55 absl::compare — three-way 비교
- 56 Abseil utility — apply·in_place
- 57 Abseil AbslHashValue 분석
- 58 Abseil HashState chaining
- 59 Abseil Custom hashable 구현
- 60 Abseil LOG·VLOG·CHECK 분석
- 61 Abseil LogSink 분석
- 62 Abseil LogEntry·structured logging
- 63 Abseil Stack trace·failure_signal_handler
- 64 ABSL_FLAG 정의 분석
- 65 Abseil ParseCommandLine 동작
- 66 Abseil Flag introspection·validation
- 67 Google 스타일의 Abseil 사용 패턴
- 68 Abseil 자주 보는 anti-pattern
- 69 std → absl 마이그레이션 전략
- 70 absl::Cleanup — 함수 종료 시 실행 보장
- 71 Abseil algorithm container 확장 — c_sort·c_find_if·c_count_if
- 72 absl::function_ref와 any_invocable — 함수 객체 전달의 두 축
- 73 absl::bind_front와 Overload — 함수 객체 보조 도구
- 74 absl::Cord — 분산 시스템용 대용량 문자열
- 75 absl::from_chars·SimpleAtoi — 빠른 숫자 변환
- 76 absl::Cord vs std::string — 선택 기준과 메모리 프로파일
- 77 absl::GetStackTrace와 Symbolize — crash 시 readable stack
- 78 absl::ComputeCrc32c — 하드웨어 가속 체크섬
- 79 absl::PeriodicSampler — 적응형 샘플링·jitter 회피
관련 글
Abseil Mocking Random — 테스트 결정성
MockingBitGen — 분포 호출의 결과값을 결정적으로 강제. flaky random 테스트를 끝낸다.
같은 시리즈에서 이어 읽기
Abseil Random Distributions — Uniform·Exponential
absl::Uniform, Gaussian, Exponential, Poisson 등 — std::*_distribution의 클래스 객체를 함수 호출로 평탄화.
같은 시리즈에서 이어 읽기
absl::BitGen — 모던 난수 생성기
absl::BitGen — std::mt19937 + std::uniform_int_distribution의 길고 verbose한 조합을 단일 호출로 압축한 random engine.
같은 시리즈에서 이어 읽기