Files
2nd/10_Wiki/Topics/readonly.md
T

7.8 KiB

category, tags, title, last_updated
category tags title last_updated
Unified
auto-consolidated
technical-documentation
Readonly 유틸리티 타입|Readonly 유틸리티 타입
2026-05-02

Readonly 유틸리티 타입

📌 Brief Summary

Readonly 유틸리티 타입(Readonly<T>)은 TypeScript에서 특정 객체 타입의 모든 속성에 readonly 수식어를 추가하여 초기화 이후 값을 재할당할 수 없도록 변환하는 기능입니다[1, 2]. 이는 런타임 성능 저하 없이 컴파일 타임에만 엄격하게 불변성을 강제하여, 의도치 않은 데이터 변형으로 인한 버그를 사전에 차단합니다[3, 4]. 단, 최상위 속성에만 적용되는 얕은(shallow) 불변성만을 제공하므로, 중첩된 객체를 완전히 동결하려면 재귀적인 형태의 딥 리드온리(Deep Readonly) 패턴이 별도로 필요합니다[5, 6].


readonly는 TypeScript에서 객체의 속성이나 배열, 튜플이 초기화된 이후에 수정되지 않도록 방지하는 수식어이자 유틸리티 타입입니다 [1-3]. 변수의 재할당을 막는 const와 달리 객체 내부 구조의 불변성을 제어하며, 런타임 오버헤드 없이 컴파일 타임에 오류를 잡아내어 코드의 안정성과 예측 가능성을 높입니다 [2, 4, 5].

📖 Core Content

  • 기본 작동 원리와 문법: Readonly<T>는 주어진 타입 T의 모든 프로퍼티를 읽기 전용으로 매핑합니다[1, 2]. 설정이나 API 응답, 상태 관리 리듀서 등 앱 내내 값이 유지되어야 하는 객체를 보호할 때 주로 사용됩니다[7, 8]. TypeScript 코드가 컴파일된 후에는 관련 어노테이션이 모두 사라지므로 실행 시점(Runtime)에는 어떠한 오버헤드도 발생시키지 않습니다[3, 9].

  • 유사 개념과의 차이점:

    • const와의 차이: const는 변수 자체의 재할당을 막지만 참조된 객체의 내부 속성 변경은 막지 못합니다. 반면 readonly는 변수 바인딩이 아닌 객체 속성이나 배열 요소 자체의 변경을 제한합니다[10, 11].
    • Object.freeze()와의 차이: Object.freeze()는 런타임에 객체를 동결하며 실행 성능에 비용을 청구하지만, readonly는 컴파일 타임에 타입 시스템을 통해서만 수정을 금지합니다[4, 12].
  • 배열에서의 활용: 객체뿐만 아니라 배열에도 ReadonlyArray<T> 또는 readonly T[] 형태로 사용할 수 있습니다[13, 14]. 이렇게 선언된 배열은 요소의 재할당이 불가능할 뿐만 아니라, push(), pop() 등 원본을 수정하는 메서드가 타입 정의에서 완전히 제거됩니다[15, 16].

  • 한계점 및 우회 취약점 (Gotcha):

    • 얕은 불변성(Shallow Immutability): Readonly<T>는 1단계 깊이의 속성에만 작용합니다. 객체 내부의 중첩된 객체 속성은 여전히 수정이 가능하며, 이를 해결하기 위해서는 매핑된 타입과 조건부 타입을 결합한 커스텀 [[DeepReadonly|DeepReadonly]]<T> 유틸리티를 구현해야 합니다[5, 6, 17].
    • 에일리어싱(Aliasing) 문제: readonly 타입의 데이터를, 수정 가능한 타입(mutable)을 매개변수로 받는 함수에 전달할 경우 타입 호환성 규칙에 의해 통과될 수 있습니다. 이로 인해 함수 내부에서 원본 데이터가 변경되는 우회 돌연변이가 발생할 수 있습니다[18, 19].

  • 작동 방식 및 성능: readonly는 전적으로 컴파일 타임에만 동작하는 기능으로, 컴파일 후 생성된 JavaScript 코드에서는 흔적이 사라집니다 [2, 6]. 따라서 성능에 어떠한 런타임 오버헤드도 주지 않으면서 속성의 불변성을 강제할 수 있습니다 [2, 5, 6].

  • 객체 및 클래스에서의 활용: 인터페이스나 타입 별칭, 클래스의 속성에 readonly를 지정할 수 있습니다. 클래스에서는 선언 시점이나 생성자(constructor) 내부에서만 초기화가 가능하며, 그 이후에 값을 수정하려고 시도하면 컴파일러가 에러를 발생시킵니다 [7, 8]. 이는 시스템의 고유 식별자(ID)나 환경 설정 값처럼 생명 주기 동안 변하지 않아야 하는 데이터를 보호할 때 유용합니다 [7, 9].

  • 배열과 튜플의 보호: 배열을 readonly T[] 또는 ReadonlyArray<T>로 선언하면 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<T> 유틸리티 타입은 최상위 레벨의 속성에만 얕게 적용됩니다 [16-18]. 즉, 중첩된 내부 객체는 여전히 수정될 수 있습니다 [17, 18]. 완벽한 깊은 불변성을 원한다면 재귀적으로 속성을 잠그는 커스텀 [[DeepReadonly|DeepReadonly]] 유틸리티 타입을 별도로 구현해야 합니다 [17-19].

⚖️ Trade-offs & Caveats

  • 과거 데이터와의 충돌: 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
  • 정책 변화: Programming & Language 분야의 자동 자산화 수행.

  • 과거 데이터와의 충돌: 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
  • 정책 변화: Programming & Language 분야의 자동 자산화 수행.

🔗 Knowledge Connections

  • Related Topics: 불변성 (Immutability), 매핑된 타입(Mapped Types), 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, Utility Types
  • Projects/Contexts: State Management, Configuration Objects, API Responses
  • Contradictions/Notes: readonly는 데이터 변경을 막는 훌륭한 타입 제어 장치지만, 컴파일러는 readonly 데이터를 변경 가능(mutable)한 매개변수를 받는 함수에 전달하는 것(Aliasing)을 허용하므로 이로 인한 우회적 변이(mutation)가 발생할 수 있다는 구조적 맹점을 주의해야 합니다 [20, 21].

Last updated: 2026-04-18