C# FrozenDictionary & FrozenSet — 읽기 전용 고성능 컬렉션
FrozenDictionary<TKey, TValue>와 FrozenSet<T>은 .NET 8에서 도입된 불변 고성능 컬렉션입니다. 생성 시 내부 구조를 최적화해 이후 조회 속도를 Dictionary보다 빠르게 만들지만, 생성 후 수정은 불가합니다.
1. 기본 사용
섹션 제목: “1. 기본 사용”using System.Collections.Frozen;
// FrozenDictionary 생성var config = new Dictionary<string, string>{ ["host"] = "localhost", ["port"] = "5432", ["db"] = "mydb"}.ToFrozenDictionary();
// 읽기 전용 — Add/Remove 없음string host = config["host"];bool hasPort = config.ContainsKey("port");
// FrozenSet 생성var allowedRoles = new[] { "admin", "editor", "viewer" } .ToFrozenSet(StringComparer.OrdinalIgnoreCase);
bool isAllowed = allowedRoles.Contains("Admin"); // true2. 성능 특성
섹션 제목: “2. 성능 특성”| 연산 | Dictionary | FrozenDictionary |
|---|---|---|
| 생성 | 빠름 | 느림 (최적화 포함) |
조회 (TryGetValue) | 기준 | 최대 ~2× 빠름 |
| 메모리 | 기준 | 비슷하거나 적음 |
| 수정 | 가능 | 불가 |
내부적으로 키 분포를 분석해 완전 해시 함수(perfect hashing)를 생성하거나, 작은 컬렉션은 선형 탐색을 사용합니다.
3. 실전 활용 패턴
섹션 제목: “3. 실전 활용 패턴”3.1 애플리케이션 시작 시 한 번 생성
섹션 제목: “3.1 애플리케이션 시작 시 한 번 생성”public static class CountryLookup{ private static readonly FrozenDictionary<string, Country> _map = LoadCountries().ToFrozenDictionary(c => c.Code);
public static Country? Find(string code) => _map.TryGetValue(code, out var c) ? c : null;}3.2 권한 체크용 FrozenSet
섹션 제목: “3.2 권한 체크용 FrozenSet”public class PermissionChecker(IEnumerable<string> permissions){ private readonly FrozenSet<string> _permissions = permissions.ToFrozenSet(StringComparer.Ordinal);
public bool Has(string permission) => _permissions.Contains(permission);}3.3 HTTP 메서드 매핑
섹션 제목: “3.3 HTTP 메서드 매핑”var methodHandlers = new Dictionary<string, Func<HttpContext, Task>>{ ["GET"] = HandleGet, ["POST"] = HandlePost, ["DELETE"] = HandleDelete,}.ToFrozenDictionary(StringComparer.OrdinalIgnoreCase);4. 커스텀 비교자
섹션 제목: “4. 커스텀 비교자”// 대소문자 무시 FrozenDictionaryvar headers = rawHeaders.ToFrozenDictionary( StringComparer.OrdinalIgnoreCase);
// 숫자 키 FrozenDictionaryvar statusMessages = new Dictionary<int, string>{ [200] = "OK", [404] = "Not Found", [500] = "Internal Server Error",}.ToFrozenDictionary();5. ImmutableDictionary와의 비교
섹션 제목: “5. ImmutableDictionary와의 비교”| 항목 | ImmutableDictionary | FrozenDictionary |
|---|---|---|
| 불변성 | ✓ | ✓ |
With 연산 | ✓ (새 인스턴스 반환) | ✗ |
| 조회 성능 | Dictionary보다 느림 | Dictionary보다 빠름 |
| 목적 | 불변 수정 가능 컬렉션 | 읽기 전용 최고 성능 |
6. 언제 사용해야 하나
섹션 제목: “6. 언제 사용해야 하나”- 애플리케이션 시작 시 데이터를 로드하고 이후 읽기만 하는 경우
- 핫 경로(hot path)에서 딕셔너리 조회 성능이 병목인 경우
- 설정 값, 코드 테이블, 권한 목록 등 정적 데이터
FrozenDictionary와 FrozenSet은 “한 번 빌드, 많이 읽기” 패턴에 최적화된 컬렉션입니다. 정적 데이터 조회가 빈번한 경우 Dictionary를 그대로 두지 말고 ToFrozenDictionary()로 교체하면 의미 있는 성능 향상을 얻을 수 있습니다.