본문 바로가기
IT 개발

리액트 불변성을 지키는 이유와 방법

by gorokeya 2022. 2. 10.

이미지 출처 : https://evilmartians.com/chronicles/optimizing-react-virtual-dom-explained

 

리액트를 접하면서 불변성 개념에 대해 알게 되었다.

리액트 네이티브도 역시나 불변성을 지켜가면서 변화를 줘야 한다.

 

불변성을 지킨다는 것은?

객체 및 배열을 직접적으로 수정하지 않는다는 말이다.

즉, 기존 객체는 내버려 두고 새로운 객체를 만들어서 새로운 객체에 원하는 값을 덮어씌워야한다

 

 

왜 불변성을 지켜야 할까?

 

렌더링 성능 최적화 방식 때문이다.

리액트에서 부모 컴포넌트가 업데이트될 경우, 그 밑의 자식 컴포넌트도 전부 업데이트(리 렌더링)된다.

이는 변경사항이 따로 없음에도 자동적으로 함께 리 렌더링이 된다.

 

만약 컴포넌트에서 처리하는 데이터 및 연산량이 많을 경우에는 이러한 성능 최적화에 더욱 신경을 써야 한다.

리액트의 Virtual DOM이 Props의 변화를 감지하기 위해, 이전의 Props와 새로 받아오는 Props를 비교한다.

불변성을 지키지 않고 객체나 배열을 직접 변경하면? 리액트의 Virtual DOM이 Props의 변화를 감지하지 못한다.

 

// example이란 상수에 객체를 대입
const example = {id: 1, text: '텍스트'};

// sameExample에 example을 대입
const sameExample = example;

// sameExample의 text를 변경
const sameExample.text = '같은 텍스트';

// sameExample의 text를 변경하니 example의 text도 그대로 변경 (불변성 유지 X)
// 같은 객체이기 때문에 비교해도 true가 나옴
console.log(example === sameExample); // true

 

이렇게 될 경우, 객체의 값이 아무리 바뀌어도 같은 객체로 인식하기 때문에 리액트의 Virtual DOM이 인식하지 못한다.

리액트, 리액트 네이티브에서의 불변성을 유지하는 건 매우 중요하며 아래의 방법을 통해 리액트 불변성 지키는 방법에 대해 알아보자

 

 

 

1. 객체의 불변성 지키기

const menu = {
id: 1,
name: 'pizza'
};

// 불변성 지키지 않는 경우

menu.name = 'chicken';

// 불변성 지킨 경우

const newMenu = {
...menu,
name: 'chicken'
}

 

위에서 처럼... spread 연산자를 통해 원래 menu 객체의 값을 그대로 복사하고,

새로 만든 newMenu에... menu로 객체의 값을 펼쳐 넣는다.

그리고 변경하고 싶은 값만 작성하면 자동으로 덮여 써진다.

 

 

2. 배열의 불변성 지키기

// 불변성을 지키지 않는 배열 예제

const numbers = [0, 1, 2]

numbers.push(3); //추가
numbers[2] = 5; //수정
numbers.splice(0,2); //삭제

 

리액트 배열에서 push, splice는 가급적 사용하지 않는다. 이는 모두 배열을 직접 수정하기 때문이다

배열의 내장 함수를 통해 새로운 배열을 생성하여 상태를 업데이트해줘야 한다.

 

// 불변성을 지키는 배열 예제

const numbers = [0, 1, 2];

// 추가 (spread, concat)

const anotherNumbers = [...numbers, 3]
const anotherNumbers = numbers.concat([3, 4])

// 제거 (filter)

const filteredNumbers = numbers.filter(number => number > 0)
const filteredNumbers = numbers.filter((n, i) => i !== 1) // 인덱스 활용

// 수정 (map)

const mapNumbers = numbers.map(number => number === 0 ? 5 : number) // 값이 0이면 5로 변경, 나머지는 그대로

 

주로 배열의 불변성을 지키는 경우에는 위와 같은 배열의 내장 함수를 통해 추가, 제거, 수정을 한다.

 

 

여러 객체로 이루어진 배열을 다룰 때는

const items = [{ id: 1, text: '1번'}, {id: 2, text: '2번'}];

const newItems = items.map(item => item.id === 1 ? {...item, text: '1번 텍스트 변경'} : item);

 

배열 내부의 객체를 업데이트하는 경우에도 이와 같이 spread 연산자를 통해 불변성을 유지시켜줘야 한다.

반응형