일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 프론트엔드
- 타입스크립트
- 투두앱만들기
- 객체지향프로그래밍
- github
- 캡슐화
- 리액트
- 불변성
- 패스트캠퍼스
- OOP
- 부트캠프
- Fetch
- 추상화
- JavaScript
- Hooks
- CSS
- 상속
- frontend
- REACT
- js
- webdevelopment
- 웹개발
- 클래스
- 자바스트립트
- Zustand
- typeScript
- 노마드코더
- Props
- 자바스크립트
- 논리연산자
- Today
- Total
connecting dots
React | React 불변성 본문
리액트에서 불변성이란 ?
한 번 값이 설정되면 그 값을 변경할 수 없는 성질
사전적 의미: 값이나 상태를 변경할 수 없는 것
자바스크립트를 통한 불변성 의미 살펴보기
원시타입: Boolean. String, Number, null, undefined, Symbol (불변성을 가짐 - 값을 변경할 수 없음)
참조타입: Object, Array, 함수(불변성을 가지지 않음 - 값을 변경할 수 있음)
메모리에서의 불변성
자바스크립트는 원시 타입과 참조 타입을 다르게 저장합니다.
1. 원시 타입:
• 원시 타입 값은 Call Stack이라는 메모리 공간에 저장됩니다.
• 예: let age = 30; 여기서 age는 Call Stack에 30이라는 값으로 저장됩니다.
2. 참조 타입:
• 참조 타입 값은 Heap이라는 별도의 메모리 공간에 저장됩니다.
• Call Stack에는 실제 값이 아닌 Heap 메모리의 참조 ID(주소)가 저장됩니다.
• 예: let person = { name: "Alice" }; 여기서 person 변수는 Heap에 저장된 객체의 참조 ID를 Call Stack에 저장합니다.
예제
1. 원시 타입
a의 값을 변경해도 b의 값이 변하지 않음.
let a = 10;
let b = a; // a의 값을 b에 복사
a = 20; // a의 값을 변경, b는 여전히 10
console.log(a); // 20
console.log(b); // 10
2. 참조 타입
arr1을 변경하면 arr2도 영향을 받음.
let arr1 = [1, 2, 3];
let arr2 = arr1; // arr1의 참조를 arr2에 복사
arr1.push(4); // arr1을 변경하면 arr2도 영향을 받음
console.log(arr1); // [1, 2, 3, 4]
console.log(arr2); // [1, 2, 3, 4]
3. 불변성 유지 예제
const [items, setItems] = useState([1, 2, 3]);
const addItem = () => {
const newItem = 4;
setItems([...items, newItem]); // 새로운 배열을 생성하여 상태를 업데이트
};
setItems([...items, newItem])는 기존 배열을 복사하고 새로운 아이템을 추가하여 새로운 배열을 생성!
--> 불변성 유지 !
원시타입 | 고정된 크기로 call stack 메모리에 저장, 실제 데이터가 변수에 할당 | |
원시타입 | let userName = "waiter" userName = "john" |
이것은 userName waiter를 john으로 대체한 것이 아닌 메모리 영역 a에 있는 waiter라는 값을 그대로 두고 메모리 영역 b에 john을 새로 할당한 것임 ==> userName이 참조하는 값이 바뀌었을 뿐, 메모리 공간에 저장된 "waiter"는 여전히 존재. --> 불변성을 가지고 있기 때문에 리액트에서 불변성을 위해서 따로 신경쓰지 않아도 됨 |
참조타입 | 데이터 크기가 정해지지 않고 call stack 메모리에 저장, 데이터의 값이 heap에 저장되며 변수에 heap 메모리의 주소값이 할당 |
|
참조타입 | let array = ['1', '2', '3'] array = ['4', '5', '6'] |
배열에 대한 요소를 추가하거나 객체 속성 값을 변경할 때 call stack의 참조 id는 동일하게 유지되고 Heap 메모리에서만 변경됨 ==> 배열의 값이 바뀌면, array 변수가 새로운 배열을 가리키게 됨. 결과적으로 array가 참조하는 배열이 변경됨. --> 불변성이 유지되지 않기 때문에 리랙트에서 신경 써줘야 함 |
불변성을 지켜야 하는 이유는 ?
1. 참조 타입에서 객체나 배열의 값이 변할 때 원본 데이터가 변경되기 때문에 이 원본 데이터를 참조하고 있는 다른 객체에서 예상치 못한 오류가 발생할 수 있어서 프로그래밍의 복잡도가 올라감
2. 리액트에서 화면을 업데이트할 때 불변성을 지켜서 값을 이전 값과 비교해서 변경된 사항을 확인한 후 업데이트하기 때문에 불변성을 지켜줘야 함
==> 리액트에서 불변성을 지키는 이유는 상태 관리와 성능 최적화를 위해서 !
상태를 변경할 때마다 새로운 객체나 배열을 생성하면 상태 변경을 추적하기 쉽고, 변경된 부분만 업데이트할 수 있어 성능이 향상됨
불변성을 지키는 방법
참조 타입에서는 값을 바꿨을 때 call stack 주소 값은 같은데 Heap 메모리 값만 바꿔주기에 불변성을 유지할 수 없었으므로
아예 새로운 배열을 반환하는 메소드를 사용하면 됨
--> spread operator, map, filter, slice, reduce
(cf. 원본을 변경하는 메소드: splice, push)
const array = [1, 2, 3, 4]
const sameArray = array
sameArray.push(5)
console.log(array === sameArray) // true
const array = [1, 2, 3, 4]
const differentArray = [...array, 5]
console.log(array === differentArray) // false