diff --git a/_posts/book/micro-state-management.md b/_posts/book/micro-state-management.md new file mode 100644 index 00000000..d68ea633 --- /dev/null +++ b/_posts/book/micro-state-management.md @@ -0,0 +1,182 @@ +--- +title: 'Micro State Management with React Hooks 리뷰' +description: '상태 관리의 종류와 기술들에 대한 이해' +tags: + ['book', 'review', 'react', 'hooks', 'context', 'zustand', 'jotai', 'valtio'] +coverImage: 'https://github.com/1ilsang/dev/assets/23524849/3a57dcf8-43b1-4e95-ae8d-2b5194c83122' +date: '2024-03-01T00:00:00.000Z' +ogImage: + url: 'https://github.com/1ilsang/dev/assets/23524849/3a57dcf8-43b1-4e95-ae8d-2b5194c83122' +--- + +![cover](https://github.com/1ilsang/dev/assets/23524849/4e361695-129c-4d6b-885e-ad8805549b4a 'cover') + +[Micro State Management with React Hooks](https://product.kyobobook.co.kr/detail/S000061587593) 리뷰를 해보려고 한다. + +## 선택하게 된 계기 + +이 책은 작년에 읽었었는데, 당시에는 이해가 많이 안 돼서 깊이 있게 생각하지 못했었다. + +실무에서 [Jotai](https://github.com/pmndrs/jotai)를 사용하기 시작하면서 사용하는 라이브러리에 대한 이해를 높이고자 다시금 이 책을 읽게 되었다. + +이 책은 세 가지 흥미로운 부분이 있다. + +1. 원서다. 영어 기술 서적은 처음 읽어서 꽤 도전적이었다. +2. Zustand, Jotai 등을 만든 상태관리에 진심인 메인테이너 [Daishi Kato](https://github.com/dai-shi)가 직접 펴낸 책이다. +3. React에서의 상태 관리 전략을 다양하게 보여주기 때문에 시야가 넓어진다. + +다 읽고 나서 알게 되었는데, [이 책은 최근에 한국어로 번역되었다](https://product.kyobobook.co.kr/detail/S000212233308)(-\_-). 이때 아니면 언제 원서 읽었겠나 싶어 만족하려고 한다. + +## 간단한 요약 + +- 상태란 무엇일까? +- 상태는 어떻게 존재할 수 있을까? +- 상태를 변화시키는 방법은 어떤 것들이 있을까? +- React hooks은 상태 관리 라이브러리에 어떤 영향을 주었을까? +- 우리는 리렌더링을 어떻게 회피할 수 있을까? + +이 책을 읽으면서 얻을 수 있었던 인사이트들이다. + +너무 어렵게 들어가지 않으면서 상태 관리의 다양한 기법들을 제시하기 때문에 주니어부터 시니어까지 충분히 배울게 많은 책이라는 생각이 든다. + +## 인상 깊었던 부분 + +책을 읽으면서 좋았던 예제나 포인트들을 가볍게 소개하고자 한다. + +### 1. React State에 대한 이해 + +React에서 상태(state)는 UI를 나타내는 모든 데이터다. React는 상태와 함께 렌더링 할 컴포넌트를 처리한다. + +책의 서두에서 기존 상태 관리의 문제점에 대해 이야기한다. + +```md +React Hooks 이전에는 모놀리식 상태 라이브러리들이 유행했다. +이는 DX 향상에 큰 도움을 주었지만 사용되지 않는 기능들도 포함된다는 문제가 있었다. + +1. Form 상태는 글로벌 상태와 별도로 다루어져야 하지만, 단일 상태 솔루션에서는 불가능하다. +2. 서버 캐시 상태는 refetching과 같은 다른 상태들과는 다른 독특한 특징을 가지고 있으나 분리가 불가능하다. +3. 브라우저 네비게이션 상태는 원본값이 브라우저 측에 기반한다는 성질이 있어 단일 상태 솔루션에 적합하지 않다. + +이런 문제들을 해결하는 것이 React Hooks의 목표 중 하나이다. +``` + +위 내용을 요약하면 Hooks 이전의 상태는 상태의 순수함이 결여되어 있었다는 점이 문제라고 꼬집는다. + +상태는 전역 상태와 지역 상태가 있다. 지역으로 존재해야 할 데이터들이 전역 스토어에 혼재되어 있고 서버/브라우저 상태가 무분별하게 스토어에 들어 있었다. + +React Hooks로 위의 내용들을 해결하고자 한다는 내용이 인상적이었다. + +### 2. useState vs useReducer + +React 컴포넌트가 상태를 가지고 있으려면 어떻게 해야 할까? + +일반 변수나 전역 변수로 선언하고 사용할 수도 있다. 하지만 해당 값이 변경되었다고 한들 컴포넌트는 리렌더링 되지 않는다. + +컴포넌트가 지역 상태의 변경을 감지하고 리렌더링 하려면 `useState` 혹은 `useReducer`를 사용해야 한다. + +> +1. React는 전역 상태를 제공하지 않는다. + +```jsx +// CASE 1. +const [count, setCount] = useState(0); +setCount(1); +setCount(1); // Not render. 동일한 값이므로 렌더링 하지 않는다. + +// CASE 2. +const [state, setState] = useState({ count: 0 }); +setState({ count: 1 }); +setState({ count: 1 }); // Re-render! 주소 참조는 항상 다른 값이 된다. + +// CASE 3. +state.count = 1; +setState(state); // Not render. state 주소값은 변하지 않았기 때문에 렌더링 하지 않는다. + +// CASE 4. +setCount(count + 1); +setCount(count + 1); // 동일하게 두 번 호출되면 +2가 아닌 +1만 될 수 있다. 이를 해결하기 위해선 함수 업데이트가 필요하다. + +// CASE 5. +setCount((prev) => prev + 1); // 함수로 작성하게 될 경우 아무리 빠르게 눌러도 횟수만큼의 업데이트가 될 것을 보장한다. 이는 내부적으로 함수를 연속적으로 호출하기 때문이다. + +// CASE 6. +setCount((prev) => prev); // 결과값이 직전과 동일하기 때문에 리렌더링이 일어나지 않는다. + +/** + * init 함수는 useState를 호출하기 전에 실행되지 않는다(lazy initialize). + * 이는 컴포넌트가 마운트 될 때 한 번만 호출함을 뜻한다. + **/ +const init = () => 0; +const [count, setCount] = useState(init); +``` + +useState의 다양한 사용 사례를 들어 리렌더링이 되는 경우를 설명한다. 또한 지연 초기화 경우를 들어 상태 관리의 최적화에 관해 설명한다. + +```jsx +const init = (count) => ({ count, text: 'hi' }); +const reducer = (state, action) => { + switch(action.type) { + case 'INCREMENT': + return { ...state, count: state.count + 1 }; + case 'SET_TEXT': + if(!action.text) { + return state; // THIS IS Bailout! 리렌더링 되지 않음. + return { ... state, text: action.text }; + default: + throw new Error(`unkown action type`); + } + } +} + +const Component = () => { + const [state, dispatch] = useReducer(reducer, 10, init); + return ( +