최근에 모 회사에서 기술면접을 봤는데 위와 같은 질문을 받았다. 좀 더 깊게 들어가서.. “SPA라는 걸 최초로 개발했고, 그걸 아무도 모른다고 했을 때, 불변성이라는 개념이 왜 중요할까?” 라는 질문이었는데 예전에 충분히 공부했다고 생각한 주제임에도 불구하고 만족스런 답변을 하지 못했다..
그게 이 글을 쓰게 된 동기이다.
불변성이 왜 필요한 지를 알아보기 전에 불변성이 무엇인지부터 알아보자.
먼저, 자바스크립트에는 “기본형” 값과 “참조형” 값이 있다. 아래 그림을 보자.
기본형 값은 “불변성” 을 지니고, 참조형 값은 “가변성”을 지닌다.
기본형 값을 재사용하기 위해서, 변수에 저장한다고 하자. 그러기 위해서는 변수를 위한 메모리 공간이 할당이 될 것이고, 해당 메모리공간의 값은 기본형 값이 저장된 메모리 주소가 저장될 것이다.
그러면 그 기본형 값은 메모리가 해체되어 사라지기 전까지 다른 값으로 변화할 수 없다. 변수에 다른 값을 대입한다고 한들, 메모리의 값이 변화하지 않는다.
한 번 코드로 살펴보자.
let num = 10; // num의 메모리 주소와 값 : 0x00000001 , 0x00000002
num = 20; // num의 메모리 주소와 값 : 0x00000001 , 0x00000003
// 10의 메모리 주소 : 0x00000002
// 20의 메모리 주소 : 0x00000003
num
에 저장된 10
이라는 값을 20
이라는 값으로 바꿨지만, 0x0000002
에 저장된 10
이라는 값은 불변성을 지니기 때문에 20
으로 변하지 않고, 새로운 메모리 공간을 할당해 (0x00000003
) 해당 주소에 20
이라는 값을 저장하고 num
의 가리키는 메모리 주소의 값을 0x00000002
에서 0x00000003
으로 바꿨다.
이러한 특성을 불변성이라고 한다.
만약 이해가 잘 안 되었거나, 좀 더 자세히 불변성과 가변성에 대해서 알고 싶다면, 이 글을 참고하도록 하자.
그러면 리액트에서 불변성이 왜 중요한 걸까? 첫번째로는 그걸 알기 위해서는 “리액트가 상태를 업데이트 하는 방식” 에 대해서 알고 있을 필요가 있다.
리액트는 상태값을 업데이트할 때, 얕은 비교를 통해 상태를 업데이트한다. 즉, 객체나 배열의 프로퍼티를 하나 하나 다 비교하는 것이 아니라, 이전 참조값과 새로운 참조값이 동일한 지만 비교한다. 이를 통해 리액트는 계산 리소스를 줄여 상태를 효율적으로 업데이트를 할 수 있다.
추가적으로, 기본적으로 모든 컴포넌트는 상위 컴포넌트의 상태가 변경되면 자동으로 리렌더링된다. 이는 변경의 영향을 받지 않은 하위 컴포넌트도 마찬가지이다. 이 때, 성능상의 이유로 리렌더링의 영향을 받지 않은 트리 부분을 건너뛰고 싶을 수 있다. 불변성은 컴포넌트의 데이터가 변경되었는지 여부를 비교하는 데 저렴하다.
두번째로는 불변성은 복잡한 기능을 구현하기 훨씬 쉽게 만든다. “특정 작업을 실행 취소하고 다시 실행하는 기능”은 일반적인 요구사항이다. 직접적인 데이터 변형을 피하면 이전 버전의 데이터를 그대로 유지하고 나중에 재사용할 수 있다. 이에 대한 좋은 예시는 여기서 확인할 수 있다.