[React] 상태 관리

유진·2023년 10월 30일

리액트

목록 보기
8/8

📝 상태 관리란?

상태 관리 기술이란 앱 상에서의 데이터를 메모리 등에 저장하고 하나 이상의 컴포넌트에서 데이터를 공유하는 것 이다.



MPA와 SPA의 상태관리 차이점

MPA : 서버의 데이터를 이용해 페이지를 렌더링하므로 클라이언트의 데이터와 서버의 데이터가 큰 차이를 가지지 않는다.
SPA : 자체적으로 데이터를 갖고 서버와의 동기화가 필요한 데이터만을 처리한다. 그외의 데이터는 Client만의 데이터로 유지한다.



상태 관리 기술의 도입

• 상태가 많지 않거나, 유저와의 인터렉션이 많지 않다면 매 작업 시 서버와 동기화하는 것으로 충분하지만 앱이 사용하는 데이터가 점점 많아지고, 유저와의 인터렉션 시 임시로 저장하는 데이터가 많아지는 경우 상태 관리를 고려해야 한다.
• 프론트엔드 뿐만 아니라, 백엔드와의 데이터 통신도 충분히 고려해야 한다. ex) GraphQL



📈 상태 관리 기술의 장점

• 높은 품질의 코드를 작성하는 데 유리하다.
• 성능 최적화, 네트워크 최적화 등에 유리하다.
• 데이터 관리의 고도화할 수 있다. ex) localStorage 활용한 persist state



📉 상태 관리 기술의 단점

• Boilerplate 문제가 있다.
• 파악해야 할 로직과 레이어가 많아진다.
• 잘못 사용할 경우, 앱의 복잡도만을 높이거나, 성능을 악화시킬 수 있다. ex) global state의 잘못된 활용 시 앱 전체 리렌더링 발생



Flux Pattern

1) Flux Pattern의 정의

2014년에 Facebook에서 제안한 웹 애플리케이션 아키텍처 패턴으로 Unidirectional data flow를 활용하여 데이터의 업데이트와 UI 반영을 단순화한다. React의 UI 패턴인 합성 컴포넌트와 어울리도록 설계되었다.
• redux, react-redux 라이브러리의 Prior art

2) MVC Pattern과 비교

MVC 패턴은 애플리케이션을 Model, View, Controller로 분리하여 개발하는 소프트웨어 디자인 패턴 중 하나이다. View에서 특정 데이터를 업데이트하면 연쇄적인 업데이트가 일어난다. 특정 유저의 인터렉션이 여러 UI 컴포넌트가 사용하는 데이터에 영향을 줄 때, MVC만으로는 앱의 복잡도를 낮추거나 업데이트의 흐름을 따라가기 어렵다. 앱이 커질수록 업데이트의 흐름을 따라가기 힘들다는 단점이 있다.
Flux는 하나의 Action이 하나의 Update만을 만들 수 있다. data와 업데이트가 한 방향으로 흐르기 때문에 UI의 업데이트를 예측하기 쉽다.

3) Flux Pattern의 구조

Action -> Dispatcher -> Store -> View 순으로 데이터가 흐른다.
• store : 미리 dispatcher에 callback을 등록해, 자신이 처리할 action을 정의한다.
• action creator : action을 생성하여 dispatcher로 보낸다.
• dispatcher : action을 store로 넘긴다.
• store : action에 따라 데이터를 업데이트 후, 관련 view로 변경 이벤트 발생한다.
• view : 데이터를 다시 받아와 새로운 UI를 만든다. 유저 인터렉션이 발생하면 View는 action을 발생한다.



상태 관리에 사용되는 훅

• 외부 라이브러리 없이 React가 제공하는 훅 만으로 상태 관리를 구현하기 위해 사용한다.
• 함수형 컴포넌트에 상태를 두고, 여러 컴포넌트 간 데이터와 데이터 변경 함수를 공유하는 방식으로 상태를 관리하게 된다.
useState, useRef, useContext, useReducer

1) useState

• 단순한 하나의 상태를 관리하기에 적합하여 상태와 상태에 대한 변화가 단순하거나, 상대적으로 소규모 앱에서 사용한다.
• 상위 컴포넌트에서 state와 state 변경 함수를 정의하고, 그 state나 변경 함수를 사용하는 컴포넌트까지 prop으로 내려주는 패턴이다.
• state가 변경되면, 중간에 state를 넘기기만 하는 컴포넌트들도 모두 리렌더링된다.
• useEffect와 함께, state에 반응하는 훅을 구축한다.

const [ state, setState ] = useState(initState | initFn)

2) useRef

• 상태가 바뀌어도 리렌더링하지 않는 상태를 정의한다. 상태가 UI의 변경과 관계없을 때 사용한다. ex) setTimeout의 timerId 저장
• uncontrolled component의 상태를 조작하는 등, 리렌더링을 최소화하는 상태 관리에 사용된다. ex) Dynamic Form 예시

3) useContext

• Provider 단에서 상태를 정의하고, 직접 상태와 변경 함수를 사용하는 컴포넌트에서 useContext를 이용해 바로 상태를 가져와 사용하는 패턴이다.
• 컴포넌트와 컴포넌트 간 상태를 공유할 때 사용한다.
• 부분적인 컴포넌트들의 상태 관리, 전체 앱의 상태 관리를 모두 구현한다.
• state는 필요한 곳에서만 사용하므로, 불필요한 컴포넌트 리렌더링을 방지한다.
• Context Provider 안에서 렌더링되는 컴포넌트는, useContext를 이용해 깊이 nested 된 컴포넌트라도 바로 context value를 가져온다.
• context value가 바뀌면 내부 컴포넌트는 모두 리렌더링된다.
• useReducer와 함께 복잡한 상태와 상태에 대한 변경 로직을 두 개 이상의 컴포넌트에서 활용하도록 구현 가능하다.
• Prop Drilling(Plumbing)을 방지하여 컴포넌트 간 결합도를 낮춘다.

4) useReducer

• useState보다 복잡한 상태를 다룰 때 사용한다.
• 별도의 라이브러리 없이 flux pattern에 기반한 상태 관리를 구현한다.
• nested state 등 복잡한 여러 개의 상태를 한꺼번에 관리하거나, 어떤 상태에 여러 가지 처리를 적용할 때 유용하다.
• 상태 복잡하다면, useState에 관한 callback을 내려주는 것보다 dispatch를 prop으로 내려 리렌더링을 최적화하는 것을 권장한다.

const [state, dispatch] = useReducer(reducer, initState)
profile
도라에몽 암기빵

0개의 댓글