블로그로 돌아가기
Javascript

javascript object freeze로 불변 객체 만들기: 개념과 실무 적용

javascript object freeze를 사용해 객체 불변성을 확보하는 방법과 실무 예제, 깊은 동결 접근법, 성능·보안 고려사항, 적용 체크리스트까지 실무 중심으로 정리합니다.

immutableobject-freezejavascript-best-practicesstate-management
Javascript Object.freeze를 사용해 객체 불변성을 구현하는 코드와 설명 이미지

javascript object freeze이 필요한 상황

javascript object freeze는 런타임에서 객체의 속성을 변경하지 못하도록 잠글 때 사용하는 네이티브 방법입니다. 이 글에서는 javascript object freeze를 통해 어떤 이점을 얻을 수 있는지, 실무에서 어떻게 적용하는지, 그리고 깊은 동결과 관련된 구현 및 주의점을 모두 다룹니다. 독자는 이 글을 통해 불변 객체를 만들고 유지하는 실무 코드 예제, 판단 기준 표, 체크리스트를 얻어 바로 적용할 수 있습니다.

javascript object freeze 핵심 개념

Object.freeze(obj)는 객체의 기존 속성을 변경할 수 없게 만들고, 속성 추가·삭제를 막습니다. 단, 얕은(freezing is shallow) 동결이므로 중첩된 객체 내부는 그대로 변경될 수 있습니다. 또한, non-strict 모드에서는 변경 시 에러가 발생하지 않지만 실패합니다. strict 모드에서는 TypeError가 발생할 수 있습니다.

주요 포인트:

  • 얕은 동결: 최상위 속성만 고정
  • 속성 속성값이 객체인 경우 내부 변경은 가능
  • 프로토타입 변경은 막지 않음(객체의 프로토타입을 수정하면 동작이 영향을 받을 수 있음)

javascript object freeze 실무 예제

간단한 사용 예제:

// 예제: 얕은 동결 const config = { apiUrl: 'https://api.example.com', retries: 3 }; Object.freeze(config); config.retries = 5; // 변경되지 않음 (strict 모드 아님) console.log(config.retries); // 3 // 중첩 객체의 문제 const state = { user: { name: 'Alice' } }; Object.freeze(state); state.user.name = 'Bob'; // 가능: 얕은 동결 console.log(state.user.name); // Bob

깊은 동결 유틸 구현 예제:

// deepFreeze 함수: 순환 참조는 간단히 처리(visited Set 사용) function deepFreeze(obj, visited = new Set()) { if (obj === null || typeof obj !== 'object') return obj; if (visited.has(obj)) return obj; visited.add(obj); Object.getOwnPropertyNames(obj).forEach((prop) => { const value = obj[prop]; if (typeof value === 'object' && value !== null) { deepFreeze(value, visited); } }); return Object.freeze(obj); } const nested = { a: { b: { c: 1 } } }; deepFreeze(nested); nested.a.b.c = 2; // 변경되지 않음 console.log(nested.a.b.c); // 1

언제 쓰면 좋고 언제 피해야 할까

언제 쓰면 좋은가:

  • 공유 상태를 외부 변경으로부터 보호하고 싶을 때
  • 라이브러리/공용 설정 객체를 안전하게 노출할 때
  • 간단한 불변성 보장을 통해 디버깅과 추적을 쉽게 하고 싶을 때

언제 피해야 할까:

  • 객체가 매우 크고 깊은 구조라 성능 오버헤드가 우려될 때
  • 빈번한 변경이 필요한 상태(예: 빈번히 업데이트되는 로컬 상태)
  • 프레임워크나 라이브러리(특히 렌더러 내부)에서 내부 최적화를 방해할 수 있는 경우

판단 기준 표

구분항목1항목2항목3
내용간단한 설정 객체공유 읽기 전용 데이터깊은 중첩 상태에는 주의

실무 적용 팁과 패턴

  • 작은 설정 객체에 Object.freeze를 사용하고, 애플리케이션 상태는 불변 라이브러리(예: Immer, Immutable.js)로 관리.
  • API 응답을 바로 freeze하지 말고, 필요한 필드만 추출 후 freeze.
  • 테스트에서 내부를 조작해야 하는 경우를 대비해 테스트 전용 훅으로 복제해서 사용.

성능·보안·운영 주의점

성능:

  • Object.freeze는 객체의 속성을 잠그는 작업으로 큰 객체나 많은 객체에 반복 적용하면 비용 발생.
  • deepFreeze는 재귀 탐색로직 때문에 순환 참조 처리 및 성능 최적화 필요.

보안:

  • Object.freeze는 런타임에서 변경을 방지하지만, 클라이언트 측에서 완전한 보안 수단은 아님. 민감 데이터는 서버에서 보호해야 함.

운영:

  • 프로덕션 소스맵 혹은 디버그 로그에서 freeze로 발생한 TypeError가 발생할 수 있으니 에러 핸들링을 설계할 것.

실무 체크리스트

  • 객체가 읽기 전용이어야 하는가 판단
  • 객체 크기(깊이)와 빈도(동결 호출 횟수) 평가
  • deepFreeze 필요한 경우 순환 참조 처리 설계
  • 테스트에서의 복제/모킹 방안 준비
  • 프레임워크/라이브러리 호환성 확인

javascript object freeze 적용 비교 표

구분사용 이유장점단점
Object.freeze간단한 얕은 불변성 필요네이티브, 간단 사용중첩 객체는 보호 안 됨
deepFreeze(유틸)중첩 객체 불변성 필요모든 중첩 잠금 가능성능 비용, 순환 처리 필요
Immer/Immutable복잡한 상태 관리편의성, 성능 최적화 옵션러닝커브, 의존성 추가

자주 묻는 질문

Q1: Object.freeze가 완전한 불변성을 보장하나요? A1: 아니요. Object.freeze는 얕은 동결이라 중첩된 객체는 여전히 변경될 수 있습니다. 완전한 불변성이 필요하면 deepFreeze나 불변성 라이브러리를 고려하세요.

Q2: Object.freeze한 객체를 JSON.stringify하면 문제가 있나요? A2: 아닙니다. Object.freeze는 직렬화에 영향을 주지 않습니다. 다만 함수나 심볼 같은 직렬화 불가능한 값은 원래와 동일한 제약을 받습니다.

Q3: deepFreeze는 순환 참조를 어떻게 처리해야 하나요? A3: 순환 참조가 있는 객체는 visited Set(또는 WeakSet)을 사용해 이미 처리한 객체를 건너뛰어야 합니다. 위 예제의 deepFreeze는 이를 반영합니다.

Q4: 프레임워크(예: React)에서 Object.freeze를 사용해도 괜찮나요? A4: 작은 설정이나 읽기 전용 상수에는 괜찮습니다. 하지만 리액트 상태 관리에는 Immer 같은 불변성 라이브러리가 더 적합할 수 있습니다.

정리

  • Object.freeze는 얕은 동결로 최상위 속성의 변경을 막는다.
  • 중첩 객체의 불변성은 deepFreeze 또는 불변성 라이브러리로 보완해야 한다.
  • 성능과 순환 참조를 고려해 적용 범위를 제한하고 체크리스트를 활용하라.
  • 실무에서는 설정값 보호, 라이브러리 API 안정성 확보 등에 유용하다.
javascript object freeze로 객체 불변성 확보하는 방법 | RYUSLOG DEV