ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TIL 2021.7.21 : 자바스크립트 데이터의 불변성 유지(feat. 가변성)
    항해99 1기 수료후 TIL 2021. 7. 21. 09:30
    자바스크립트 데이터의 불변성 개념을 처음 접하면 알쏭달쏭하지 않던가요? 그리고 리액트에서 왜 불변성 유지를 해줘야 리렌더링이 되는지 이해를 하셨나요? 이제 이해해봅시다.

    자바스크립트 데이터의 불변성

    아래 데이터들의 코드를 보자.

    기본형 데이터인 숫자형 데이터는 데이터를 바꾸면 참조하는 데이터 영역의 주소가 바뀌면서(= 변수 영역의 값이 바뀌면서) a와 b는 서로 다른 데이터가 된다. 그러나 참조형 데이터인 객체의 경우, 내부 프로퍼티를 바꿔도 객체 프로퍼티의 변수 영역이 참조하는 데이터 영역의 주소만 바뀌지 변수영역이 참조하는 데이터 영역의 주소는 바뀌지 않기 때문에 서로 obj1과 obj2는 같은 데이터로 간주 된다. 이것이 바로 참조형 데이터는 가변값이라는 개념으로, 참조형 데이터는 내부 프로퍼티를 바꾼다고 해도 변수영역이 참고하는 데이터 영역의 주소값이 바뀌지 않았기 때문에 내부 프로퍼티를 바꾸기 전의 데이터와 같은 데이터라고 간주 된다는 뜻이다.

    이 원리의 개념도는 아래와 같다. 

     

    그런데 원래 같았던 두 객체중에서 한 객체 자체를 변경하면(= 새로운 객체를 할당하면) 변수영역이 참조하는 데이터영역의 주소가 바뀌면서 서로 다른 객체로 간주 된다. 

    이렇게 내부 프로퍼티를 바꿔야 할 때, 기존 객체의 내부 프로퍼티를 변경하는 것(= 이러면 가변성이다)이 아니라 내부 프로퍼티가 바뀐 새로운 객체를 만들어 쓴다면 객체도 불변성을 확보할 수 있다. 왜냐면 새 객체를 만들었기 때문에 변수영역이 참고하는 데이터 영역의 주소값이 바뀌어서 이전과는 다른 데이터로 간주 되기 때문이다. 리액트에서 state가 변경될 때 리렌더링이 되는 것은 이 원리를 이용한 것인데, 예를 들어보겠다.

     

    그 예를 설명하기 위한 사전 지식으로, 자바스크립트에서 제공하는 spread operator도 객체의 불변성을 확보하기 위해서 새 객체를 만드는 것임을(= 기존 객체를 복사해서 새 객체로 만드는 것) 보여주겠다.

    처음부터 있던 obj1을 spread operator로 복사해서 obj2를 만들었다. 그러면 obj1 === obj2가 false로 판정되면서 obj1과 obj2는 다른 객체로 판정된다(= obj2의 변수 영역이 참조하는 데이터 영역의 주소는 obj1과는 다른 주소다). 그래서 spread operator를 이용하면 객체의 불변성을 유지 할 수 있다.

     

    리액트에서 spread operator를 이용해 객체를 복사하면서 객체 불변성을 유지하고, 이걸 이용해서 state가 변해야 리렌더링이 되는 원리를 설명하겠다.

    state가 변경된다는 말의 뜻은 다음과 같다. state도 어차피 데이터인데, state가 변한다는 말은 state의 변수영역에서 참조하는 데이터 영역의 주소값이 바뀌어서 이전 데이터와 다른 데이터가 된다는 말이다(= 불변성 확보). 그리고 state가 변경 되어야 리렌더링이 된다는 말은 이전과 다른 데이터가 되었음을 감지해야 리렌더링이 된다는 말과 같다. 다시말해, 내부 프로퍼티가 바뀌었는데 바뀐 내용이 반영된 화면이 뜨도록 리렌더링을 하려면 내부 프로퍼티가 바뀐 새로운 객체를 만들어서(= 불변성을 확보해서) 리액트가 그 데이터가 이전과 다른 데이터임을 확인하면 리렌더링이 된다는 뜻이다.   

    위 코드는 input 상자에 값이 입력되면, 원래는 내부프로퍼티에 키는 있지만 value는 빈 string이던 inputs 라는 state가 value에 입력값이 할당된, 원본과는 다른 새 데이터를 만드는(= 기존 input state를 복사해서 새 inputs state를 만든다. 즉, 불변성을 확보한 것) 코드다. 앞서 spread operator는 변수영역에서 참조하는 데이터 영역의 주소를 원본 데이터가 참조하는 데이터 영역의 주소와 다르게 하는 식으로 복사한다고 설명했다. 이 코드에서도 spread operator로 원본 데이터와는 다른 데이터가 생기게 했으므로 불변성을 확보했고, state도 변경 되었음이 감지 되게 함으로써 리렌더링이 된다.

     

    이렇게 spread operator를 쓰는 것 외에도 리액트에서는 immer 같은 불변성을 확보해주는 라이브러리를 활용해서 state를 변경해서 리렌더링이 되게 하는 방법이 널리 쓰인다.

     

    참고문헌

    코어자바스크립트(정재남)

    불변성 유지 (in 리액트 state, 리덕스 store) - FE study14

    벨로퍼트와 함께 하는 모던 리액트

    댓글

금손이 프론트엔드 개발자가 되고자 오늘도 존버중