1. 개요
- react의 전부라고 할 수 있는, 상태관리의 근본적인 원리도 모르고 쓰기는 react에게 미안하다.
- 실무에서 느낀 상태관리의 의의에 대해 다시 생각해 보고 싶었다.
2. 상태?
- react dev docs에 따르면, 직접적으로 명령에 대해 명시하지 않고, 시각적 상태에 따라 보고 싶은 UI를 설명한다고 한다.
- 즉, UI 변경에 따른 결과를 말 그대로 '상태'라고 할 수있고, 그것을 저장, 변경, 컴포넌트 간 전달한다.
- 이때, 상태는 UI 변경점에 따른 것이므로, 상태가 변하면 UI 도 자연스럽게 업데이트 될 것이다.
3. useState
- 하루에도 수 십번 사용하는 근본 hook.
- 상태를 변경하고, 사용할 수 있도록 한다.
const [data, setData] = useState([])
- 첫 번째 인자로 상태값을, 두 번째 인자로 상태를 변경할 함수를 받아 구조 분해 할당으로 사용하게 된다.
- 근본적 원리는, useState는 초기값을 처음 인자로 받아 disoatcher 인스턴스를 생성해, 유저가 원할 때마다 반환해 준다.
- 특이점 : 우리는 처음 'const'로 useState를 구조분해할당 했기 때문에 data가 직접 바뀌지는 않는다.
- 전역에 생성된 closuer가 useState가 실행될 때마다 초기값을 비교하고 할당해 준다.
- setState가 실행되면 받은 인수로 closuer의 값을 변경시켜 주고, 리렌더링을 실행하며, 바뀐 값을 useState가 가져온다.
4. 전역 상태 관리
- 결국, useState의 값은 한 컴포넌트 안에서만 사용가능하다.
- 같은 상태를 위계가 다른 컴포넌트에서 사용하려고 하거나, 상태를 props 드릴링 하다보면 상태의 생명주기를 알 수 없게 되고, 무분별한 리렌더링이 일어난다.
- 그래서 한번 선언한 상태를 다른 컴포넌트에서도 사용하기 위해 전역 수준에서 상태를 관리하기도 한다.
- 기본적인 방법으로 Context API를 사용할 수 있다.
- Context API는 '의존성 주입'을 위한 API 이다.
- ContextProvuder 컴포넌트를 만들어 내부에 useState를 사용해 상태를 만들어주고 value를 props로 받는다.
- value가 바뀔 때마다 상태를 변경해 주고 다시 바뀐 상태를 반환 한다.
- 이후 ContextProvuder 아래의 children들은 useContext hook으로 상태에 접근이 가능하다.
- 단점 : props의 value가 바뀔 경우 모든 children들은 리렌더링 된다. 결국 상태이기 때문이다. 그래서 불필요한 리렌더링을 막기 위해 memoization이 필수적이다. 결국, 어디서 memoization이 일어나고, 상태가 변경하는지를 정확히 알지 못하게 되는 경우가 프로젝트 사이즈가 커지면 종종 일어나기 때문에 상태의 생명주기를 어지럽히는 요인이 된다.
5. Zustand
- redux보다 간단하고, 필요 없는 렌더링을 조절하기가 간단한 전역 상태 관리 라이브러리이다.
import { create } from 'zustand'
const useStore = create((set) => ({
count: 1,
inc: () => set((state) => ({ count: state.count + 1 })),
}))
function Counter() {
const { count, inc } = useStore()
return (
<div>
<span>{count}</span>
<button onClick={inc}>one up</button>
</div>
)
}
- useState와 마찬가지로, 초기값, set 함수의 동작을 create 하고, hook으로 어디서든 접근이 가능하다.
- 일반적으로 create로 만든 hook 들을 한 파일에서 관리하고, 사용해야 할 컴포넌트에서 가져와 사용한다.
6. 적절한 상태관리란?
- 상태의 '범위'를 알고 사용하는 것이 중요하다. 각 스코프에 맞는 사이즈의 상태를 만들고, 상태의 생명주기를 개발자가 마음대로 조절할 수 있어야 한다. 불필요하게 모든 상태를 전역으로 사용하려 한다거나, 무분별한 props 드릴링으로 상태를 컴포넌트 간에 전달하는 방향은 다른 개발자들을 괴롭히는 일이다.
- 필요에 의한 상태만을 만든다. 상태로 관리해야 할 것은 'UI 변화에 따른 값'이다. 한번 선언해 놓고 더 이상 변하지 않는 값을 가진 경우나, 초기값만 이 중요한 경우라면 굳이, 상태로 만들지 않고 선언해서도 충분히 사용할 수 있다. 불필요한 리렌더링을 줄이는 것도 큰 의의가 있다.
- 여러 가지 전역 상태관리 라이브러리를 혼용해서 사용하지 않는다. 상태의 생명주기를 더욱 따라가기 힘들게 할 뿐이다.
- 의존적이지 않고, 결합적이지 않은 코드를 작성하기 위해서는 전역 상태 관리를 사용하지 않는 것이 좋다. 필요에 따라 사용할 수 도 있지만 분명, 재사용에 큰 제약을 만들 것이다.
'Coding > Today I Learned' 카테고리의 다른 글
2024.04.27(Sat.) <React Query를 통한 state에 관한 고찰 > (2) | 2024.04.27 |
---|---|
2023.08.11(Fri.) <Atomic Design Pattern> (0) | 2023.08.12 |
2023.07.27(Tue.) <얻은 알고리즘 문제 : 해싱, 시간파싱> (0) | 2023.07.27 |
2023.07.12(Wed.) <React 항상 z-index 최상위에 있는 Modal 만들기> (0) | 2023.07.12 |
2023.06.29(Tue.) <Blob Type Response의 에러 처리> (0) | 2023.06.29 |