여러 스레드가 같은 설정 데이터를 읽고 한 항목만 바꿔 공유하려 합니다. 불변 데이터가 안전성과 비용에 미치는 영향은 무엇인가요?
잠깐, 답변을 보기 전에
먼저 내 말로 설명해 볼까요?
답변과 점검 포인트 펼치기답변 접기
구두 답변
정의를 외우기보다, 원리와 조건을 연결해 설명해 보세요.
불변 데이터는 만든 뒤 그 객체 자체를 바꾸지 않는 값입니다. 여러 실행 흐름이 같은 인스턴스를 읽을 때 누가 언제 필드를 바꿨는지 조정할 필요가 줄어들어, 잠금 누락이나 관찰 중간 상태를 예방하기 쉽습니다. 변경이 필요하면 새 값을 만들고 참조를 교체하므로 이전 버전을 읽던 코드와 새 버전을 읽는 코드가 서로의 객체를 훼손하지 않습니다.
하지만 final이나 읽기 전용 참조 하나만으로 깊은 불변이 되지는 않습니다. 불변 객체가 내부의 가변 목록을 그대로 노출하거나, 목록 원소가 변경 가능하면 외부에서 내부 상태를 바꿀 수 있습니다. 설정 스냅샷이라면 필드뿐 아니라 중첩된 목록·맵·원소까지 변경 경로를 닫고, 외부 입력을 받을 때 복사하거나 불변 값으로 변환하겠습니다. 읽기 전용 뷰는 호출자가 뷰를 통해 수정하지 못하게 할 뿐, 원본을 가진 다른 코드의 변경까지 막지는 않습니다.
매번 큰 트리를 통째로 복사하면 메모리와 CPU 비용이 커질 수 있습니다. 그래서 바뀌지 않은 하위 구조를 재사용하는 구조적 공유와 경로 복사를 사용할 수 있지만, 공유된 원소가 정말 불변이어야 안전합니다. 작은 설정은 전체 복사가 단순하고, 큰 문서나 빈번한 갱신은 공유 구조가 유리할 수 있습니다. 여러 스레드가 최신 스냅샷을 교체할 때는 참조 교체의 원자성뿐 아니라 새 객체의 초기화가 독자에게 보이는 안전한 공개와 이전 객체의 수명도 보장하고, 불변 객체가 여러 데이터를 저장하는 트랜잭션의 원자적 커밋까지 보장한다고 과장하지 않겠습니다.
깊은 불변과 공개 시점을 보장합니다
설정 객체가 내부 목록을 그대로 보관하면 생성 뒤 외부가 원본을 바꿀 수 있습니다. 생성 시 방어적으로 복사하고 중첩 맵·목록·원소까지 불변 값으로 변환해야 합니다. 새 스냅샷을 완전히 초기화한 뒤 참조를 교체해 독자가 반쯤 채워진 값을 보지 않게 하고, 언어의 메모리 공개 규칙도 확인합니다. 읽기 전용 뷰는 뷰를 통한 수정을 막을 뿐 원본 소유자의 변경까지 막지 않습니다.
구조적 공유의 비용을 계산합니다
큰 설정 트리에서 한 항목만 바뀔 때 바뀐 경로만 복사하고 나머지 불변 노드를 재사용하면 할당량을 줄일 수 있습니다. 하지만 공유 노드가 가변이면 과거 스냅샷도 오염되고, 갱신이 매우 잦으면 버전과 메모리 회수 비용이 전체 복사보다 커질 수 있습니다. 독자가 옛 버전을 읽는 동안 GC·참조 카운트·epoch 등 수명 보장을 적용합니다. 스냅샷 교체는 여러 DB 행이나 파일을 원자적으로 커밋하지 않으므로 외부 저장의 트랜잭션은 별도로 검증하겠습니다.
구체적인 경계 사례
독자는 설정을 사용할 때 루트 참조를 한 번만 얻어야 합니다. 최소값을 읽고 루트를 다시 얻어 최대값을 읽으면 두 객체가 각각 불변이어도 서로 다른 버전의 필드를 조합할 수 있습니다. 관련 필드를 같은 루트 아래 두고 요청 하나가 같은 스냅샷을 사용하게 하겠습니다. 여러 작성자가 같은 옛 루트에서 각각 변경해 새 루트를 게시하면 뒤 게시가 앞 변경을 잃을 수 있어 CAS 실패 후 재계산하거나 작성자를 직렬화해야 합니다.
수백만 노드 트리에서 한 리프를 바꾸는 경로 복사는 전체 크기보다 경로 높이에 비례하는 새 노드를 만들 수 있습니다. 다만 과거 루트를 감사 이력으로 계속 보관하면 공유되지 않은 옛 경로들이 남습니다. 보관 버전 수와 독자 수명을 측정하고 불변성의 읽기 편의와 장기 보관 메모리를 함께 평가하겠습니다.
득점 포인트
이해가 드러나는 지점을 확인해 보세요.
- 읽기 전용 참조와 깊은 불변, 공개 시점의 메모리 안전성을 구분한다.
- 전체 복사와 구조적 공유의 할당·GC·갱신 비용을 비교한다.
- 스냅샷 교체와 DB·외부 저장의 트랜잭션 원자성을 분리한다.
감점 포인트
놓치기 쉬운 조건과 오해를 짚어 보세요.
- final 참조나 읽기 전용 뷰만으로 중첩 데이터까지 불변이라고 한다.
- 불변 객체면 참조 교체·수명·외부 커밋 동기화가 불필요하다고 말한다.
- 구조적 공유가 항상 전체 복사보다 싸고 안전하다고 단정한다.
더 파고들 거리
하나 더 질문하며 이해의 범위를 넓혀 보세요.
- 불변 트리의 리프 하나를 수정합니다. 어느 경로만 복사하고 어떤 하위 노드를 공유할 수 있나요?
- 새 불변 snapshot을 게시한 뒤 옛 snapshot을 독자가 읽고 있습니다. 메모리 회수와 독자 수명은 어떻게 제한하나요?
- 가변 캐시를 불변 스냅샷으로 바꿀 때 갱신 빈도와 읽기 지연을 어떻게 측정할까요?
득점·감점 포인트는 학습용 자기 점검 기준이며, 특정 회사의 실제 채점표가 아닙니다.
원리부터 공부하고 싶다면
답변을 보충하는 개념·예제·슈도코드를 읽어 보세요.