2024. 4. 24. 21:49ㆍ지식&개념
리엑트의 가장 중요한 특징이라고 하면 불변성일 것이다.
아래의 궁금증을 가지며 글을 작성해본다.
리엑트는 왜 불변성을 가질까?
불변성을 지켜 어떤 이점을 가져갈 수 있고, 그에 따른 단점이 무엇일까?
불변성
불변성은 메모리에 있는 값을 변경할 수 없는 것을 말한다.
하지만 우리는 변수의 값을 곧 잘 변경했었다. 편의상 변경이라고는 하지만 내부적으로는 변하지 않는다.
변수는 기존 값을 참조하고, 변수의 값을 변경시 새로운 값이 생성되고 변수는 새로 생성된 값을 참조하게 된다. 아무런 참조가 없는 값은 가비지 콜렉터가 처리하게 된다.
- 원시 데이터(string, number, boolean, null, undefined, Symbol) : 불변성이 있다.
- 원시 데이터는 수정시, 메모리에 저장된 값 자체는 바꿀 수 없고, 새로운 메모리 저장 공간에 새로운 값을 저장한다.
- 원시 데이터가 아닌 데이터(Object 타입 : 객체, 배열, 함수 등) : 불변성이 없다.
- 원시 데이터가 아닌 데이터는 수정했을 때 기존에 저장되어 있던 메모리 저장 공간의 값 자체를 변경한다.
프로그래밍 및 데이터 구조의 맥락에서 불변성은 일단 인스턴스화 되면 내부 상태에 대한 수정을 방지하는 객체 또는 데이터 구조의 속성을 나타낸다.
기존 객체를 수정하는 대신 해당 상태를 변경하면 원하는 변경 사항이 포함된 새 객체가 생성된다.
불변 패러다임
불변 데이터는 함수형 프로그래밍에서 파생된 개념이다.
간단히 불변 객체는 한번 생성되면 변경할 수 없는 객체이다.
javascript 및 react 의 맥락에서 이는 기존 객체를 수정하는 대신 변경을 원할 때마다 상태의 새 버전을 생성한다는 의미이다.
React 불변성의 이점
javascript 는 기본적으로 변경 가능한 데이터 구조를 허용한다. 이는 변수가 시간이 지남에 따라 값을 변경할 수 있음을 의미한다.
가변성은 편리할 수 있지만 코드에 복잡성과 예상치 못한 동작이 발생할 수 있다.
반면 불변성은 예측 가능하고 안정적인 프로그래밍 스타일을 촉진한다. 데이터를 변경할 수 없으면 예기치 않게 변경되지 않으므로 버그가 줄어들고 디버깅이 쉬워진다.
react 내에서 불변성의 주요 이점은 조정 프로세스, 즉 DOM 을 효율적으로 업데이트하는 react의 방식에 있다.
이전 상태와 새 상태를 비교하여 react 는 어떤 변경이 필요한지 결정한다.
불변 데이터를 사용하면 객체를 심층적으로 비교하는 대신 이전 참조와 새 참조가 다른지 간단하게 확인할 수 있어 비교가 훨씬 빠르고 효율적이다.
- 일관성 : 불변 데이터 구조는 수명 내내 일관된 상태로 유지된다. 일단 생성되면 예상치 못한 수정에 대한 걱정 없이 프로그램의 여러 부분에서 안전하게 공유할 수 있다.
- 예측 가능성 : 불변성은 실수로 객체의 상태를 변경할 수 없기 때문에 코드를 예측할 수 있다. 이렇게 하면 버그 가능성이 줄어들고 코드에 대해 더 쉽게 추론할 수 있다.
- 동시성 : 불변 데이터 구조는 잠금 및 동기화 메커니즘이 필요 없기 때문에 동시 또는 다중 스레드 프로그래밍에 적합하다. 데이터는 변경될 수 없으므로 여러 스레드가 동시에 안전하게 액세스 할 수 있다.
- 함수형 프로그래밍 : 불변성은 함수형 프로그래밍의 기본 개념이다. 함수형 프로그래밍 언어와 패러다임은 불변 데이터 작업을 강조하며, 이는 선언적이고 순수한 함수로 이어진다.
- 성능 : 새로운 객체를 생성하는 것이 비효율적으로 보일 수 있지만 최신 프로그래밍 언어와 라이브러리는 새로운 불변 객체를 생성하는 프로세스를 최적화한다. 대부분의 불변 데이터 구조는 복사와 같은 특정 작업의 경우 변경 가능한 데이터 구조만큼 효율적일 수 있다.
불변성의 단점
- 메모리 소비 : 변경이 이루어 질 때마다 새로운 데이터 복사본을 생성하는 것은 대규모 데이터 세트의 경우 리소스 집약적일 수 있다. 때문에 불변 데이터 구조에는 더 많은 메모리가 필요한 경우가 많다.
- 성능 오버헤드 : 일부 시나리오에서는 새로운 데이터 복사본을 생성하는데 따른 성능 오버헤드가 불변성의 이점보다 클 수 있다. 실시간 애플리케이션이나 메모리가 제한된 상황에서는 불변성이 최선이 아닐 수 있다.
- 업데이트의 복잡성 : 변경 불가능한 데이터를 업데이트하는 것은 변경 가능한 데이터를 제자리에 수정하는 것 보다 덜 직관적일 수 있다. 어떤 경우에는 사소한 업데이트를 위해 완전히 새로운 데이터 구조를 생성하면 코드가 복잡해질 수 있다.
- 호환성 : 변경 불가능한 데이터를 기존 코드베이스, 변경 가능한 데이터에 의존하는 코드베이스에 통합하는 것은 어려울 수 있다. 이 전환에는 불변성을 수용하기 위한 리펙토링 및 조정이 필요할 수 있다.
변경가능과 불변
// 배열 수정(변경 가능)
const mutableArr = [1, 2, 3];
mutableArr.push(4);
// 새 배열 생성(불변)
const immutableArr = [1, 2, 3];
const newImmutableArr = [...immutableArr, 4];
이처럼 불변성은 변하지 않고 일관되며 예측 가능한 데이터 구조의 생성을 촉진한다.
동작
1. 불변 데이터
react 는 객체를 포함한 불변 데이터 구조의 사용을 권장한다. react 에서 객체를 업데이트 할 때 기존 객체를 수정하는 대신 새 객체를 생성해야 한다. react 는 구성 요소를 다시 렌더링할 시기를 결정하기 위해 참조 동일성에 의존하기 때문에 중요하다. 객체를 제자리에서 수정하면 react 가 변경 사항을 감지하지 못하고 다시 렌더링을 트리거하지 않을 수 있다.
// 안좋음 : 상태 객체를 직접 변경
this.state.user.name = 'New Name';
// 좋음 : 업데이트 된 데이터를 사용하여 새 객체 생성
const updateUser = { ...this.state.user, name: 'New Name' };
this.setState({ user: updateUser })
2. useState 훅
기능적 구성 요소에서 useState 훅을 사용할 때 react 는 업데이트 된 값이 포함된 새 개체를 전달하여 상태를 업데이트 하는 방법을 제공한다. react 는 변경사항을 기존 상태 객체에 병합한다.
const [user, setUser] = useState({ name: 'yeon', age: 30 });
// 새 객체로 상태 업데이트
setUser({ ...user, name: 'New Name' });
3. 객체 참조 평등
react는 객체 참조 평등을 사용해 구성 요소를 다시 렌더링할지 여부를 결정한다. 객체의 속성이 변경될 때 구성 요소가 다시 렌더링 되도록 하려면 해당 변경 사항이 포함된 새 객체를 만들어야 한다. 이는 객체를 하위 구성 요소에 소품으로 전달할 때 중요하다.
// ParentComponent.jsx
const [user, setUser] = useState({ name: 'yeon', age: 30 });
// ChildComponent.jsx
const ChildComponent = ({user}) => {
// 사용자 개체 참조가 변경되지 않으면 이 구성요소는 다시 렌더링되지 않는다.
// 구성 요소에서 user.name 및 user.age 를 사용해야 한다.
}
4. useEffect 훅
useEffect 훅을 사용할 때 종속성을 지정하여 효과가 실행되어야 하는 시기를 결정할 수 있다.
개체 참조가 종속성 배열에 포함되어 있으면 개체 참조가 변경될 때마다 효과가 실행된다.
useEffect(() => {
// 이 효과는 user 개체 참조가 변경되면 실행된다.
// user가 변경되면 작업을 수행
}, [user]);
5. Context API
상태 관리를 위해 react 의 context API 를 사용하는 경우 해당 컨텍스트를 소비하는 구성 요소에서 다시 렌더링을 트리거하기 위해 컨텍스트 값을 업데이트 할 때 새 객체를 생성하는 것이 중요하다.
const MyContext = createContext();
const MyProvider = ({ children }) => {
const [value, setValue] = useState({ data: 'initial' });
const updateValue = () => {
// 컨텍스트 값을 업데이트 하기 위해 새 객체를 생성한다.
setValue({ ...value, data: 'updated' });
};
return (
<MyContext.Provider value={{ value, updateValue }}>
{ children }
</MyContext.Provider>
);
};
요약하자면 react 의 객체 참조는 불변으로 처리되어야 하며, react 애플리케이션에서 적절한 렌더링 및 상태관리를 보장하기 위해 필요할 때 업데이트 된 데이터로 새 객체를 생성해야 한다.
객체를 직접 변경하면 예상치 못한 동작과 버그가 발생할 수 있다.
'지식&개념' 카테고리의 다른 글
자바스크립트의 역사 (0) | 2024.04.23 |
---|---|
토큰에 대한 고민 (0) | 2024.04.22 |
UUID (Universally Unique IDentifier) (1) | 2024.04.19 |
단방향 데이터 바인딩 양방향 데이터 바인딩 (0) | 2024.04.18 |
Angular vs React vs Vue (0) | 2024.04.16 |