cs 지식/코어 자바스크립트

[코어 자바스크립트] 불변 객체

귤먹는코더 2022. 5. 31. 20:29
728x90

불변 객체(immutable object)

객체 지향 프로그래밍에 있어서 불변객체(immutable object)는 생성 후 그 상태를 바꿀 수 없는 객체를 말한다.

 

불변 객체를 만드는 이유
  • 다중 스레드 환경에서 안전
  • 방어적 복사본을 만들 필요가 없다.
  • 사이드 이펙트가 발생할 확률이 적다.

 

객체의 가변성에 따른 문제점
var user = {
    name: 'Jaenam',
    gender: 'male'
}

var changeName = function(user, newName){
    var newUser = user;
    newUser.name = newName;
    return newUser;
};

var user2 = changeName(user, 'Jung');

if(user !== user2){
    console.log('유저 정보가 변경되었습니다.');
}
console.log(user.name, user2.name);  //Jung Jung
console.log(user === user2);         //true
 
 

changName()의 동작을 살펴보면 알 수 있듯이. 같은 객체를 가리키는 새로운 변수만을 생성하고 그 변수가 가리키는 name 프로퍼티의 값을 변경을 주었기 때문이다.

 

즉 user, user2 까지의 모든 변수는 같은 주소 공간을 바라보고 있고, 그 주소공간중 name 프로퍼티가 가리키는 데이터를 변경하였기 때문에, 모든 변수에 담긴 name 프로퍼티 값이 같이 변경된 듯한 현상이 발생하는 것이다.

 

객체의 가변성에 따른 문제점의 해결 방법
var user = {
    name: 'Jaenam',
    gender: 'male'
}

var changeName = function(user, newName){
    return {
        name: newName,
        gender: user.gender
    }
};

var user2 = changeName(user, 'Jung');

if(user !== user2){
    console.log('유저 정보가 변경되었습니다.'); // 유저 정보가 변경되었습니다.
}
console.log(user.name, user2.name);  //Jaenam Jung
console.log(user === user2);         //true

changeName 함수가 새로운 객체를 반환하도록 수정, 이제 user와 user2는 서로 다른 객체이므로 안전하게 변경 전과 후를 비교할 수 있다.

changeName 함수는 새로운 객체를 만들면서 변경할 필요가 없는 기존 객체의 프로퍼티(gender)를 하드코딩으로 입력했다. 이런 식으로는 대상 객체에 정보가 많을수록, 변경해야 할 정보가 많을수록 사용자가 입력하는 수고가 늘어날 것이다. 이런 방식보단 대상 객체의 프로퍼티 개수에 상관 없이 모든 프로퍼티를 복사하는 함수를 만드는 편이 더 좋을 것 같다.

 

기존 정보를 복사해서 새로운 객체를 반환하는 함수(얕은 복사)
var copyObject = function (target) {
    var result = {};
    for (var prop in target){
        result[prop] = target[prop];
    }
    return result;
}

 

copyObject를 이용한 객체 복사
var user = {
    name: 'Jaenam',
    gender: 'male'
};

var user2 = copyObject(user);
user2.name = 'Jung';

if(user !== user2){
    console.log('유저 정보가 변경되었습니다.'); //유저 정보가 변경되었습니다.
}

console.log(user.name, user2.name); //Jaenam Jung
console.log(user === user2);        //false

copyObject 함수는 간단한 만큼 아쉬운 점이 많다.

무엇보다도 '얕은 복사만을 수행한다'는 부분이 가장 아쉽다.

728x90