[React] React의 불변성을 지키는 방법과 이유
📑 개요
이것도 리액트의 특징 중 하나......................
사실 쓸 때는 그냥 그렇게 쓰라길래
일단 프로젝트가 급하니까 글쿤하고 썼는데 정리하면서 이런 이유였구나 했다.
프젝하면서 공부도 같이 할 시간이 충분했다면 정말 좋았을텐데!!!!!!!!!!!🥺
그러니 지금 공부하고 있는 거겠지... 후... 하...🥺
React의 불변성
- 불변성이란?
값이나 상태를 변경 할 수 없는 것으로,
JavaScript에서는 메모리 영역의 값이 변하지 않는 것을 의미합니다.
여기서 메모리 원시 타입과 참조 타입에 대해 이해해야 한다.
이 부분은 이전에 정리한 게 있긴 한데... 포스팅할 만큼 정리되진 않아서 간단한 예시와 함께 설명하겠다.
만약 원시 타입과 참조 타입을 잘 모른다면 먼저 숙지하고 와야 이해가 될 것이다.
불변성의 의미를 파악하기 위해 JavaScript의 원시타입의 불변성을 살펴보자.
let string = "첫째"
string = "둘째"
이 경우 string의 값이 첫째 -> 둘째로 변한 것으로 보인다.
하지만 실제 메모리 영역에는 첫째와 둘째가 모두 존재하고 있다.
어떻게 가능할까?
let string = "첫째" // string "첫째"가 메모리 영역 1에 등록된다.
string = "둘째" // string "둘째"가 메모리 영역 2에 등록된다.
바로 메모리 영역 1에 첫째라는 값을 그대로 두고 메모리 영역 2에 둘째라는 값을 새로 할당하는 것이다.
이번엔 참조타입을 보자.
let array = [1, 2, 3, 4] // 메모리 영역 1
array.push(5) // 메모리 영역 1
array = [1, 2, 3, 4] // 메모리 영역 2 (새로운 참조 값)
array.push를 통해 원본 배열을 수정함으로써 불변성을 지키지 않았으며,
array = [1, 2, 3, 4]는 새로운 배열 [1, 2, 3, 4]를 할당하고 새로운 참조값을 만들어주어 불변성을 지켰다.
불변성이란, 메모리 영역에서 값을 변경할 수 없다는 것이다.
- 어째서 불변성을 지켜야 하죠?
1. 리액트는 상태값을 업데이트할 때 얕은 비교를 수행하기 때문이다.
배열이나 객체의 속성을 하나하나 비교하지 않고 이전 참조값과 현재 참조값만을 비교하여 상태 변화를 감지하는 것이다.
따라서, 배열이나 객체를 업데이트 할 때 불변성이 없는 변경은 React에서 상태가 바뀌었다고 판단하지 못하므로 불변성을 지킨 업데이트가 필요하다.
배열이나 객체를 새로 생성하여 새로운 참조값을 만들고 상태를 업데이트 하는 것이다.
얕은 비교를 통해 계산 리소스가 줄어들고 상태 업데이트가 효율적으로 된다.
2. 사이드 이펙트 방지
외부에 존재하는 원본데이터를 직접 수정하지 않고 원본데이터의 복사본을 만들어 값을 사용하므로 예상치 못한 오류를 방지할 수 있다.
원본데이터가 변경되면 원본 데이터를 참조하고 있는 다른 객체에서 오류가 발생할 수 있다.
불변성을 지킴으로써 이러한 사이드 이펙트를 방지할 수 있는 것이다.
React의 불변성을 지키는 방법
- 객체나 배열을 변경하지 않기
기존 객체나 배열을 직접 수정하는 대신, 새로운 객체나 배열을 생성하여 변경한다. 이를 통해 원본 데이터가 변경되지 않고 새로운 데이터가 생성된다.
// 잘못된 방법 - 원본 배열을 직접 수정
const myArray = [1, 2, 3];
myArray.push(4);
// 올바른 방법 - 새로운 배열 생성
const myNewArray = [...myArray, 4];
- 객체나 배열을 병합하거나 분해할 때도 불변성을 유지하기
객체나 배열을 병합하거나 분해할 때에도 새로운 객체나 배열을 생성하여 변경한다.
// 잘못된 방법 - 원본 객체를 직접 수정
const myObject = { name: 'John', age: 30 };
myObject.age = 31;
// 올바른 방법 - 새로운 객체 생성
const myNewObject = { ...myObject, age: 31 };
- Object.assign()
Object.assign() 함수를 사용하여 새로운 객체를 생성하고 기존 객체의 속성을 복사한다.
// Object.assign()을 사용한 예시
const myObject = { name: 'John', age: 30 };
const myNewObject = Object.assign({}, myObject, { age: 31 });
- 배열의 메서드를 사용하여 새로운 배열 생성하기
배열의 메서드인 concat(), slice(), map() 등을 사용하여 새로운 배열을 생성한다.
// 배열의 메서드를 사용한 예시
const myArray = [1, 2, 3];
const myNewArray = myArray.concat(4);
- Spread 연산자
Spread 연산자 (...)를 사용하여 객체나 배열을 복사하고 새로운 요소를 추가한다.
// Spread 연산자를 사용한 예시
const myArray = [1, 2, 3];
const myNewArray = [...myArray, 4];
✨ 마무리
정말... 프젝 때 알았으면 좋았을 것을!
리액트며 뭐며 공부를 할 수록
아 정말 기술을 쓰기만 했구나~ 쓸 줄만 아는구나~ 하고 나의 바닥을 알게 된다.
하지만 지금도 기술에 대해 잘 이해함으로써 어떤 식으로 개발에 도움이 되는지는 와닿지 않긴 한다.
프로젝트로 들어가봐야 이론이 도움 되는구나! 하고 좀 와닿을까...
어서 토이 프로젝트를 하나 해봐야겠다.
- 요약
참고 문헌