JS의 불변성

jh_leitmotif·2022년 3월 5일
0

Frontend 개인 공부

목록 보기
24/24
post-thumbnail

불변성.

지긋지긋한 이야기, React는 state가 변동되면 다시 렌더링합니다.

이 때 주의할 것은 state의 값이 변경된 것을 확인하는 것이 아닙니다. 참조하는 위치가 변경되었는가? 에 대해 비교합니다.

왜 이렇게 비교하는 걸까요?

객체는, 참조한다.

원시 타입의 경우

let a = 1;

이 코드를 해석하면.

메모리 영역에 1이 생성되고, 그것을 a라는 객체가 가리킨다

let a = 1; 		---- (1)
let b = a; 		---- (2)

a=2;	   		---- (3)

(3) 까지 진행되었을 때, a와 b의 값은 무엇일까요?

정답은, a는 2이고 b는 1입니다.

(2)에서 b는 a가 가리키고 있는 1을 참조합니다.
(3)에서 a는 새로 생성된 메모리인 2를 참조하게 됩니다.

그렇듯, JS는 기본적으로 불변성을 유지하는 원시타입들이 있습니다.

* boolean
* String
* Number
* Null
* undefined
* Symbol

원시 타입의 객체는 각자 독립적인 메모리 주소 값을 할당하며, 곧 깊은 복사 라고도 합니다.

Object와 Array의 경우

원시 타입과 다르게 Object, Array는 불변성이 없습니다.

이 두 가지 데이터 타입은 원본 데이터의 수정이 허락됩니다.
a와 b는 같은 메모리 주소를 공유하게 되고, 이를 얕은 복사라고 합니다.

그런데 잠깐, 객체는 참조 한다고 했습니다.

만약 위의 예시에서 b는 a와 다른 영역에서 사용되는 객체라고 가정해봅시다.

그런데 어디에선가 a를 건드려서 값이 변경됐는데, 그게 하필이면 원시 타입이 아니라면 어떻게 되는 걸까요?

오류가 발생하지 않더라도 [1,2,3] 이란 값을 기준으로 작성했던 코드를 변경해야하는 필요성이 발생할 수 있고, 이는 곧 의도하지 않은 부수 효과 라고 할 수 있습니다.

그러므로 불변성을 지키지 않는다면 예측 불가능하고 불편한 가독성을 지닌 코드가 됩니다.

그래서, React의 경우.

React는 그래서, 애초에 불변성 개념을 지키게끔 규칙을 정했습니다.

const [test, setTest] = useState(1)

test = 2    ------ (1) (에러!)
setTest(2)  ------ (2) (옳지!)

state는 항상 setState를 이용해 갱신 되어야만 합니다.

(1)과 같은 방식으로 작성하면 자체적으로 React는 불변성을 지키라면서 오류를 뱉습니다. 원시 타입이 아닌 경우는 어떨까요?

const [test, setTest] = useState({ id:1 })

test.id=2

위의 경우도 마찬가지입니다. 엄격하게, state를 변경하고자 한다면 setState를 사용해야합니다. 여기서 더 나아가, 객체를 복사하거나 갱신할 때에 다음과 같은 방법이 권장됩니다.

const [test, setTest] = useState({ id:1 })

setTest(current =>{
	const newObj = {...current}
    newObj.id = 2;
    return newObj;
})

setState는 자기 자신을 인자로 건넬 수 있습니다.
... 스프레드 연산자를 이용해 기존의 값이 복사된 새로운 객체를 만들고, 그것을 반환합니다.

즉, 내부 콜백을 이용해 새로운 메모리를 선언해서 불변성을 해치지 않는 방식으로 state를 갱신시킬 수 있습니다.

profile
Define the undefined.

0개의 댓글