변수 선언 원리 및 불변성으로 인한 코드 오류 발생을 방지하기 위해 작성한 글입니다.
프로그래밍에서 불변성이 주목받게 된 계기는 변경 가능한 state를 여러 곳에서 공유하게 됨으로써 발생하는 여러 가지 문제를 해결하기 위함이었다.
불변성을 지켜주는 이유는 리액트의 상태 업데이트를 하는 원리 때문이다. 상태값을 업데이트할 때 얕은 비교를 수행, 즉 객체의 속성 하나하나를 비교하는 게 아니라 참조값만 비교하여 상태 변화를 감지한다는 의미다.
이러한 이유로 배열이나 객체를 업데이트할 때 아래와 같이 새로 생성하고 새로운 참조값을 만들어서 상태를 업데이트한다.
setState([...state, newState])
setState([...state, [key]:[value])
이는 불변성을 지켜주며 사이드 이펙트를 방지해준다. 즉 외부에 존재하는 원본데이터를 직접 수정하지 않고, 원본데이터의 복사본을 만들어서 값을 사용하기에 예상치 못한 오류를 사전에 방지하는 것이다.
반대로 생각했을 대 외부 값을 함부로 변경하는 것은 위험한 일이다. 만약 다른 어떤 곳에서 원본데이터를 사용하고 있다고 하면 어플리케이션 어딘가에서 사이드 이펙트가 발생할 가능성이 있기 때문이다.
- 원시타입 - string, number, bigint, boolean, undefined, symbol
- 실제 값을 변수에 직접 저장하고 저장된 값을 변수가 직접적으로 가르키는 형태
- 값이 절대 변하지 않는 불변성을 갖고 있음
- 참조타입 - array, object, class, interface
- 메모리의 번지 값을 변수에 저장함으로써 객체 주소(번지)를 참조하는 형태
- 주소(번지)를 통해 객체를 참조한다는 뜻으로 참조 타입이라 부른다.
원시타입 - 스택 영역
참조타입 - 힙 영역
원시타입과 참조타입의 가장 큰 차이점은 참조타입은 변수의 크기가 동적으로 변하는 특징 때문에 object 데이터 자체가 별도의 메모리 공간인 heap에 저장된다.
변수 할당 시 데이터의 주소, 즉 Heap 메모리의 주소값이 저장되기 때문에 JS Engine이 변수가 가지고 있는 메모리 주소를 이용해 변수의 값에 접근하게 되는 것이다.
이러한 특성으로 변수 복사 및 수정 시 참조 여부를 잘 고려해야 한다. 원본 데이터가 예상치 못한 방향으로 변경될 수 있다는 점을 항상 고려하자.
얕은 복사와 깊은 복사의 개념은 이 링크에서 확인해주세요 !
효율적인 상태업데이트 - 얕은 비교 수행
얕은 비교란 객체 프로퍼티를 하나하나 비교하는 것이 아닌 객체의 참조 주소값만 변경되었는지 확인하기 때문에 계산리소스를 줄여준다.
사이드 이펙트 방지 및 프로그래밍 구조의 단순성
원시타입은 애초에 불변성 특징을 가지고 있지만 참조타입은 새로운 값을 변경할 때 원본 데이터가 변경이 되어 불변성이 지켜지지 않는다. 이렇게 원본 데이터가 변경될 경우, 이 원본데이터를 참조하고 있는 다른 객체에서 예상치 못한 오류를 야기시킬 수 있다. 프로그래밍의 복잡도도 올라간다.