꽃 같은 인생
React&Redux ✨ React - 상태관리 심화 🌈 본문
🌐 React 전역 상태관리 개념 정리 노트 🌐
🎯 1. 전역 상태관리의 장점
- 리액트는 대표적인 SPA라이브러리이고 SPA구현방법은 상태변경 → 리렌더링 이기에 상태를 잘 관리 하는 것이 매우 중요하다.
🎨 리액트 전역 상태 관리 개념
- 리액트 전역 상태 관리는 여러 컴포넌트 간 데이터 공유를 효율적으로 처리하는 방법.
- 로컬 상태(useState)로는 관리하기 어려운 글로벌 데이터(예: 사용자 정보, 테마 설정, 로그인 상태 등)를 전역에서 일관되게 사용할 수 있다.
- 전역 상태 관리가 필요한 이유:
- ⚡ props drilling 문제 해결
- ♻️ 반복적인 데이터 전달 방지
- 🔗 컴포넌트 간 상태 일관성 유지
📌 데이터 일관성 및 유지보수
- 여러 컴포넌트에서 동일한 데이터를 공유할 때 중앙에서 관리하여 일관성 유지가 가능
- 상태가 한 곳에서 관리되기 때문에 버그 추적과 수정이 용이.
- 전역 상태를 활용하면 대규모 프로젝트에서도 유지보수성이 높아짐
🔗 Props Drilling 문제
- 정의: 부모 컴포넌트에서 자식, 손자 컴포넌트로 데이터를 계속 전달하는 방식
- 문제점:
- 중간 컴포넌트가 데이터를 실제로 사용하지 않아도 전달만 해야 해서 코드가 복잡해진다.
- 컴포넌트 구조가 복잡해질수록 가독성 저하와 유지보수성 악화가 발생할 수 있다.
💡 전역 상태 관리의 필요성
- Props Drilling 문제 해결: 복잡한 컴포넌트 구조에서 불필요한 props 전달 없이 데이터를 쉽게 공유할 수 있다.
- 중앙 집중형 관리: 여러 컴포넌트가 동일한 데이터를 공유할 때, 중앙 집중형 관리를 통해 효율성을 높일 수 있다.
- 규모 확장성: 애플리케이션 규모가 커질수록 상태 동기화 문제와 버그 발생 위험을 줄일 수 있다.
🌟 리액트 전역 상태 관리 방법
🔥 방법 🌟 설명 💡 장점 ⚡ 단점
| 🎨 Props Drilling | 부모에서 자식 컴포넌트로 props를 통해 데이터 전달 | 단순 구현, 기본 React 기능만 사용 | 트리 깊을수록 관리 어려움 |
| 🌿 Context API | createContext와 useContext로 전역 상태 공유 | 간단한 전역 상태 관리, props drilling 해결 | 대규모 앱에서 성능 문제 발생 가능 |
| 💎 Redux | 상태를 store에 저장하고 action, reducer로 업데이트 | 대규모 앱에서 일관된 상태 관리 | 보일러플레이트 코드 많음 |
| 🚀 Redux Toolkit | Redux 설정을 간소화하고 코드량을 줄이는 표준 툴킷 | 간결한 코드, DevTools 통합 지원 | Redux 개념 이해 필요 |
⚛️ 2. React 내부 구현 상태관리
🌿 내부 상태 관리 방법
✅ useState
- 간단한 상태 관리를 위한 기본적인 React Hook이다.
- 컴포넌트 내부에서 상태를 선언하고 갱신하는 데 사용된다.
- 💡 예시 코드:
- import React, { useState } from 'react'; const Counter = () => { const [count, setCount] = useState(0); return ( <div> <p>카운트: {count}</p> <button onClick={() => setCount(count + 1)}>증가</button> </div> ); }; export default Counter;
⚡ useReducer
- 복잡한 상태 로직이나 다수의 상태 값을 다룰 때 사용돼.
- 리듀서 패턴을 통해 상태를 체계적으로 관리할 수 있어.
- 💡 예시 코드:
- import React, { useReducer } from 'react'; 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 Counter = () => { const [state, dispatch] = useReducer(reducer, { count: 0 }); return ( <div> <p>카운트: {state.count}</p> <button onClick={() => dispatch({ type: 'INCREMENT' })}>증가</button> <button onClick={() => dispatch({ type: 'DECREMENT' })}>감소</button> </div> ); }; export default Counter;
🌈 Context API
📌 개념
- 전역 상태를 손쉽게 관리할 수 있는 React 내장 기능
- createContext, Provider, useContext를 사용해 구현
- 컴포넌트 트리 전체에 데이터를 전달하여 props drilling 문제를 해결
🌟 특징
- 별도의 라이브러리 없이 전역 상태 공유가 가능
- 단순한 구조로 빠르게 구현할 수 있지만, 빈번한 업데이트 시 성능 이슈에 주의
💡 Context API 사용 예시
// 📁 context/UserContext.js
import React, { createContext, useState, useContext } from 'react';
const UserContext = createContext();
export const UserProvider = ({ children }) => {
const [user, setUser] = useState(null);
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
};
export const useUser = () => useContext(UserContext);
// 📁 App.js
import React from 'react';
import { UserProvider, useUser } from './context/UserContext';
const Profile = () => {
const { user } = useUser();
return <div>{user ? `안녕하세요, ${user.name}님!` : '로그인해주세요.'}</div>;
};
const App = () => (
<UserProvider>
<Profile />
</UserProvider>
);
export default App;
⚖️ 장단점
- ✅ 장점: 간단하고 props drilling 문제 해결
- ⚠️ 단점: 대규모 앱에서 성능 저하 발생 가능
🚀 3. React 외부 구현 상태관리
🌍 외부 상태 관리 방법
- 전용 상태관리 라이브러리를 사용하여 복잡한 상태 관리 문제를 해결할 수 있어.
- 주요 라이브러리:
- Redux
- Redux Toolkit
- 기타: MobX, Recoil, Zustand 등
💎 Redux & Redux Toolkit
📌 Redux
- 특징:
- 모든 상태를 **하나의 스토어(Store)**에 저장.
- *액션(Action)**과 **리듀서(Reducer)**를 통해 상태 변경을 관리.
- 단방향 데이터 흐름으로 디버깅과 유지보수가 용이해.
- 💡 Redux의 장점: 대규모 프로젝트에서 예측 가능한 상태 관리와 디버깅 편의성 제공.
⚡ Redux Toolkit
- 목적: Redux 사용 시 발생하는 보일러플레이트 코드를 줄여 간편하게 사용할 수 있도록 해.
- 내장 기능:
- createSlice: 액션과 리듀서를 한 번에 생성.
- createAsyncThunk: 비동기 로직 간편 처리.
- 💡 Redux Toolkit 추천 이유:복잡한 상태 관리를 더 효율적이고 직관적으로 구현할 수 있어.
💡 Redux Toolkit 사용 예시
npm install @reduxjs/toolkit react-redux
// 📁 store.js
import { configureStore, createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => { state.value += 1; },
decrement: (state) => { state.value -= 1; },
},
});
export const { increment, decrement } = counterSlice.actions;
const store = configureStore({
reducer: {
counter: counterSlice.reducer,
},
});
export default store;
// 📁 App.js
import React from 'react';
import { Provider, useSelector, useDispatch } from 'react-redux';
import store, { increment, decrement } from './store';
const Counter = () => {
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();
return (
<div className="p-4 text-center">
<h1 className="text-3xl mb-4">카운트: {count}</h1>
<button className="px-4 py-2 bg-green-500 text-white mr-2" onClick={() => dispatch(increment())}>
증가
</button>
<button className="px-4 py-2 bg-red-500 text-white" onClick={() => dispatch(decrement())}>
감소
</button>
</div>
);
};
const App = () => (
<Provider store={store}>
<Counter />
</Provider>
);
export default App;
✨ 전역 상태관리 요약 ✨
💡 개념 🌟 설명 💎 장점 ⚠️ 단점
| ⚡ Props Drilling | 상위 컴포넌트에서 하위로 props 전달 | 간단한 구조에서 적합 | 깊은 트리에서 비효율적 |
| 🌿 Context API | React 내장 전역 상태관리 도구 | 별도 설치 없이 사용 가능 | 큰 상태 변경 시 리렌더링 발생 |
| 🚀 Redux | 중앙 집중식 상태 관리 | 대규모 앱에 적합, 강력한 생태계 | 초기 설정 복잡 |
| 🎯 Redux Toolkit | Redux를 더 쉽게 사용하도록 도와주는 공식 툴킷 | 간편한 설정, 비동기 지원 내장 | 러닝커브 존재 |
⚛️ React 상태관리 심화 노트 ⚛️
🎨 1. 리액트 전역 상태 관리 개념
- 리액트 전역 상태 관리는 여러 컴포넌트 간 데이터 공유를 효율적으로 처리하는 방법.
- 로컬 상태(useState)로는 관리하기 어려운 글로벌 데이터(예: 사용자 정보, 테마 설정, 로그인 상태 등)를 전역에서 일관되게 사용할 수 있다.
- 전역 상태 관리가 필요한 이유:
- ⚡ props drilling 문제 해결
- ♻️ 반복적인 데이터 전달 방지
- 🔗 컴포넌트 간 상태 일관성 유지
🌟 2. 리액트 전역 상태 관리 방법
🔥 방법 🌟 설명 💡 장점 ⚡ 단점
| 🎨 Props Drilling | 부모에서 자식 컴포넌트로 props를 통해 데이터 전달 | 단순 구현, 기본 React 기능만 사용 | 트리 깊을수록 관리 어려움 |
| 🌿 Context API | createContext와 useContext로 전역 상태 공유 | 간단한 전역 상태 관리, props drilling 해결 | 대규모 앱에서 성능 문제 발생 가능 |
| 💎 Redux | 상태를 store에 저장하고 action, reducer로 업데이트 | 대규모 앱에서 일관된 상태 관리 | 보일러플레이트 코드 많음 |
| 🚀 Redux Toolkit | Redux 설정을 간소화하고 코드량을 줄이는 표준 툴킷 | 간결한 코드, DevTools 통합 지원 | Redux 개념 이해 필요 |
🌿 3. Props Drilling 실습
🌿 개념
- 상위 컴포넌트가 하위 컴포넌트로 데이터를 전달할 때 여러 단계를 거치는 현상.
💡 예시 코드
const Child = ({ message }) => <p>{message}</p>;
const Parent = ({ message }) => <Child message={message} />;
const App = () => {
const message = "Hello from App!";
return <Parent message={message} />;
};
export default App;
⚖️ 장단점
- ✅ 장점: 단순하고 React 기본 기능만 사용
- ⚠️ 단점: 트리가 깊어질수록 데이터 전달이 복잡해짐
💎 4. Context API
🌟 개념
- 전역 상태를 손쉽게 관리할 수 있는 React 내장 기능.
- createContext, Provider, useContext를 사용해 구현.
💡 예시 코드
import React, { createContext, useContext, useState } from 'react';
const MessageContext = createContext();
const MessageProvider = ({ children }) => {
const [message, setMessage] = useState("Hello from Context!");
return (
<MessageContext.Provider value={{ message, setMessage }}>
{children}
</MessageContext.Provider>
);
};
const Child = () => {
const { message } = useContext(MessageContext);
return <p>{message}</p>;
};
const App = () => (
<MessageProvider>
<Child />
</MessageProvider>
);
export default App;
⚖️ 장단점
- ✅ 장점: 간단하고 props drilling 문제 해결
- ⚠️ 단점: 대규모 앱에서 성능 저하 발생 가능
🎁 Redux
⚡ 개념
- 전역 상태를 중앙 집중화하여 관리하는 예측 가능한 상태 컨테이너.
- 상태를 store에 저장하고 action, reducer를 통해 업데이트.
💡 예시 코드
// store.js
import { createStore } from 'redux';
const initialState = { count: 0 };
const reducer = (state = initialState, action) => {
switch (action.type) {
case 'INCREMENT':
return { ...state, count: state.count + 1 };
default:
return state;
}
};
const store = createStore(reducer);
export default store;
// App.js
import React from 'react';
import { Provider, useSelector, useDispatch } from 'react-redux';
import store from './store';
const Counter = () => {
const count = useSelector((state) => state.count);
const dispatch = useDispatch();
return (
<div>
<p>Count: {count}</p>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
</div>
);
};
const App = () => (
<Provider store={store}>
<Counter />
</Provider>
);
export default App;
⚖️ 장단점
- ✅ 장점: 대규모 앱에서 일관성 있는 상태 관리
- ⚠️ 단점: 설정이 복잡하고 보일러플레이트 코드가 많음
🎛️ Redux Toolkit
🚀 개념
- Redux 설정을 간소화하고 표준화된 상태 관리를 제공하는 툴킷.
- createSlice, configureStore 등으로 구현 단순화.
💡 예시 코드
// counterSlice.js
import { createSlice, configureStore } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { count: 0 },
reducers: {
increment: (state) => {
state.count += 1;
},
},
});
export const { increment } = counterSlice.actions;
const store = configureStore({
reducer: counterSlice.reducer,
});
export default store;
// App.js
import React from 'react';
import { Provider, useSelector, useDispatch } from 'react-redux';
import store, { increment } from './counterSlice';
const Counter = () => {
const count = useSelector((state) => state.count);
const dispatch = useDispatch();
return (
<div>
<p>Count: {count}</p>
<button onClick={() => dispatch(increment())}>Increment</button>
</div>
);
};
const App = () => (
<Provider store={store}>
<Counter />
</Provider>
);
export default App;
⚖️ 장단점
- ✅ 장점: 간결한 코드, Redux 설정 자동화, DevTools 통합 지원
- ⚠️ 단점: Redux의 기본 개념에 대한 이해 필요
⚛️ Props Drilling 실습 노트 ⚛️
1️⃣ Props Drilling 개념- Props Drilling은 데이터를 상위 컴포넌트에서 하위 컴포넌트로 props를 통해 전달하는 방식이야.
- 컴포넌트 트리에서 여러 단계를 거쳐 데이터를 전달해야 할 때 발생해.
- 전역 상태 관리 도구 없이도 데이터 전달이 가능하지만, 컴포넌트가 많아질수록 유지보수가 어려워질 수 있어.
- 중간 컴포넌트가 데이터에 관심이 없음에도 props를 전달해야 하는 상황 발생
- 트리 깊이가 깊어질수록 코드의 가독성 및 유지보수성이 떨어짐
- 불필요한 리렌더링 발생 가능성 증가
2️⃣ Props Drilling 예제
📝 예제 설명// Child.js const Child = ({ message }) => <p>{message}</p>; // Parent.js const Parent = ({ message }) => <Child message={message} />; // App.js const App = () => { const message = "Hello from App!"; return <Parent message={message} />; }; export default App;- App 컴포넌트에서 생성된 message가 Parent를 거쳐 Child에 전달돼.
- Parent는 message를 직접 사용하지 않지만, 전달자 역할만 수행해.
3️⃣ 복잡한 Props Drilling 예시
📝 예제 설명const LevelThree = ({ message }) => <p>{message}</p>; const LevelTwo = ({ message }) => <LevelThree message={message} />; const LevelOne = ({ message }) => <LevelTwo message={message} />; const App = () => { const message = "Hello from the top!"; return <LevelOne message={message} />; }; export default App;- App에서 생성된 message가 LevelOne → LevelTwo → LevelThree까지 전달돼.
- 트리의 깊이가 깊어질수록 props 전달이 반복되어 코드의 복잡성이 증가해.
4️⃣ Props Drilling의 문제점- 중간 컴포넌트가 불필요한 props를 수신하고 전달해야 함
- 유지보수 어려움: 컴포넌트가 많아질수록 props 전달 경로를 따라가기 힘듦
- 성능 문제: 중간 컴포넌트가 필요하지 않은 상태 변경에도 리렌더링됨
- Context API 사용
- 전역 상태 관리 도구 사용 (Redux, Zustand 등)
- 컴포넌트 재구조화하여 필요한 데이터만 전달
5️⃣ Props Drilling 문제 해결: Context API 사용 예시
📝 예제 설명import React, { createContext, useContext, useState } from 'react'; const MessageContext = createContext(); const MessageProvider = ({ children }) => { const [message] = useState("Hello from Context!"); return ( <MessageContext.Provider value={message}> {children} </MessageContext.Provider> ); }; const LevelThree = () => { const message = useContext(MessageContext); return <p>{message}</p>; }; const LevelTwo = () => <LevelThree />; const LevelOne = () => <LevelTwo />; const App = () => ( <MessageProvider> <LevelOne /> </MessageProvider> ); export default App;- useContext 훅을 사용하여 중간 컴포넌트를 거치지 않고 상태를 직접 접근할 수 있어.
- props drilling 문제 해결 및 리렌더링 최적화 가능.
6️⃣ Props Drilling 요약 정리🔥 항목 🌟 설명 💡 해결 방안🎨 개념 상위에서 하위로 props를 통해 데이터 전달 Context API, 전역 상태 관리 도구 ⚡ 문제점 중간 컴포넌트의 불필요한 props 전달, 리렌더링 문제 컴포넌트 재구조화, 상태 분리 🚀 해결 방법 Context API로 전역 상태 관리, Redux 활용 효율적인 상태 전달과 유지보수성 향상
✨💖 Props Drilling 개념과 실습을 통해 효율적인 데이터 전달 구조를 만들어
1️⃣ Props Drilling 개념- Props Drilling은 데이터를 상위 컴포넌트에서 하위 컴포넌트로 props를 통해 전달하는 방식이야.
- 컴포넌트 트리에서 여러 단계를 거쳐 데이터를 전달해야 할 때 발생해.
- 전역 상태 관리 도구 없이도 데이터 전달이 가능하지만, 컴포넌트가 많아질수록 유지보수가 어려워질 수 있어.
- 중간 컴포넌트가 데이터에 관심이 없음에도 props를 전달해야 하는 상황 발생
- 트리 깊이가 깊어질수록 코드의 가독성 및 유지보수성이 떨어짐
- 불필요한 리렌더링 발생 가능성 증가
2️⃣ Props Drilling 예제
📝 예제 설명// Child.js const Child = ({ message }) => <p>{message}</p>; // Parent.js const Parent = ({ message }) => <Child message={message} />; // App.js const App = () => { const message = "Hello from App!"; return <Parent message={message} />; }; export default App;- App 컴포넌트에서 생성된 message가 Parent를 거쳐 Child에 전달돼.
- Parent는 message를 직접 사용하지 않지만, 전달자 역할만 수행해.
3️⃣ 복잡한 Props Drilling 예시
📝 예제 설명const LevelThree = ({ message }) => <p>{message}</p>; const LevelTwo = ({ message }) => <LevelThree message={message} />; const LevelOne = ({ message }) => <LevelTwo message={message} />; const App = () => { const message = "Hello from the top!"; return <LevelOne message={message} />; }; export default App;- App에서 생성된 message가 LevelOne → LevelTwo → LevelThree까지 전달돼.
- 트리의 깊이가 깊어질수록 props 전달이 반복되어 코드의 복잡성이 증가해.
4️⃣ Props Drilling의 문제점- 중간 컴포넌트가 불필요한 props를 수신하고 전달해야 함
- 유지보수 어려움: 컴포넌트가 많아질수록 props 전달 경로를 따라가기 힘듦
- 성능 문제: 중간 컴포넌트가 필요하지 않은 상태 변경에도 리렌더링됨
- Context API 사용
- 전역 상태 관리 도구 사용 (Redux, Zustand 등)
- 컴포넌트 재구조화하여 필요한 데이터만 전달
5️⃣ Props Drilling 문제 해결: Context API 사용 예시
📝 예제 설명import React, { createContext, useContext, useState } from 'react'; const MessageContext = createContext(); const MessageProvider = ({ children }) => { const [message] = useState("Hello from Context!"); return ( <MessageContext.Provider value={message}> {children} </MessageContext.Provider> ); }; const LevelThree = () => { const message = useContext(MessageContext); return <p>{message}</p>; }; const LevelTwo = () => <LevelThree />; const LevelOne = () => <LevelTwo />; const App = () => ( <MessageProvider> <LevelOne /> </MessageProvider> ); export default App;- useContext 훅을 사용하여 중간 컴포넌트를 거치지 않고 상태를 직접 접근할 수 있어.
- props drilling 문제 해결 및 리렌더링 최적화 가능.
6️⃣ Props Drilling 요약 정리🔥 항목 🌟 설명 💡 해결 방안🎨 개념 상위에서 하위로 props를 통해 데이터 전달 Context API, 전역 상태 관리 도구 ⚡ 문제점 중간 컴포넌트의 불필요한 props 전달, 리렌더링 문제 컴포넌트 재구조화, 상태 분리 🚀 해결 방법 Context API로 전역 상태 관리, Redux 활용 효율적인 상태 전달과 유지보수성 향상 - 🌟 Context API 사용 코드
- ⚠️ 주요 문제점
- 💡 컴포넌트 트리가 깊을 때
- 💡 기본 예시 코드
- 🌿 Props Drilling 실습 노트 🌿
- 🌟 Context API 사용 코드
- ⚠️ 주요 문제점
- 💡 컴포넌트 트리가 깊을 때
- 💡 기본 예시 코드
🌐 전역 상태 관리: Context API 노트 🌐
🌿 Context API란?
- React 내장 전역 상태관리 도구이고 ****별도 설치 없이 사용 가능하다. 그러나 큰 상태 변경 시 리렌더링 발생한다.
1️⃣ Context API 개념
-
- Context API는 React 내장 전역 상태 관리 도구로, 컴포넌트 트리의 깊이에 관계없이 데이터를 전달할 수 있다.
- props drilling 문제를 해결하여 컴포넌트 간 데이터 공유를 간편하게 만들어준다.
- 주요 구성 요소:
- createContext: 컨텍스트 생성
- Provider: 하위 컴포넌트에 데이터 전달
- useContext: 하위 컴포넌트에서 데이터 접근
2️⃣ Context API 사용 시기
-
- ⚡ props drilling 문제가 발생할 때
- 🌈 전역 테마 설정 (예: 다크 모드, 컬러 테마)
- 🔑 인증 상태 관리 (로그인/로그아웃 상태)
- 🌐 다국어 지원(Localization)
- 📦 글로벌 데이터 공유 (사용자 정보, 장바구니 데이터 등)
3️⃣ Context API 기본 사용법
-
- createContext로 전역상태 만들기
- Provider로 전역상태 연결하기
- useContext로 전역상태 가져오기
💡 간단한 예시 코드
-
import React, { createContext, useContext, useState } from 'react'; // 1️⃣ Context 생성 const UserContext = createContext(); // 2️⃣ Provider 컴포넌트 생성 const UserProvider = ({ children }) => { const [user, setUser] = useState({ name: 'Alice', age: 25 }); return ( <UserContext.Provider value={{ user, setUser }}> {children} </UserContext.Provider> ); }; // 3️⃣ Context 사용 const Profile = () => { const { user } = useContext(UserContext); return ( <div> <h2>👤 {user.name}</h2> <p>🎂 {user.age} years old</p> </div> ); }; // 4️⃣ App에서 Provider로 감싸기 const App = () => ( <UserProvider> <Profile /> </UserProvider> ); export default App;
📝 예제 설명
-
- UserContext를 생성하여 사용자 정보를 전역으로 관리.
- Profile 컴포넌트에서 useContext를 사용해 중간 컴포넌트를 거치지 않고 데이터를 직접 접근.
4️⃣ Context API 고급 사용법
🌟 useReducer와 함께 사용하기
-
- 복잡한 상태 로직을 관리할 때 useReducer와 함께 사용하면 좋다.
💡 예시 코드
-
import React, { createContext, useReducer, useContext } from 'react'; const CounterContext = createContext(); const counterReducer = (state, action) => { switch (action.type) { case 'INCREMENT': return { count: state.count + 1 }; case 'DECREMENT': return { count: state.count - 1 }; default: return state; } }; const CounterProvider = ({ children }) => { const [state, dispatch] = useReducer(counterReducer, { count: 0 }); return ( <CounterContext.Provider value={{ state, dispatch }}> {children} </CounterContext.Provider> ); }; const Counter = () => { const { state, dispatch } = useContext(CounterContext); return ( <div> <p>🔢 Count: {state.count}</p> <button onClick={() => dispatch({ type: 'INCREMENT' })}>➕ Increment</button> <button onClick={() => dispatch({ type: 'DECREMENT' })}>➖ Decrement</button> </div> ); }; const App = () => ( <CounterProvider> <Counter /> </CounterProvider> ); export default App;
📝 예제 설명
-
- useReducer와 함께 사용하여 상태 관리 로직을 더 깔끔하고 예측 가능하게 관리.
5️⃣ Context API의 장단점
🌟 장점
-
- ✅ props drilling 문제 해결
- ✅ 간단한 설정과 사용 (별도의 라이브러리 필요 없음)
- ✅ 컴포넌트 트리 전역 상태 공유
⚡ 단점
-
- ⚠️ 대규모 앱에서 성능 문제 발생 가능 (모든 하위 컴포넌트가 리렌더링됨)
- ⚠️ 상태가 커질수록 복잡성 증가 (Redux 같은 도구가 더 적합할 수 있음)
6️⃣ Context API 요약 정리
- 🔥 항목 🌟 설명 💡 예시
🎨 핵심 기능 컴포넌트 트리 내 전역 상태 제공 테마 설정, 다국어 지원 ⚡ 사용 시기 props drilling 문제 발생, 간단한 전역 상태 필요할 때 로그인 상태, 사용자 정보 공유 🚀 고급 사용법 useReducer와 결합하여 복잡한 상태 로직 처리 카운터 기능, 폼 데이터 관리 💎 성능 최적화 상태 분리, React.memo 사용하여 불필요한 렌더링 방지 대규모 프로젝트에서의 최적화 작업 💎 전역 상태 관리: Redux 노트 💎
1️⃣ Redux 개념- Redux는 예측 가능한 상태 관리를 위한 자바스크립트 라이브러리로, React 애플리케이션의 전역 상태를 일관성 있게 관리할 수 있어.
- 모든 상태는 하나의 store에서 관리되며, action과 reducer를 통해 상태 변경이 이루어져.
- React 외에도 Angular, Vue 등 다양한 프레임워크와 호환 가능해.
- 🏪 Store: 상태가 저장되는 공간
- 🎬 Action: 상태에 일어날 변화를 설명하는 객체
- 🛠️ Reducer: 액션에 따라 상태를 업데이트하는 함수
- 🔗 Dispatch: 액션을 리듀서에 전달하는 함수
2️⃣ Redux 사용 시기- ⚡ 복잡한 상태 관리가 필요한 경우 (대규모 애플리케이션)
- 🔗 다양한 컴포넌트 간의 상태 공유가 필요할 때
- 🕹️ 일관성 있는 상태 업데이트가 중요할 때
- 📦 디버깅 및 상태 추적이 필요한 프로젝트
3️⃣ Redux 기본 사용법🏪 1. Store 생성🎬 2. 컴포넌트에서 상태 사용📝 예제 설명- store를 Provider로 감싸 전역 상태를 제공.
- useSelector로 상태 접근, useDispatch로 액션 전달.
4️⃣ Redux의 장단점- ✅ 일관성 있는 상태 관리: 단일 store를 통해 상태 추적 용이
- ✅ 디버깅 편의성: Redux DevTools 지원
- ✅ 예측 가능한 상태 흐름: 액션과 리듀서를 통한 명확한 상태 변경
- ⚠️ 보일러플레이트 코드: 설정과 구성에 많은 코드 필요
- ⚠️ 학습 곡선: 액션, 리듀서, 스토어 개념 이해 필요
- ⚠️ 간단한 프로젝트에 과한 설정
5️⃣ Redux 고급 사용법- 비동기 작업을 처리하기 위해 redux-thunk와 같은 미들웨어를 사용.
// App.js import React, { useEffect } from 'react'; import { Provider, useSelector, useDispatch } from 'react-redux'; import { store, fetchData } from './store'; const DataDisplay = () => { const data = useSelector((state) => state.data); const dispatch = useDispatch(); useEffect(() => { dispatch(fetchData()); }, [dispatch]); return ( <div> <h2>📦 Data from API:</h2> <pre>{JSON.stringify(data, null, 2)}</pre> </div> ); }; const App = () => ( <Provider store={store}> <DataDisplay /> </Provider> ); export default App;
6️⃣ Redux 요약 정리🎨 핵심 기능 단일 store로 전역 상태 관리 카운터 앱, 사용자 인증 관리 ⚡ 사용 시기 대규모 앱, 상태 공유 및 복잡한 상태 관리 필요 시 전자상거래 사이트, 대시보드 🚀 미들웨어 사용 redux-thunk를 통한 비동기 상태 처리 API 데이터 페칭, 비동기 작업 처리 💎 성능 최적화 리렌더링 최적화 및 불필요한 상태 업데이트 방지 대규모 프로젝트 최적화 🚀 전역 상태 관리: Redux Toolkit 노트 🚀
1️⃣ Redux Toolkit 개념
- Redux Toolkit은 Redux의 공식 표준 툴킷으로, 복잡하고 반복적인 Redux 설정을 간소화해.
- 기본적인 Redux 기능인 store, reducer, action을 간결하게 생성할 수 있어.
- Redux DevTools와 기본 통합되어 디버깅이 용이해.
- ⚡ configureStore: 간편한 스토어 설정
- 🧩 createSlice: action과 reducer를 자동 생성
- 🌐 createAsyncThunk: 비동기 작업 처리
- 🔧 createReducer: 간결한 리듀서 생성
2️⃣ Redux Toolkit 사용 시기- 🏃 빠른 Redux 설정이 필요한 경우
- 💡 보일러플레이트 코드를 줄이고 싶을 때
- 🚀 비동기 작업이 자주 발생하는 프로젝트에서
- 🏗️ 대규모 상태 관리가 필요한 복잡한 애플리케이션
3️⃣ Redux Toolkit 기본 사용법🏪 1. Slice 생성 및 스토어 설정🎬 2. 컴포넌트에서 상태 사용📝 예제 설명- createSlice를 사용하여 reducer와 action을 동시에 생성.
- configureStore로 간단하게 store를 설정.
- useSelector, useDispatch로 상태 접근 및 업데이트.
4️⃣ Redux Toolkit 고급 사용법💡 비동기 예제 코드
📝 예제 설명// App.js import React, { useEffect } from 'react'; import { Provider, useSelector, useDispatch } from 'react-redux'; import store, { fetchUser } from './userSlice'; const UserProfile = () => { const { user, status } = useSelector((state) => state); const dispatch = useDispatch(); useEffect(() => { dispatch(fetchUser()); }, [dispatch]); return ( <div> <h2>👤 User Profile</h2> {status === 'loading' ? <p>Loading...</p> : <pre>{JSON.stringify(user, null, 2)}</pre>} </div> ); }; const App = () => ( <Provider store={store}> <UserProfile /> </Provider> ); export default App;- createAsyncThunk를 사용해 비동기 API 호출 처리.
- extraReducers로 비동기 상태(loading, succeeded, failed) 관리.
5️⃣ Redux Toolkit의 장단점- ✅ 간결한 코드: action과 reducer를 한 번에 생성
- ✅ 비동기 작업 내장 지원: createAsyncThunk로 간단한 비동기 처리
- ✅ DevTools 통합: 상태 추적 및 디버깅 용이
- ✅ 권장 표준 방식: Redux 팀이 공식적으로 권장
- ⚠️ 기본 Redux 개념 이해 필요
- ⚠️ 간단한 앱에는 과도할 수 있음
6️⃣ Redux Toolkit 요약 정리🔥🎨 핵심 기능 createSlice, configureStore로 간단한 상태 관리 카운터 앱, 사용자 인증 관리 ⚡ 사용 시기 빠른 설정 및 간결한 Redux 사용이 필요할 때 대시보드, 전자상거래 앱 🚀 비동기 작업 처리 createAsyncThunk를 사용한 비동기 상태 처리 API 호출, 데이터 페칭 💎 성능 최적화 DevTools와의 통합, 상태 업데이트 최적화 대규모 애플리케이션 최적화