# [[TypeScript Utility Types (Record, Readonly)|TypeScript Utility Types (Record, Readonly)]]

## 📌 Brief Summary
TypeScript의 유틸리티 타입인 `Readonly`와 `Record`는 타입 안전성을 높이고 데이터 구조를 효과적으로 모델링하는 데 사용됩니다. `Readonly<T>`는 주어진 객체 타입의 모든 속성을 읽기 전용으로 변환하여 컴파일 타임에 의도치 않은 상태 변경(돌연변이)을 방지합니다 [1, 2]. `Record<K, V>`는 키와 값의 타입을 지정하여 객체(사전) 구조를 안전하게 정의하는 데 쓰이며, 이 둘을 결합하면 불변의 키-값 맵을 구축할 수 있습니다 [3, 4].

## 📖 Core Content
- **`Readonly<T>` 유틸리티 타입**
  - **기능 및 목적:** `Readonly<T>`는 기존 타입 `T`를 변환하여 모든 속성을 초기화 이후 재할당할 수 없는 읽기 전용으로 만듭니다 [2, 5]. 이는 런타임 성능 오버헤드 없이 오직 컴파일 타임에 불변성을 강제하여 코드의 예측 가능성을 높이고 우발적인 변이로 인한 버그를 차단합니다 [1, 6].
  - **얕은 불변성(Shallow Immutability)의 한계:** TypeScript의 내장 `Readonly<T>`는 최상위 수준의 속성에만 적용됩니다 [7, 8]. 중첩된 객체나 배열은 여전히 수정이 가능하므로, 데이터의 완전한 불변성이 필요한 경우 개발자가 직접 재귀적으로 동작하는 `DeepReadonly` 유틸리티 타입을 정의하여 사용해야 합니다 [7, 8].
  - **구조적 우회(Aliasing) 취약점:** TypeScript의 구조적 타이핑 특성으로 인해 `readonly` 속성이 부여된 배열이나 객체를 가변 매개변수를 요구하는 함수에 넘길 때, 타입 호환이 성립되어 컴파일 에러 없이 전달될 수 있습니다 [9]. 이 경우 함수 내부에서 해당 객체의 값을 은연중에 수정할 위험이 있습니다 [9, 10].

- **`Record<K, V>` 유틸리티 타입**
  - `Record<K, V>`는 키 타입 `K`와 값 타입 `V`를 가진 객체 구조를 간단히 모방(analogue)하여 정의할 수 있게 해줍니다 [4, 11]. 
  - 특정 속성 목록이나 임의의 제네릭 객체를 다룰 때 활용도가 높으며, 예를 들어 `Record<string, unknown>`의 형태로 범용적인 객체를 모델링할 때 빈번하게 사용됩니다 [12].

- **`Readonly`와 `Record`의 시너지**
  - 두 유틸리티 타입을 결합(`Readonly<Record<K, V>>`)하면 속성이 절대 변하지 않는 불변의 키-값 맵(Immutable key-value map)을 구성할 수 있습니다 [3]. 이는 애플리케이션 전반에서 변하지 않아야 하는 정적인 사전(Static dictionaries)을 선언할 때 권장되는 패턴입니다 [3].

## 🔗 Knowledge Connections
- **Related Topics:** [[DeepReadonly|DeepReadonly]], TypeScript Structural Typing, Utility Types
- **Projects/Contexts:** `Readonly`는 앱의 설정(Configuration) 객체를 고정하거나 [13, 14], 상태 관리(Reducer) 시 불변성을 강제하고 [14], API로부터 받아온 응답 데이터가 로직 내에서 우발적으로 변조되는 것을 막는 컨텍스트에 널리 활용됩니다 [14].
- **Contradictions/Notes:** TypeScript의 `Readonly`는 런타임에 데이터를 얕게 동결시키는 자바스크립트의 `Object.freeze()`나 변수 자체의 재할당을 막는 `const`와 구별됩니다. `Readonly`는 런타임 비용이 전혀 없으며 컴파일 타임에만 엄격하게 속성 재할당을 검사합니다 [1, 15, 16].

---
*Last updated: 2026-04-18*