목 차
1. 리엑트 네이티브(RN)의 동작 원리.
2. 리엑트 네이티브(RN)의 플랫폼 파트 ( 구성 요소 )
3. 리엑트 네이티브(RN)의 애플리케이션 동작 순서 및 뉴 아키텍처.
4. 리엑트 네이티브에서 상태관리는 어떻게?
------------
5. 리엑트 네이티브에서 에러 핸들링과 디버깅은 어떻게?
6. 네이티브 모듈을 사용하여 기기의 하드웨어 기능에 어떻게 접근하는가?
목 차
1. 리엑트 네이티브 상태 관리 개요.
2. 상태 관리의 필요성
3. 내장 상태 관리 방법들.
3-1. useState
3-2. this.setState
4. Context API
5. 외부 라이브러리 활용.
5-1. Redux.
5-2. Recoil.
5-3. MobX.
5-4. Zustand.
6. 상태 관리 모범 사례
7. 결론 및 요약
리액트 네이티브에서 상태 관리는 앱의 데이터를 효율적으로 관리하고,
UI를 동적으로 업데이트하는 데 중요한 역할을 합니다.
특히, 복잡한 앱을 개발할 때 상태 관리가 더욱 중요해집니다.
상태 관리에는 여러 가지 방법과 라이브러리가 있으며, 각기 다른 장점과 사용 사례가 있습니다.
리액트 네이티브는 내장된 상태 관리 방법과
외부 라이브러리를 통해 다양한 상태 관리 요구를 충족시킬 수 있습니다.
내장된 방법으로는 useState와 this.setState가 있으며,
외부 라이브러리로는 Redux, Recoil, MobX, Zustand 등이 있습니다.
상태 관리가 필요한 이유는 다음과 같습니다.
동적 UI 업데이트:
데이터 일관성 유지:
복잡한 로직 처리:
성능 최적화:
이 방법은 리액트의 기본 기능을 활용하여 '상태'를 관리하는 데 사용됩니다.
내장 상태 관리 방법에는 'useState', 'this.setState', 'useReducer' 가 있습니다.
import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';
const CounterApp = () => {
const [count, setCount] = useState(0);
return (
<View>
<Text>{count}</Text>
<Button title="Increment" onPress={() => setCount(count + 1)} />
</View>
);
};
장점:
클래스 컴포넌트에서 유용합니다.
상태를 업데이트할 때 자동으로 UI를 갱신합니다.
한계:
함수형 컴포넌트에서는 사용할 수 없습니다.
복잡한 상태 관리에는 적합하지 않을 수 있습니다.
import React, { Component } from 'react';
import { View, Text, Button } from 'react-native';
class CounterApp extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
render() {
return (
<View>
<Text>{this.state.count}</Text>
<Button title="Increment" onPress={() => this.setState({ count: this.state.count + 1 })} />
</View>
);
}
}
장점:
복잡한 상태 논리를 쉽게 관리할 수 있습니다.
상태의 흐름을 명확히 파악할 수 있습니다.
한계:
초기 설정이 복잡할 수 있습니다.
상태 관리가 간단한 경우에는 불필요할 수 있습니다.
import React, { useReducer } from 'react';
import { View, Text, Button } from 'react-native';
const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
};
const CounterApp = () => {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<View>
<Text>{state.count}</Text>
<Button title="Increment" onPress={() => dispatch({ type: 'increment' })} />
<Button title="Decrement" onPress={() => dispatch({ type: 'decrement' })} />
</View>
);
};
context API는 여러 컴포넌트 간에 데이터를 공유할 때 유용합니다.
이는 prop driling을 피하고, 전역적으로 데이터를 관리하는 데 적합합니다.
import React, { createContext, useState } from 'react';
import { View, Text } from 'react-native';
const ThemeContext = createContext();
const App = () => {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Toolbar />
</ThemeContext.Provider>
);
};
const Toolbar = () => {
const { theme } = useContext(ThemeContext);
return (
<View>
<Text>Current theme: {theme}</Text>
</View>
);
};
중앙화된 상태 :
액션과 리듀서 :
상태를 업데이트하려면 '액션'을 디스패치해야 하며,
'리듀서' 함수가 이 액션을 처리하여 상태를 업데이트합니다.
액션.
리듀서.
리듀서의 역할 :
리듀서의 구조 :
장점:
복잡한 상태 관리에 적합합니다.
상태의 흐름을 명확히 파악할 수 있습니다.
문서화가 잘 되어 있고 커뮤니티가 활발합니다.
한계:
초기 설정이 복잡할 수 있습니다.
보일러플레이트 코드가 많을 수 있습니다.
성능이 다른 라이브러리보다 떨어질 수 있습니다.
import { createStore } from 'redux';
import { Provider } from 'react-redux';
const initialState = { count: 0 };
const reducer = (state = initialState, action) => {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 };
default:
return state;
}
};
const store = createStore(reducer);
const App = () => {
return (
<Provider store={store}>
<CounterApp />
</Provider>
);
};
atoms: 상태의 기본 단위로, 업데이트와 구독이 가능합니다.
selectors: atoms나 다른 selectors를 입력으로 받아 파생된 상태를 제공하는 함수입니다.
atom의 역할: atom은 상태의 기본 단위로, 업데이트와 구독이 가능합니다.
atom의 구조: atom은 key와 default 값을 가지며, 이는 상태의 식별자와 초기 값을 정의합니다.
selector의 역할:
selector의 구조: selector는 get 함수를 통해 상태를 계산하고,
장점:
간단하고 유연한 API를 제공합니다.
성능 최적화에 적합합니다.
기존 코드와 원활하게 통합됩니다.
한계:
상대적으로 새로운 라이브러리라서 커뮤니티가 작을 수 있습니다.
문서가 일부 경쟁 라이브러리만큼 포괄적이지 않을 수 있습니다.
import { atom, useRecoilState } from 'recoil';
const countState = atom({
key: 'countState',
default: 0,
});
const CounterApp = () => {
const [count, setCount] = useRecoilState(countState);
return (
<View>
<Text>{count}</Text>
<Button title="Increment" onPress={() => setCount(count + 1)} />
</View>
);
};
observable:
action:
reaction:
장점:
한계:
import { observable, action } from 'mobx';
import { observer } from 'mobx-react';
class CounterStore {
@observable count = 0;
@action
increment() {
this.count++;
}
}
const store = new CounterStore();
const CounterApp = observer(() => {
return (
<View>
<Text>{store.count}</Text>
<Button title="Increment" onPress={store.increment} />
</View>
);
});
Zustand는 Context API를 기반으로 하는 가벼운 상태 관리 라이브러리입니다.
특히 중소 규모의 애플리케이션에 적합하도록 설계되었습니다.
create 함수:
useStore 훅:
장점:
한계:
import create from 'zustand';
const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}));
const CounterApp = () => {
const { count, increment } = useStore();
return (
<View>
<Text>{count}</Text>
<Button title="Increment" onPress={increment} />
</View>
);
};
atom:
useSetAtom:
장점:
한계:
import { atom, useSetAtom } from 'jotai';
const countAtom = atom(0);
const CounterApp = () => {
const [count, setCount] = useSetAtom(countAtom);
return (
<View>
<Text>{count}</Text>
<Button title="Increment" onPress={() => setCount(count + 1)} />
</View>
);
};
-Valtio는 Recoil과 MobX의 영향을 받은 반응형 상태 관리 라이브러리입니다.
proxy: 상태를 프록시로 감싸 반응형으로 만듭니다.
useProxy: 상태를 사용하는 훅입니다.
proxy의 역할:
proxy의 구조:
useProxy의 역할:
useProxy의 구조:
장점:
한계:
import { proxy, useProxy } from 'valtio';
const state = proxy({ count: 0 });
const CounterApp = () => {
const snap = useProxy(state);
return (
<View>
<Text>{snap.count}</Text>
<Button title="Increment" onPress={() => state.count++} />
</View>
);
};
models: 상태의 구조를 정의하는 모델입니다.
actions: 상태를 수정하는 함수입니다.
action의 역할:
action의 구조:
장점:
한계:
import { types } from 'mobx-state-tree';
const CounterModel = types.model('Counter', {
count: types.number,
}).actions(self => ({
increment() {
self.count++;
},
}));
const store = CounterModel.create({ count: 0 });
const CounterApp = observer(() => {
return (
<View>
<Text>{store.count}</Text>
<Button title="Increment" onPress={store.increment} />
</View>
);
});
createSlice: 상태와 리듀서를 한 번에 생성하는 함수입니다.
configureStore: 스토어를 쉽게 설정하는 함수입니다.
createSlice의 역할:
createSlice의 구조:
configureStore의 역할:
configureStore의 구조:
장점:
한계:
import { configureStore, createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { count: 0 },
reducers: {
increment(state) {
state.count++;
},
},
});
const store = configureStore({
reducer: {
counter: counterSlice.reducer,
},
});
const CounterApp = () => {
const { count, increment } = useSelector((state) => state.counter);
const dispatch = useDispatch();
return (
<View>
<Text>{count}</Text>
<Button title="Increment" onPress={() => dispatch(increment())} />
</View>
);
};
1.로컬 상태 사용:
2.불변 데이터 구조 사용:
3.중복 상태 피하기:
4.테스트 가능성 고려:
5.최적화 기법 활용:
6.상태 구조를 단순화:
7.명확한 명명 규칙 사용:
리액트 네이티브에서 상태 관리는
앱의 데이터를 효율적으로 관리하고, UI를 동적으로 업데이트하는 데 중요한 역할을 합니다.
다양한 상태 관리 방법과 라이브러리가 있으며, 각기 다른 장점과 사용 사례가 있습니다.
내장 상태 관리 방법:
외부 라이브러리:
상태 관리를 선택할 때는 앱의 복잡성, 성능 요구 사항, 개발자 팀의 경험 등을 고려해야 합니다.