Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript에서 Object.freeze()로 중첩된 객체까지 불변(Immutable)으로 만들 수 있을까?

Object.freeze() 메서드는 객체를 불변(immutable) 상태로 만들 수 있지만, 중첩된 객체(nested object)가 포함된 경우에는 내부 객체의 변경까지 막아주지 못합니다. Object.freeze()는 최상위 부모 객체에만 불변성을 제공할 뿐, 내부에 존재하는 자식(중첩) 객체에는 접근하지 않습니다.

1. 중첩 객체가 없는 경우

다음 예제에는 중첩된 객체가 없습니다. Object.freeze() 메서드가 객체 전체를 동결하려고 시도하기 때문에, 동결 이후에도 "name" 속성은 변경되지 않습니다.

<html>
<body>
   <script>
      const person = {
         "name" : "Suresh",
         "Country" : "India",
         "Designation" : "Mayor"
      }
      document.write("동결 전 이름: " + person.name);
      document.write("</br>");
      Object.freeze(person);
      person.name = "John";
      document.write("동결 후 이름: " + person.name);
   </script>
</body>
</html>

출력 결과

동결 전 이름: Suresh
동결 후 이름: Suresh

2. 중첩 객체가 있는 경우

반면, 중첩된 객체를 Object.freeze()로 동결하려고 하면 아무런 효과가 없습니다. 그 이유는 Object.freeze()가 내부의 중첩 객체에는 접근할 수 없기 때문입니다.

다음 예제에서 볼 수 있듯이, 객체가 Object.freeze() 메서드로 동결되었음에도 불구하고 중첩 객체의 속성 값은 정상적으로 변경됩니다.

<html>
<body>
<script>
    const person = {
       "name" : "Suresh",
       "Country" : "India",
       "Designation" : "Mayor",
       "CompaniesOwned" :{
          "Company1" : "Tesla",
          "Company2" : "SolarCity",
          "Company3" : "Spacex"
       }
    }
    document.write("동결 전 Company2: " + person.CompaniesOwned.Company2);
    Object.freeze(person);
    document.write("</br>");
    person.CompaniesOwned.Company2 = "Neuralica";
    document.write("동결 후 Company2: " + person.CompaniesOwned.Company2);
</script>
</body>
</html>

출력 결과

동결 전 Company2: SolarCity
동결 후 Company2: Neuralica

3. 해결 방법: 깊은 동결(Deep Freeze)

중첩 객체까지 완전히 불변으로 만들려면 재귀 함수를 사용해 모든 하위 객체에 Object.freeze()를 적용하는 깊은 동결(deep freeze) 기법을 활용할 수 있습니다.

function deepFreeze(obj) {
  // 먼저 현재 객체 자신을 동결합니다.
  Object.freeze(obj);

  Object.getOwnPropertyNames(obj).forEach((name) => {
    const value = obj[name];
    // 프로퍼티 값이 객체라면 재귀적으로 동결합니다.
    if (value && typeof value === "object") {
      deepFreeze(value);
    }
  });

  return obj;
}

deepFreeze(person);
person.CompaniesOwned.Company2 = "Neuralica"; // 무시됨 (엄격 모드에서는 TypeError 발생)
console.log(person.CompaniesOwned.Company2); // "SolarCity"

이처럼 Object.freeze()는 얕은(shallow) 동결만 수행한다는 점을 기억해야 합니다. 중첩 구조를 가진 데이터를 안전하게 보호하려면 위와 같은 깊은 동결 처리를 직접 구현하거나, Immutable.js와 같은 불변 데이터 라이브러리를 사용하는 것을 고려하는 것이 좋습니다.