728x90
반응형
📌 MobX (전역 상태 관리)
상태 관리 라이브러리는 여러 컴포넌트 간의 상태를 쉽게 관리할 수 있도록 돕는 도구입니다.
MobX는 전역적으로 상태를 관리할 수 있는 스토어(Store)를 제공하여,
상태를 한 곳에서 관리하고 필요할 때 접근할 수 있게 합니다.
이를 통해 컴포넌트 간에 상태를 계속 전달하지 않아도 되어 상태 관리가 간단해집니다.
📌 MobX 작동 원리
MobX는 단방향 데이터 흐름을 기반으로 작동합니다.
MobX에서의 상태 관리 과정은 다음과 같은 단계로 이루어집니다.
- Actions (액션)
상태를 변경하기 위한 함수
사용자가 어떤 동작을 취하면 그에 따라 상태를 변화시키는 역할 - Observable State (관찰 가능한 상태)
MobX에서 관리하는 데이터
이 데이터는 여러 컴포넌트에서 관찰될 수 있으며,
변화가 발생하면 이를 사용하는 컴포넌트가 자동으로 업데이트 - Computed Values (계산된 값)
Observable State가 변경될 때마다 자동으로 재 계산되는 값
이 값들은 주로 상태로부터 파생된 데이터를 계산할 때 사용 - Reactions (반응)
Observable State의 변화로 인해 발생하는 부수 효과(Side Effects)
예를 들어, 상태가 변경될 때마다 UI를 재 렌더링하거나
특정 로직을 실행하는 등의 작업 수행
📌 React에 MobX 적용
MobX는 상태 관리를 도와주는 라이브러리입니다.
MobX v6부터는 데코레이터를 사용하지 않고,
makeObservable 또는 makeAutoObservable 사용하여 상태를 설정합니다.
✅ MobX 라이브러리 설치
React에서 MobX를 사용하려면
mobx와 함께 mobx-react-lite 또는 mobx-react를 설치해야 합니다.
npm i mobx mobx-react
# mobx-react 함수형컴포넌트와 클래스형컴포넌트 모두 지원
npm install mobx mobx-react
# mobx-react-lite 함수형컴포넌트만 지원
npm install mobx mobx-react-lite
✅ MobX 스토어 생성 (상태 관리)
MobX에서는 상태를 관리하는 스토어(Store) 라는 개념이 있습니다.
Redux는 하나의 앱에 하나의 스토어만 사용할 수 있지만,
MobX는 여러 개의 스토어를 만들 수 있어 각 기능별로 독립적으로 관리할 수 있습니다.
- MobX 스토어 폴더 생성 (상태 관리 파일 모음)
- 상태를 관리할 파일들을 모아두기 위해 "📁mobx" 새 폴더 생성
- 스토어 클래스 생성 (상태 관찰 파일)
- 상태를 관리하고 관찰하기 위해 "스토어 클래스 생성"
- makeAutoObservable 사용해 상태가 자동으로 관찰될 수 있도록 설정합니다.
- 예 : 📜counter.tsx
- 스토어 내보내기 (📜index.tsx)
- 여러 스토어를 한 곳에서 관리하기 위해 "📜index.tsx" 파일에서 각 스토어를 내보냅니다.
- 폴더명만 적으면 기본적으로 index.tsx를 참조합니다.
- MobX
📁mobx/📜index.tsx 에서 스토어 내보내고,
컴포넌트에서 import stores from '../mobx';로 가져옵니다. - Hooks
📁hooks/📜index.tsx 에서 훅 내보내고,
컴포넌트에서 import { useToggle, useClamp } from '../hooks'; 로 가져옵니다.
- MobX
사용예시
✏️ 스토어 클래스 생성 (📜counter.tsx)
- 생성자에서 makeAutoObservable(this); 사용하면,
number 속성 관찰 대상(observable)이 되고,
increment, decrement 메서드 행동(action)이 됩니다. - 메서드(increment, decrement)들이 number 값을 변경하면,
MobX는 이 상태 변화를 자동으로 감지합니다. - MobX를 사용할 컴포넌트(예: LowComponent)를 observer 함수로 감싸면,
observer(LowComponent)는 Counter 스토어의 number 값 변경을 자동으로 감지하고,
값이 바뀌면 자동으로 다시 렌더링됩니다.
import { makeAutoObservable } from 'mobx';
class Counter {
number: number;
constructor() {
this.number = 0;
makeAutoObservable(this); // ▶ 상태와 메서드를 자동으로 설정
}
increment(value: number){
this.number += value; // 상태가 변경됩니다.
}
decrement(value: number){
this.number -= value; // 상태가 변경됩니다.
}
}
export default Counter;
✏️ 스토어 내보내기 (📜index.tsx )
- 각 스토어를 index.tsx에서 모아서 내보냅니다.
- counter 스토어를 다른 컴포넌트에서 import하여 사용할 수 있습니다.
import Counter from './counter';
export default {
counter: new Counter()
};
✅ 컴포넌트에서 MobX 스토어 사용
- App 컴포넌트 (Provider)
- <Provider {...stores}> 모든 스토어를 하위 컴포넌트에 전달합니다.
- 예를 들어, stores가 { counter: new Counter(), one: new One() } 형태일 때,
자식 컴포넌트는 이 스토어들을 사용할 수 있습니다. - <Observer />는 Provider 하위에서 스토어를 사용할 수 있게 해줍니다.
- inject와 observer 함수 (MobX 스토어 주입 및 상태 변화에 따른 컴포넌트 리렌더링)
- const Observer = inject('스토어클래스명')(observer(스토어사용할컴포넌트명));
- observer(LowComponent)
LowComponent를 observer로 감싸 상태 변화에 반응하도록 만듭니다. - inject('counter')
counter 스토어를 LowComponent에 주입하여 컴포넌트에서 사용할 수 있게 합니다.
- LowComponent 컴포넌트 (MobX 스토어 사용)
- Props에서 counter 타입을 정의합니다.
- 주입받은 counter 매개변수를 사용하여 UI를 렌더링하고,
버튼 클릭 시 스토어의 메서드(increment, decrement)를 호출하여 상태를 변경합니다. - observer(LowComponent)를 사용하면, LowComponent가 counter 스토어의 상태 변화를 감지하고,
상태가 변경되면 자동으로 화면이 업데이트됩니다. - 타입스크립트에서 counter?는
inject('counter')로 나중에 전달될 수 있어 선택적으로 설정합니다.
🔎 inject, observer 함께 사용 이유
- inject, observer를 함께 사용하는 이유는 두 가지 기능을 결합하기 위함
- inject 함수 필요한 MobX 스토어를 컴포넌트에 주입합니다.
이를 통해 컴포넌트는 특정 스토어의 상태와 메서드를 사용 - observer 함수 MobX 스토어의 상태 변화를 감지하고,
상태가 변경될 때 해당 컴포넌트를 자동으로 다시 렌더링
- inject 함수 필요한 MobX 스토어를 컴포넌트에 주입합니다.
사용예시
✏️ 컴포넌트에서 MobX 스토어 사용 (📜app.tsx )
Provider를 사용하여 애플리케이션의 모든 스토어를 하위 컴포넌트에 전달,
inject와 observer를 통해 특정 컴포넌트가 그 스토어를 사용하는 설정을 하고,
마지막으로 실제 컴포넌트가 그 스토어를 사용하여 UI를 구성하는 순서
- App 컴포넌트 (Provider)
- inject, observer 함수 (MobX 스토어 주입 및 상태 변화에 따른 컴포넌트 리렌더링)
- LowComponent 컴포넌트 (MobX 스토어 사용)
import React from 'react';
import stores from '../mobx';
import { inject, observer, Provider } from 'mobx-react';
// ▶ 'counter' 스토어를 LowComponent에 주입하고, 상태 변화를 감지하도록 설정
const Observer = inject('counter')(observer(LowComponent));
// ▶ Props 타입 정의: counter 스토어를 선택적으로 받을 수 있음
// Props 인터페이스에서 counter 속성은 선택적, 타입은 stores.counter
interface Props {
counter?: typeof stores.counter;
}
// ▶ LowComponent: counter 스토어를 사용하여 UI를 렌더링
function LowComponent({ counter }: Props) {
return (
<div>
<button onClick={() => counter?.increment(1)}>증가</button>
<button onClick={() => counter?.decrement(1)}>감소</button>
<div>{counter?.number}</div>
</div>
);
}
// ▶ Provider로 모든 스토어를 하위 컴포넌트에 제공
export default function App() {
return (
<div>
{/* stores 객체의 모든 속성(예: counter)을 Provider의 props로 전달 */}
<Provider {...stores}>
<Observer />
</Provider>
</div>
);
}
728x90
반응형