
객체 지향의 함정, 불변성을 무너뜨리는 잘못된 상속 설계와 그 대안을 파헤칩니다.
단순히 가변 리스트를 래핑하는 것만으로는 완벽한 불변성을 보장할 수 없습니다. 이 아티클은 코틀린의 상속 구조에서 발생할 수 있는 불변성 제약의 허점을 지적하며, 안전한 시스템 구축을 위한 가변/불변 객체의 올바른 계층 설계 원칙을 제시합니다.
도메인 모델의 무결성이 중요한 대규모 시스템 설계자에게 추천하며, 클래스 정의 시 'open' 키워드를 남발하기보다 'Composition'이나 인터페이스 기반 설계를 우선시할 것을 권장합니다.
클래스에 'Immutable'이라는 명칭을 붙여 불변성을 의도하더라도 클래스를 상속 가능(open)하게 설계하면, 자식 클래스에서 내부 필드에 접근하거나 메서드를 오버라이드하여 객체의 가변성을 허용할 수 있는 보안 허점이 발생한다.
불변성을 보장해야 하는 클래스는 기본적으로 상속을 금지(final)하고, 가변 객체와 불변 객체 간의 공통 분모가 필요한 경우에는 오직 조회 기능만 포함된 '읽기 전용(Read-only)' 인터페이스를 부모로 두는 구조로 개선해야 한다.
상속으로 인한 불변성 훼손 가능성을 근본적으로 차단함으로써 코드의 예측 가능성을 높이고, 런타임에 발생할 수 있는 예기치 못한 상태 변경 버그를 방지할 수 있다.
Trade-off
클래스 확장이 제한되어 상속을 통한 코드 재사용성이 낮아질 수 있으며, 읽기 전용 계층을 추가하는 과정에서 초기 설계 비용과 클래스 구조의 복잡도가 다소 증가할 수 있다.
객체 생성 후 내부 상태가 변하지 않는 특성으로, 멀티스레드 환경에서 안전하고 코드의 사이드 이펙트를 최소화하는 핵심 원칙이다.
Kotlin에서 하위 클래스가 해당 클래스를 상속받아 기능을 확장하거나 메서드를 재정의할 수 있도록 허용하는 키워드이다.
수정 메서드가 없는 '읽기 전용' 상태와 상태 변경 자체가 불가능한 '불변' 상태를 구분하는 설계 개념이다.








