--- category: Unified tags: [auto-consolidated, technical-documentation] title: [[Readonly 유틸리티 타입|Readonly 유틸리티 타입]] last_updated: 2026-05-02 --- # [[Readonly 유틸리티 타입|Readonly 유틸리티 타입]] ## 📌 Brief Summary > Readonly 유틸리티 타입(`Readonly`)은 TypeScript에서 특정 객체 타입의 모든 속성에 `readonly` 수식어를 추가하여 초기화 이후 값을 재할당할 수 없도록 변환하는 기능입니다[1, 2]. 이는 런타임 성능 저하 없이 컴파일 타임에만 엄격하게 불변성을 강제하여, 의도치 않은 데이터 변형으로 인한 버그를 사전에 차단합니다[3, 4]. 단, 최상위 속성에만 적용되는 얕은(shallow) 불변성만을 제공하므로, 중첩된 객체를 완전히 동결하려면 재귀적인 형태의 딥 리드온리(Deep Readonly) 패턴이 별도로 필요합니다[5, 6]. --- > `readonly`는 TypeScript에서 객체의 속성이나 배열, 튜플이 초기화된 이후에 수정되지 않도록 방지하는 수식어이자 유틸리티 타입입니다 [1-3]. 변수의 재할당을 막는 `const`와 달리 객체 내부 구조의 불변성을 제어하며, 런타임 오버헤드 없이 컴파일 타임에 오류를 잡아내어 코드의 안정성과 예측 가능성을 높입니다 [2, 4, 5]. ## 📖 Core Content - **기본 작동 원리와 문법:** `Readonly`는 주어진 타입 `T`의 모든 프로퍼티를 읽기 전용으로 매핑합니다[1, 2]. 설정이나 API 응답, 상태 관리 리듀서 등 앱 내내 값이 유지되어야 하는 객체를 보호할 때 주로 사용됩니다[7, 8]. TypeScript 코드가 컴파일된 후에는 관련 어노테이션이 모두 사라지므로 실행 시점(Runtime)에는 어떠한 오버헤드도 발생시키지 않습니다[3, 9]. - **유사 개념과의 차이점:** - **`const`와의 차이:** `const`는 변수 자체의 재할당을 막지만 참조된 객체의 내부 속성 변경은 막지 못합니다. 반면 `readonly`는 변수 바인딩이 아닌 객체 속성이나 배열 요소 자체의 변경을 제한합니다[10, 11]. - **`Object.freeze()`와의 차이:** `Object.freeze()`는 런타임에 객체를 동결하며 실행 성능에 비용을 청구하지만, `readonly`는 컴파일 타임에 타입 시스템을 통해서만 수정을 금지합니다[4, 12]. - **배열에서의 활용:** 객체뿐만 아니라 배열에도 `ReadonlyArray` 또는 `readonly T[]` 형태로 사용할 수 있습니다[13, 14]. 이렇게 선언된 배열은 요소의 재할당이 불가능할 뿐만 아니라, `push()`, `pop()` 등 원본을 수정하는 메서드가 타입 정의에서 완전히 제거됩니다[15, 16]. - **한계점 및 우회 취약점 (Gotcha):** - **얕은 불변성(Shallow Immutability):** `Readonly`는 1단계 깊이의 속성에만 작용합니다. 객체 내부의 중첩된 객체 속성은 여전히 수정이 가능하며, 이를 해결하기 위해서는 매핑된 타입과 조건부 타입을 결합한 커스텀 `[[DeepReadonly|DeepReadonly]]` 유틸리티를 구현해야 합니다[5, 6, 17]. - **에일리어싱(Aliasing) 문제:** `readonly` 타입의 데이터를, 수정 가능한 타입(mutable)을 매개변수로 받는 함수에 전달할 경우 타입 호환성 규칙에 의해 통과될 수 있습니다. 이로 인해 함수 내부에서 원본 데이터가 변경되는 우회 돌연변이가 발생할 수 있습니다[18, 19]. --- * **작동 방식 및 성능:** `readonly`는 전적으로 컴파일 타임에만 동작하는 기능으로, 컴파일 후 생성된 [[JavaScript|JavaScript]] 코드에서는 흔적이 사라집니다 [2, 6]. 따라서 성능에 어떠한 런타임 오버헤드도 주지 않으면서 속성의 불변성을 강제할 수 있습니다 [2, 5, 6]. * **객체 및 클래스에서의 활용:** 인터페이스나 타입 별칭, 클래스의 속성에 `readonly`를 지정할 수 있습니다. 클래스에서는 선언 시점이나 생성자(constructor) 내부에서만 초기화가 가능하며, 그 이후에 값을 수정하려고 시도하면 컴파일러가 에러를 발생시킵니다 [7, 8]. 이는 시스템의 고유 식별자(ID)나 환경 설정 값처럼 생명 주기 동안 변하지 않아야 하는 데이터를 보호할 때 유용합니다 [7, 9]. * **배열과 튜플의 보호:** 배열을 `readonly T[]` 또는 `ReadonlyArray`로 선언하면 `push`, `pop`, 요소 직접 재할당 등 배열을 변이시키는 모든 메서드와 작업이 타입 시스템에서 제거되어 안전하게 보호됩니다 [10-12]. 튜플 역시 각 위치의 값을 고정하기 위해 `readonly`를 적용할 수 있습니다 [10]. * **const 및 Object.freeze()와의 비교:** * `const`: 런타임에 변수 자체의 재할당을 방지하지만, 참조된 객체 내부 속성의 변경은 막지 못합니다 [4, 13, 14]. * `Object.freeze()`: 런타임에 객체의 얕은 수정을 차단하며 성능 비용이 발생합니다 [5, 14, 15]. * `readonly`: 컴파일 타임에 객체/배열 내부 속성의 변경을 타입 레벨에서 차단하여, 실행 전 코드 작성 단계에서 안전을 보장합니다 [4, 5, 14]. * **얕은 불변성(Shallow Immutability)의 한계:** 기본적인 `readonly` 수식어나 `Readonly` 유틸리티 타입은 최상위 레벨의 속성에만 얕게 적용됩니다 [16-18]. 즉, 중첩된 내부 객체는 여전히 수정될 수 있습니다 [17, 18]. 완벽한 깊은 불변성을 원한다면 재귀적으로 속성을 잠그는 커스텀 `[[DeepReadonly|DeepReadonly]]` 유틸리티 타입을 별도로 구현해야 합니다 [17-19]. ## ⚖️ Trade-offs & Caveats - **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요. - **정책 변화:** Programming & Language 분야의 자동 자산화 수행. --- - **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요. - **정책 변화:** Programming & Language 분야의 자동 자산화 수행. ## 🔗 Knowledge Connections - **Related Topics:** [[불변성 (Immutability)|불변성(Immutability]], 매핑된 타입(Mapped Types), [[DeepReadonly|DeepReadonly]] - **Projects/Contexts:** 변경 불가한 외부 API 응답 데이터 모델링, 상태 관리 시스템(Redux 리듀서 등)의 데이터 무결성 보장, 그리고 애플리케이션의 전역 환경 설정(Configuration) 객체 보호 맥락에서 광범위하게 쓰입니다[8, 17]. - **Contradictions/Notes:** TypeScript의 에일리어싱 한계로 인해 `readonly` 데이터가 `mutable` 타입을 요구하는 함수로 전달되어 내부에서 값이 변경될 위험이 존재하므로, 완전한 불변성을 지키려면 함수 시그니처 전반에 걸쳐 읽기 전용 파라미터를 강제하거나 데이터의 복사본을 넘기는 설계가 필요합니다[18, 19]. 또한, 모든 `readonly` 속성을 다시 수정 가능하게 되돌려야 할 때는 `Mutable`이라는 커스텀 헬퍼 타입을 만들어 매핑 수식어를 제거(`-readonly`)하는 방식으로 해결할 수 있습니다[6]. --- *Last updated: 2026-04-18* --- --- - **Related Topics:** const, Object.freeze(), ReadonlyArray, [[DeepReadonly|DeepReadonly]], Utility Types - **Projects/Contexts:** [[State|State]] [[Management|Management]], Configuration Objects, API Responses - **Contradictions/Notes:** `readonly`는 데이터 변경을 막는 훌륭한 타입 제어 장치지만, 컴파일러는 `readonly` 데이터를 변경 가능(mutable)한 매개변수를 받는 함수에 전달하는 것(Aliasing)을 허용하므로 이로 인한 우회적 변이(mutation)가 발생할 수 있다는 구조적 맹점을 주의해야 합니다 [20, 21]. --- *Last updated: 2026-04-18* ---