Q1. 리액트에서 왜 불변성을 지켜야하나요?
- 리액트에서는 상태값을 업데이트할 때 얕은 비교를 수행합니다.
얕은 비교(Shallow Compare)란?
얕은 비교는 자료형에 따라 데이터 비교 방법이 다르다. 숫자, boolean과 같은 원시 자료형에 경우에는 그 값을 비교하고, 배열, 객체 등과 같은 참조 자료형에 경우에는 그 속성 (attributes)을 비교하는 것이 아니라 참조주소값(reference)을 비교하는데, 이것을 얕은 비교하고 합니다.
- 그렇기 때문에 리액트에서는 객체와 같은 데이터에 변경이 있을 경우에는 속성에 변경이 있더라도 참조주소값에 변경이 없으면 그 변경을 인지하지 못합니다.
- 따라서, 리액트에서 객체에 변화가 있다면 그 참조 주소값을 변경해주어야 하는 것 입니다.
이것이 불변성이랑 무슨 관계일까요?
- 먼저 불변성이 무엇인지를 알아야 합니다.
불변성이란?
- 일차원적으로는 값이나 상태를 변경할 수 없는 것을 의미합니다.
- 불변성은 원시자료형과 참조자료형의 메모리 할당방식에 따라 다르게 나타납니다.
- 원시 자료형에 경우에는 어떤 변수의 데이터가 선언되었을때 고정된 메모리에 할당된 원시자료형에 변수가 할당됩니다.
- 따라서 같은 변수의 데이터가 변경이 되었을때 고정되어 있는 다른 메모리로 할당되어 참조주소값이 변경됩니다.
- 이때 할당된 메모리에 있는 데이터값이 변경되지 않고 유지되기 때문에 원시자료형은 "불변성을 가지고 있다." 라고 표현하게 됩니다.
- 그러나, 참조 자료형에 경우에는 다릅니다.
- 참조 자료형에 경우에는 변수가 선언되었을때 일정한 메모리에 데이터를 저장합니다.
- 그리고 데이터에 변경이 있는 경우에는 같은 메모리에 있는 데이터 자체를 변경하게 됩니다.
- 이때 같은 메모리에 데이터가 변경되기 때문에 참조자료형에는 "불변성이 없다." 라고 표현할 수 있습니다.
- 따라서 불변성이란 "메모리 영역에서 데이터값이 변하지 않는 것" 이라고 정의할 수 있습니다.
리액트에서 불변성을 지켜준다는 것은 무슨 의미일까요?
- 앞에서 말했듯이 리액트에서는 데이터를 비교할때 얕은 비교를 합니다.
- 그러나 객체와 같은 참조 자료형은 데이터에 변경이 있을 경우 메모리 주소값은 변하지 않고 데이터 자체가 변경되기 때문에 참조 주소값을 비교하는 리액트에서는 그 변화를 인지하지 못하는 것입니다.
- 그렇기 때문에 리액트에서 객체의 속성을 변경할 경우에는 새로운 객체를 복사하여 그 값을 변경해 줍니다.
- 이 때 원본 객체는 할당되었던 메모리 영역에서 데이터 값이 변경되지 않고 유지되기 때문에 그대로 불변성을 지키고 있습니다.
- 이것을 리액트에서는 "불변성을 지켜준다." 라고 표현을 하는 것입니다.
리액트에서는 왜 얕은 비교를 수행하는 걸까요?
Shallow compare is an efficient way to detect changes.
- 그 이유는 얕은 비교는 계산 리소스를 줄여주므로 효율적이기 때문이다.
- 속성의 값을 하나 하나 비교하는 깊은 비교보다는 주소값만을 비교해주면 되기때문에 변화를 감지하는것이 용이하다.
객체 변경없이 새로운 객체를 생성하여 데이터를 수정하는 것의 이점
- 특정 행동을 취소하고 다시 실행하는 기능과 같은 복잡한 기능을 비교적 단순하게 구현가능하게 합니다. 왜냐하면 이전 할당되었던 메모리의 값이 불변성을 유지하고 그대로 있기 때문이죠.
- 참조하고 있는 객체의 주소가 변경된 것을 감지하는 것이 변화를 감지하는데 가장 확실한 방법입니다.
- 리액트에서 리렌더링하는 시기를 결정할수 있습니다.
순수 컴포넌트는 입력된 값을 받아 그대로 출력합니다. 이러한 경우 데이터값은 변경되지 않았지만 새로운 객체가 생성되기 때문에 리렌더링을 할 수 있습니다. - 사이드 이펙트를 방지 및 프로그래밍 구조의 단순성
원본 데이터가 변경될 경우, 이 원본데이터를 참조하고 있는 다른 객체에서 예상치 못한 오류가 발생할 수 있습니다. 또한 프로그래밍의 복잡도도 올라갑니다. 즉, 외부에 존재하는 원본데이터를 직접 수정하지 않고, 원본데이터의 복사본을 만들어서 값을 사용하기에 예상치 못한 오류를 사전에 방지할 수 있습니다. - 효율적인 상태 업데이트 (얕은 비교 수행)
객체의 참조 주소값만 변경되었는지 확인합니다. 얕은 비교는 계산 리소스를 줄여주기 때문에 리액트는 효율적으로 상태를 업데이트 할 수 있습니다.
어떻게 불변성을 지키나요?
- 불변성을 지키기 위해서 리액트에서는 새로운 배열 혹은 객체를 반환하는 메소드들을 활용합니다.
- spread operator, map, filter, slice, reduce 등등을 주로 사용합니다.
- splice는 기존 배열에 변화를 주기 때문에 주의해야 합니다.
- setState를 사용하는 경우에는 원시 자료형에 경우에는 값을 바로 넣어주어도 값이 저장되어있는 참조 주소가 변경되기 때문에 바로 넣어주어도 되지만
- 참조 자료형에 경우에는 새로운 객체나 배열을 생성한 후에 값을 넣어주어야 합니다.
1. 자바스크립트에서 유사배열과 배열의 차이는 무엇일까요? 유사배열의 각 요소를 수정하고 싶다면 어떤 과정을 거쳐야할까요?
2. 부모 컴포넌트 A와 자식 컴포넌트 B가 있습니다. 컴포넌트 A는 state로 {name: "르탄이"}를 가지고 있고, 자식인 컴포넌트 B에게 name 값을 넘겨주었습니다. 컴포넌트 B는 받아온 name을 화면에 뿌려주고 있습니다. 컴포넌트 A의 state가 {name: "진도사우르스"}로 바뀌었을 때, 어떤 과정을 거쳐 바뀐 값을 화면에 보여주는 지 라이프 사이클 흐름을 그려볼까요?
3. 양방향 바인딩은 무엇일까요? 양방향 바인딩을 사용하는 경우 리렌더링이 어떻게 이루어질 지 그려보세요. (부모 컴포넌트 A와 자식 컴포넌트 B가 있음을 가정하고 그려봅시다.)
4. event listener는 등록되면 반드시 해제되어야 합니다. 클래스형 컴포넌트에서는 컴포넌트가 화면에서 사라질 때(unmount 될 때) event listener를 해제합니다. (componentWillUnmount에서요!) 그럼 라이프사이클 메소드를 사용할 수 없는 함수형 컴포넌트에서는 event listener를 해제할 때 어떻게 해야할까요?
5. 리액트에서는 DOM 요소에 접근하기 위해 주로 ref를 씁니다. domcument.getElementsByClassName 등을 쓰는 게 아니라 ref를 쓰는 이유는 무엇일까요?
6. SPA 방식과 MPA 방식은 무엇인가요?
'Hanghae99' 카테고리의 다른 글
| 221201 TIL 07 문서 객체 모델 (Document Object Model) 2 (0) | 2022.12.01 |
|---|---|
| 221129 TIL 07 문서 객체 모델 1 (0) | 2022.12.01 |
| 221130 TIL React 입문주차 4 (0) | 2022.11.30 |
| 221128 TIL React 입문주차 3 (0) | 2022.11.29 |
| 221126 TIL React 입문 주차 2 (0) | 2022.11.28 |