똑같은 삽질은 2번 하지 말자

[vuex] do not mutate vuex store state outside mutation handlers. (feat. javascript의 얕은복사 깊은복사) 본문

Vue

[vuex] do not mutate vuex store state outside mutation handlers. (feat. javascript의 얕은복사 깊은복사)

곽빵 2021. 11. 20. 19:08

원인

해당에러는 store의 state의 값들을 vuex의 mutation을 통해서가 아닌 직접 값을 변형하려고 할 때 발생하는 에러이다.

ex) this.$store.state.name = gwak;

 

해결방법

store에서 땡겨온 값들은 기본적으로 복사해서 사용하는게 좋다.

(아니면 값을 변형하는 처리 자체를 하나하나 mutations을 통해 해주거나)

 

javascript 객체를 복사하는 방법으로써는 두가지의 종류가 있다.

 

얕은복사(객체안의 객체같은 depth >= 2 인 경우에는 해결방법이 아님)

객체를 복사하지만 객체의 값들중에 원본객체를 참조하고 있는 요소가 존재하면 그건 얕은복사 이다.

 

1. 객체를 통째로 집어넣기

const obj1 = { a: 1, b: 2};
const obj2 = obj1;
console.log( obj1 === obj2 ); // true

 

2. Object.assign으로 객체를 생성해서 복사했지만, 여전히 안의 요소들은 원본객체를 참조중

const obj1 = {
  a: 1,
  b: {
    c: 2,
  },
};

const obj2 = Object.assign({}, obj1);

obj2.b.c = 3

obj1 === obj2 // false
obj1.b.c === obj2.b.c // true

 

3. 전개 연산자 (spread operator)를 이용한 복사..를 했지만 여전히 내부 객체에선 원본 객체를 참조

const obj1 = {
  a: 1,
  b: {
    c: 2,
  },
};

const obj2 = {...obj1}

obj2.b.c = 3

obj1 === obj2 // false
obj1.b.c === obj2.b.c // true

 

깊은복사(완벽하진 않지만...)

1. JSON.parse(JSON.stringify(복사할 대상)) -> 비추천(낮은 퍼포먼스)

const obj1 = {
  a: 1,
  b: {
    c: 2,
  },
};

const obj2 = JSON.parse(JSON.stringify(obj1)),

obj2.b.c = 3

obj1 === obj2 // false
obj1.b.c === obj2.b.c // false

 

2. 재귀함수를 이용한 복사 (깊은복사를 해야하는 상황이라면 추천하는 방식)

const obj1 = {
  a: 1,
  b: {
    c: 2,
  },
};

function copy(obj1) {
  const obj2 = {};

  for (let key in obj1) {
    if (typeof obj1[key] === 'object') {
      obj2[key] = copy(obj1[key]);
    } else {
      obj2[key] = obj1[key];
    }
  }

  return obj2;
}

const obj2 = copy(obj1);

obj2.b.c = 3

console.log(obj1.b.c) // 2

 

객체안의 객체이외에도 참조형 자료형(배열, 맵등등)이 있다면 그 경우에는 좀더 확장해서 개선 가능할 방법인거같다.

 

3. lodash 라이브러리를 이용(완벽한 복사가 가능)

이건 해본적이 없으므로 다른 기사들을 참조하시길.. 

깊은복사를 위해 라이브러리까지 써야하는..상황이라면 구조를 바꾸는게 좋겠다.

 

 

내 생각

가능하면 깊은복사같은걸 해야만 하는 상황들을 피하는게 좋다는 기사를 봤다.

javascript 구조상 완벽한 복사는 불가능? 이라는 말이다. ( 밑의 글을 참조!! )

depth가 2이상의 데이터를 깊은복사하는 경우가 오지 않도록 잘 설계..하는게 최고인거 같긴하다..

 

[Javascript] 얕은 복사, 깊은 복사

자바스크립트에서 값은 원시값과 참조값으로 나뉜다. 원시값 Number String Boolean Null Undefined 참조값 Object Symbol 원시값은 값을 복사 할 때 복사된 값을 다른 메모리에 할당 하기 때문에 원래의 값과

velog.io

 

Comments