๐จ 11. Context API์ ํ๊ณ์ ๋ ๋ ์ํฐํด ํ๊ดด
๐ ๊ฐ์
Context API๋ฅผ ์ํ ๊ด๋ฆฌ ํด๋ก ์คํดํ ๋ ํฐ์ง๋ ๋ถํ์ํ ์ ์ญ ๋ ๋๋ง ์ฐธ์ฌ๋ฅผ ๋ง๊ณ ์ฐํํ๋ ํ์ ๋ถ๋ฆฌ ๊ธฐ๋ฒ์ ๋ค๋ฃน๋๋ค.
๐ฏ ์ด ์น์ ์ ์ฝ๊ณ ๋๋ฉด:
- Context API๋ฅผ ๋ฆฌ๋์ค(Redux)์ฒ๋ผ ์ํ ๊ด๋ฆฌ ๋๊ตฌ๋ผ๊ณ ๋ถ๋ฅผ ์ ์๋ ๊ทผ๋ณธ์ ์ธ ์์ง ํ๊ณ๋ฅผ ์ค๋ช ํ ์ ์๋ค.
- Context ์์ ๊ฐ์ด ํ๋ ๋ฐ๋์์ ๋ ํ์ ํธ๋ฆฌ๊ฐ ์ ๋ถ ๋ชจ์กฐ๋ฆฌ ๋ ๋๋ง๋๋ ํญํฌ์(Waterfall) ์ฐธ์ฌ๋ฅผ ๋ชฉ๊ฒฉํ๋ค.
- ๊ฐ(Value)๊ณผ ํ๋(Action)์ ์๊ฒ ์ชผ๊ฐ๋ Context ์ชผ๊ฐ๊ธฐ(Splitting) ๋ฐฉ์ด์ ์ ๋ค๋ฃฌ๋ค.
๐ ๋ชฉ์ฐจ
- ๐ค ์ ์์์ผ ํ๋๊ฐ: Context๋ ๋ฌด์ฃ๋ค, ๋น์ ์ด ๋จ์ฉํ์ ๋ฟ
- ๐๏ธ ๋น์ ๋ก ๋จผ์ ์ดํดํ๊ธฐ
- ๐งฉ ๋ฐฉ์ฌ๋ฅ ๋ถ๋ฆฌ ํ๊ฒฉ์ : ์ฌ๋ฌ ๊ฐ์ ํฌํ๋ก ์ชผ๊ฐ๊ธฐ (Splitting)
- ๐ฅ ์๋ฌ ํด๊ฒฐ ์นดํ๋ก๊ทธ
๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
โฑ๏ธ ์์ ์ฝ๊ธฐ ์๊ฐ: 10๋ถ / ํต์ฌ ํํธ: 6๋ถ
๐บ๏ธ ์ด ๋ฌธ์์ ๋ฐฐ๊ฒฝ ์ธ๊ณ๊ด: '์์๋ค ์ปค๋ฎค๋ํฐ'
- ์์ฒ (์ ์
): "Props ๋๊ธฐ๋ ๊ฑฐ ๋๋ฌด ๊ท์ฐฎ์์! ์ฐ๋ฆฌ ์ปค๋ฎค๋ํฐ์ ํ
๋ง(๋คํฌ๋ชจ๋), ๋ก๊ทธ์ธํ ์ ์ ์ ๋ณด, ์ฌ์ง์ด ์
๋ ฅ์ฐฝ ์๋์์ฑ ํค์๋๊น์ง ์น ๋ค ๊ฑฐ๋ํ ํ๋์ ๋ฑ๋ฑํ
Context์ ์ฑ์ฌ๋ฃ๊ณ ์ ์ญ์์ ๋ฝ์ ์ธ๊ฒ์!" - ์ํธ(๋ฆฌ๋): "์์ฒ ๋... Context๋ ์ณ๋ค๋ง ๋ด๋ ์ฃ์ ์ธ '๋ ๋๋ง ๋ฐฉ์ฌ๋ฅ'์ ๋ด๋ฟ๋ ํญํ ๋ฐ๊ตฌ๋์ ๋๋ค. ๊ทธ๊ฑธ ํ๋๋ก ๋ญ์ณ๋๋ค๋จ."
๐ค ์ ์์์ผ ํ๋๊ฐ: Context๋ ๋ฌด์ฃ๋ค, ๋น์ ์ด ๋จ์ฉํ์ ๋ฟ
๋ง์ ์ฌ๋๋ค์ด Zustand, Recoil, Redux ๊ฐ์ ์ธ๋ถ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐ๊ธฐ ์ซ์ด์, ๋ฆฌ์กํธ ์์ ๋ด์ฅ๋ Context API๋ฅผ '์ ์ญ ์ํ ๊ด๋ฆฌ ๋๊ตฌ'๋ผ๊ณ ๋งน์ ํ๋ ์์ฒญ๋ ์ฐฉ๊ฐ์ ํฉ๋๋ค.
Context ์์ฒด๋ ์ํ(State)๊ฐ ์๋๋ฉฐ ๊ด๋ฆฌ(Manage)ํ์ง๋ ์์ต๋๋ค! ๊ทธ์ ๋ถ๋ชจ์ ์ํ๋ฅผ ์ ๋ฐ๋ฐ๋ฅ ์ฌํด๋ก **ํฌํ์ ์ด์ด ์๊ฐ์ด๋(Dependency Injection, ์์กด์ฑ ์ฃผ์ )**์์ผ ์ค ๋ฟ์ธ ํ์ดํ๋ผ์ธ์ ๋ถ๊ณผํ์ฃ .
๐ค ์ ๊น, ๋จผ์ ์๊ฐํด๋ด
๊ฑฐ๋ํ ๋ฐ๊ตฌ๋(Context) ํ๋์ ์ ์ ์ ๋ณด(name)์ ๋คํฌ๋ชจ๋(isDark)๋ฅผ ๋ค ๋ฃ์์ด. ๋ฒํผ์ ๋๋ฌ ๋ฐคํ๋์ฒ๋ผ ์์ ๋คํฌ๋ชจ๋๋ฅผ ์ผฐ์ง. ๊ทผ๋ฐ ์ ์ ์ ์ ๋ณด๋ง ์กฐ์ฉํ ๋์์ฃผ๋ ์ ๋๋ค ์๋ฐํ ์ปดํฌ๋ํธ๊น์ง ๋ฉ๋ฌ์ ๋ชธ์ด(๋ฆฌ๋ ๋๋ง)์ ์์๊น?
// โ ์์ฒ ์ด์ ํญํ ๋ฐ๊ตฌ๋ (Context ์ค๋จ์ฉ)
const AppContext = createContext();
function AppProvider({ children }) {
const [theme, setTheme] = useState("light");
const [user, setUser] = useState({ name: "์์ฒ " });
// ๐ฃ ๋ฑ๋ฑํ ๊ฐ์ฒด(๋ฐ๊ตฌ๋) ํ๋ ๋ง๋ค์ด์ ํต์งธ๋ก ํฌํ!
const value = { theme, setTheme, user, setUser };
return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
}
// ------------------------------
// ์์ฃผ ์กฐ๊ทธ๋ง ์ปดํฌ๋ํธ A
function Avatar() {
// ๋๋ 'user'๋ง ํ์ํ๋ฐ ์ด์ฉ ์ ์์ด ๊ฑฐ๋ ๋ฐ๊ตฌ๋๋ฅผ ๋ค์ ธ ๊บผ๋ธ๋ค
const { user } = useContext(AppContext);
console.log("์๋ฐํ ๋ฆฌ๋ ๋๋ง๋จ!"); // ๐จ ํ
๋ง ๋ฒํผ ๋๋ฅด๋ฉด ๋๋ ๋น๋ช
์ง๋ฆ!
return <div>{user.name}</div>;
}๊ฒฐ๊ณผ: ์ ์ ๊ฐ setTheme("dark")๋ฅผ ๋๋ฌ ๋คํฌ๋ชจ๋๋ฅผ ์ ํํ๋ฉด, ์ ๋ฉ๋ฆฌ ๊ตฌ์์ ์ฒ๋ฐํ์ ๋ก๊ทธ์ธ ์ด๋ฆ๋งํฌ ๋์ฐ๊ณ ๊ฐ๋งํ ์๋ Avatar ์ปดํฌ๋ํธ๊ฐ ๊ฐ์ ๋ก ๋ฆฌ๋ ๋๋ง๋๋ฉฐ ํผ๊ฒฉ ๋ฐ๋ฏธ์ง๋ฅผ ์
์ต๋๋ค.
๐๏ธ ๋น์ ๋ก ๋จผ์ ์ดํดํ๊ธฐ
๐ง 5์ด์๊ฒ ์ค๋ช ํ๋ค๋ฉด?
Context๋ ๊ฑฐ๋ํ ์คํผ์ปค๊ฐ ๋ฌ๋ฆฐ ๋ง์ํ๊ด ๋๋ค ๋ฐฉ์ก๊ตญ์ด์ผ.- ๋๋ค ๋ฐฉ์ก ์ฃผํ์(
useContext)๋ฅผ ๊ฝ๊ณ ๋ผ๋์ค๋ฅผ ๋ฃ๋ ์ง๋ค์ด 100๊ฐ๊ตฌ๊ฐ ์์ด. (์๋ฐํ ์ง, ํ๋กํ ์ง, ํ ๋ง ์ธํ ์ง ๋ฑ...)- ์์ฒ (์ด์ฅ๋)์ด ๋ง์ดํฌ(Context Value)๋ฅผ ๋ค๊ณ ๋ฐฉ์ก์ ์ผฐ์ด. "์์! ์ค๋๋ถํฐ ๋คํฌ๋ชจ๋ ์ค์!"
- ์๋ฐํ ์ปดํฌ๋ํธ๋ ์ฌ์ค ๋คํฌ๋ชจ๋ ๋ฐ์ 1๋ ๊ด์ฌ ์์ด. ์ ์ ์์ด๋๋ง ๋ค์ผ๋ ค๊ณ ๋ผ๋์ค๋ฅผ ์ผ ๋์ด๊ฑฐ๋ . (๋
user์ ๋ณด๋ง ๋บ์)- ํ์ง๋ง ๋ฆฌ์กํธ๋ ์๋น๊ฐ ์์ง. ๋ฐฉ์ก๊ตญ ๋ง์ดํฌ์์ ์ด์จ๋ ์ด๋ค ์๋ฆฌ๋ ๋จ ํ๋๋ผ๋ ์ก์ถ(Context Value ๊ฐ์ฒด์ ๊ป๋ฐ๊ธฐ ๋ณ๋)๋๋ฉด, ์ฃผํ์๋ฅผ ๊ตฌ๋ ์ค์ธ 100๊ฐ๊ตฌ๋ฅผ ๋ชจ์กฐ๋ฆฌ ๋ค ๋ง์น๋ก ๋๋ค๊ฒจ ๊นจ์ฐ๊ณ ๊ฐ์ ๋ก ์ฌ์กฐ๋ฆฝ(๋ฆฌ๋ ๋๋ง) ์์ผ๋ฒ๋ ค. "๋ฐฉ์ก ๋์์ผ๋ ๋ค ๋ค์ ์ธํ ํด!" ์ด๊ฒ ์ด๋ฅธ๋ฐ ๋ ๋๋ง ๋ฐฉ์ฌ๋ฅ ์ํฐํด์ด์ผ.
โ
ํต์ฌ ์๋ฆฌ:
09. ์ต์ ํ์ ๊ฑฐ์ง๋ง์์ ๊ฐ์ฒด์ ์ฐธ์กฐ๊ฐ ๋ฌ๋ผ์ง๋ฉด ๋ฆฌ์กํธ๊ฐ ๋ฐ์ํ๋ค๊ณ ๋ฐฐ์ ์ฃ ? AppProvider์์ ๋ ๋๋ง์ด ๋๋ฉด, ์ ๊ธฐ ๊ตฌ๋ฉ(value)์ ๊ฝํ { theme, user... } ๋ฌถ์ ๋ฐ๊ตฌ๋ ์ ์ฒด์ ํ ๋ฉ๋ชจ๋ฆฌ ๊ฐ์ฒด ์ฃผ์์ง๊ฐ ์๊ฑธ๋ก ๊ฐ์ ์น์์ง๋๋ค.
useContext๋ฅผ ์ ์ธํ ๋ชจ๋ ํ์ ์ปดํฌ๋ํธ๋ ์์ ์ด ๊บผ๋ด ์ด ๊ฐ์ด ๋ญ๋ ์ง ๊ฐ์, "์! ์ ๊ณต์ฅ์ ํฌ์ฅ์ง(value ์ฃผ์๊ฐ)๊ฐ ์๋ก ๋ฐ๋์๊ตฐ! ๋ด๋ถ๋ ์ ๋ด๋ ์๋ก ๋ ๋๋งํด์ผ์ง!" ๋ผ๋ฉฐ ๋ฌด์กฐ๊ฑด ๋ ๋๋ง ์ค๋
์ท์ ๋๋ ค๋ฒ๋ฆฌ๋ ๋ฉ์ฒญํ ์น๋ช
์ ๋จ์ ์ ๊ฐ์ง๋๋ค. (์ด๊ฒ Redux ๊ฐ์ ์ธ๋ถ ์ํ ํด์ด ๊ฐ๋ณ ์ต์ ํ๋ฅผ ๊ตฌ์ฌํ๋ ๊ฒ๊ณผ Context์ ๊ฐ์ฅ ํฐ ์ฐจ์ด์
๋๋ค.)
๐งฉ ๋ฐฉ์ฌ๋ฅ ๋ถ๋ฆฌ ํ๊ฒฉ์ : ์ฌ๋ฌ ๊ฐ์ ํฌํ๋ก ์ชผ๊ฐ๊ธฐ (Splitting)
์ฐ๋ฆฌ๊ฐ ์ด ๋ฐฉ์ฌ๋ฅ ์ง์ฅ์์ ํ์ถํ๋ ๊ฐ์ฅ ๊ณ ์ํ ์๋์ด์ ๋ฐฉ๋ฒ์ ๋ฐฉ์ฌ๋ฅ ํฌํ ๋ฐ๊ตฌ๋๋ฅผ '๊ธฐ๋ฅ ๋จ์', ๋๋ '์ํ vs ์ก์ ๋จ์'๋ก ์์ฃผ ์๊ฒ ์ฐข์ด ๋๋ ๊ฑฐ์ผ.
โ ์ํธ์ ๋ฆฌํฉํ ๋ง: ๋ฐ๊ตฌ๋ ๊ฐ์ ๋ถํ (Splitting Context)
์ ์ ๋ฐ๊ตฌ๋๋ ํ ๋ง ๋ฐ๊ตฌ๋๋ฅผ ์ฐข๋ ๊ฑด ๋น์ฐํ ๊ฑฐ๊ณ , ๋์๊ฐ์ 5๋ ์ฐจ๋ค์ ์ฑ๋ฅ์ ํ๊ณ๊น์ง ๋์ด์ฌ๋ฆฌ๊ธฐ ์ํด "๋ช ์ฌ(๊ฐ)" ๊ณผ "๋์ฌ(๋ฐ๊พธ๋ ํจ์)" ๋ฐ๊ตฌ๋์กฐ์ฐจ ๊ฒฉ๋ฆฌ์์ผ ๋ถ๋จํด ๋ฒ๋ฆฌ์ง.
// โ
์ฐ์ํ ๊ณ ์ฑ๋ฅ ์ํคํ
์ฒ (Pro Approach)
// 1. ๊ฐ(Value) ์ ์ฉ ํฌํ
const ThemeStateContext = createContext();
// 2. ํ๋(Action/Dispatch) ์ ์ฉ ํฌํ
const ThemeDispatchContext = createContext();
function ThemeProvider({ children }) {
const [theme, setTheme] = useState("light");
// ์ด ๋ณ๊ฒฝ ๋ฒํผ ํจ์๋ค์ ์๋ฌด๋ฆฌ ๋ ๋๋งํด๋ ์์ํ ๋๊ฐ์ ์ฃผ์(ํฌ์ฅ์ง)์ฌ์ผ ํจ!
const dispatch = useMemo(() => ({
toggleToDark: () => setTheme("dark"),
toggleToLight: () => setTheme("light")
}), []);
return (
<ThemeStateContext.Provider value={theme}>
{/* ๐ฏ ํ๋ ํฌํ ์๋์ ๊ฐ ํฌํ์ ์ค์ฒฉ ์ค๊ณ */}
<ThemeDispatchContext.Provider value={dispatch}>
{children}
</ThemeDispatchContext.Provider>
</ThemeStateContext.Provider>
);
}
// ------------------------------
// ์ด๋ค ์ปดํฌ๋ํธ B (๋คํฌ๋ชจ๋ ๋ณ๊ฒฝ ๋ฒํผ)
function DarkModeToggleButton() {
// ๐ฏ ์ด ์ปดํฌ๋ํธ๋ ์ค์ง '๋๋ฅด๋ ๋์'๋ง ํ์ํ๋ค.
// '์ํ(ํ
๋ง ๊ฐ)'๋ฅผ ๋ณด์ง ์์ผ๋ฏ๋ก StateContext๋ฅผ ์์ (useContext)ํ์ง ์์!
const { toggleToDark } = useContext(ThemeDispatchContext);
// ๐ญ ์๋ฆ๋๋ ๋ง๋ฒ: ๋ฒํผ์ ๋๋ฌ ํ
๋ง๊ฐ ์์ ๋ฐ๊ปด๋,
// ์ด ๋ฒํผ ์ปดํฌ๋ํธ ์์ ์ ์ ๋ ๋ฆฌ๋ ๋๋ง ๋ฐ๋ฏธ์ง๋ฅผ ๋ง์ง ์๊ณ ํ์จํ๋ค!
// ์ํ ํฌํ ๊ตฌ๋
์ ํฌ๊ธฐํ๊ณ ์ก์
ํฌํ๋ง ๊บผ๋ด ์ผ๊ธฐ ๋๋ฌธ.
return <button onClick={toggleToDark}>์ด๋ ์ด์ฌ ๋ด๊ฒ ์ค๋ผ</button>;
}์ด ์๋์ ์ค๊ณ(Context Splitting)๋ฅผ ๋ณด์ญ์์ค.
ํ
๋ง ๊ฐ์ ๊ตฌ๋
(์์ )ํ๋ ํ์ ์ปดํฌ๋ํธ๋ค์ ๋น์ฐํ ์์ด ๋ฐ๋๋ฉด ์ฌ๊ฐ์กฐ๋์ด์ผ ํ๋๊น ๋ฆฌ๋ ๋๋ง ๋ฐ๋ฏธ์ง๋ฅผ ์จ๋ชธ์ผ๋ก ๋ง์ต๋๋ค.
ํ์ง๋ง! ๋จ์ํ ํ
๋ง๋ฅผ ๋ฐ๊พธ๋ '์ค์์น' ์ญํ ๋ง ํ๋, ๊ตณ์ด ์๊ธฐ๊ฐ ์ฌ๋ ๋๋ง๋๋ฉฐ ๊น๋นก๊ฑฐ๋ฆด ํ์๊ฐ ์๋ ์ปดํฌ๋ํธ๋ค์ ์์ ํ ๊ฒฉ๋ฆฌ๋ DispatchContext๋ง ์กฐ์ฉํ ๊บผ๋ด ์๋๋ค. ์ํ ๋ณํ ๋ฐฉ์ฌ๋ฅ ํ๋์ ์๋ฒฝํ๊ฒ ํผํด ๊ฐ๋ ์ต๊ณ ์ ์ปดํฌ๋ํธ ์์กด๊ธฐ๋ฒ์ด์ฃ .
๐ฅ ์๋ฌ ํด๊ฒฐ ์นดํ๋ก๊ทธ
โ ๋งค๋ฒ value์ ์ฉ ๊ฐ์ฒด๋ฅผ ์ค์
๋ฃ๋ ์ต์
์ ํ์
์ํฉ:
const DataContext = createContext(null);
function Layout() {
const [info, setInfo] = useState('data');
const size = useWindowSize(); // ํ
(์ฐฝ ํฌ๊ธฐ ๊ฐ์ง)
// ๐ฅ Layout์ด ๋ ๋๋ง(์ฐฝ ํฌ๊ธฐ ์ถ์ ๋ฑ) ๋ ๋๋ง๋ค ์ด { ์์ } ๊ดด๋ฌผ ๊ฐ์ ๊ฐ์ฒด ํฌ์ฅ์ง๊ฐ ์๋ก ์์ฑ๋์ด ์ดํฌ๋๋ค.
return (
<DataContext.Provider value={{ info, setInfo }}>
<PageArea />
</DataContext.Provider>
)
}์์ธ: useWindowSize ๋๋ฌธ์ ๋ธ๋ผ์ฐ์ ํ๋ฉด์ด 1px๋ผ๋ ์ข์์ง๊ฑฐ๋ ์กฐ์ ์ด๋ฒคํธ๊ฐ ์ผ์ด๋ ๋๋ง๋ค Layout ๊ป๋ฐ๊ธฐ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง์ ๋๋๋ค. ๊ทธ๋ด ๋๋ง๋ค ์ value={{ info, setInfo }} ๊ตฌ๋ฌธ์ด ๋ค์ด๋ฐํ๋ฉด์ ์์ ํ ์๋ก์ด ๋ฉ๋ชจ๋ฆฌ ๋๋ฏธ ๋ถ์ด๋นต ๊ป์ง ๊ฐ์ฒด 100๋ง ๊ฐ๊ฐ ๋ณต์ฌ ๋ฐ์ฌ๋ฉ๋๋ค. info๋ ํธ๋ํ๋ ๋ฐ๋์ง ์์์์๋, DataContext๋ฅผ ์์ ํ๋ ๋ชจ๋ ํ์ ํธ๋ฆฌ ๋ฐฑ๋ง ๋๊ตฐ์ด ์ธ๋ฐ์์ด ํ์ด๋นํฉ๋๋ค.
ํด๊ฒฐ์ฑ
:
Context๋ฅผ ํ๋๋ก ๊ธฐ์ ์ฐ์ง ๋ง๊ณ , ์ฐข์ด๋ด๋ ์ ๋ฐฉ๋ฒ์ด ์ต์ ์
๋๋ค. ๋ง์ฝ ๊ตณ์ด ์ฌ๋ฌ ๊ฐ๋ฅผ ๋ฌถ์ด์ผ๊ฒ ๋ค๋ฉด ์ตํ์ ๋ณด๋ฃจ์ธ ๋ฐฉ์ด๊ธฐ์ฌ(useMemo)๋ฅผ ๋ฐ๋ฅด์ญ์์ค.
<DataContext.Provider value={useMemo(() => ({info, setInfo}), [info])}> ๋ก ํฌ์ฅ์ง๋ฅผ ๊ฐ์ ๋๊ฒฐ์ํค๋ฉด ๊ทธ๋๋ง ์๋น๊ทํ์ ๋ง์ ์ ์์ต๋๋ค.
๐ ์ด๋ฒ์ ๋ฐฐ์ด ๋ด์ฉ ์ด์ ๋ฆฌ
| ์ํฉ | โ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(Zustand ๋ฑ)์ ์๋ | โ ์์ Context API์ ์๋(ํ๊ณ์ ) |
|---|---|---|
| ๊ฑฐ๋ ๋ฐ๊ตฌ๋์์ ์กฐ๊ทธ๋ง ๊ฐ A๋ง ์์ | ๊ฐ A๊ฐ ์ ๋ฐ๋์์ผ๋ฉด Selector๋ก ์ปท! ๋๋ ๋ ๋๋ง ๋ฌดํจ | ๊ฐ B๊ฐ ๋ฐ๋์๋ค๊ณ ? ํฌ์ฅ์ง๊ฐ ๊ฐ๋ ธ์ผ๋ ์ปดํฌ๋ํธ A ๋๋ ๊ฐ์ ํญํ! (์๋น ์์) |
| ๊ทน๋ณต ์ํคํ ์ฒ | ๋จ์ผ ๊ฑฐ๋ ์คํ ์ด ์ ์ ๊ฐ๋ฅ | ๋ฐ๋์ ๊ด์ฌ์ฌ๋ณ๋ก(User / Theme / Locale) ์์ญ ๊ฐ์ Context๋ฅผ ๋ถํ ์กฐ๋ฆฝ |
๐ก ํ ์ค๋ก ๊ธฐ์ตํ๊ธฐ
Context๋ ์ฐ๋ฒ์ด์ธ , ๋ฐฐ๋ฏผ ๋ฐฐ๋ฌํต๊ณผ ๊ฐ๋ค. ์์ ์นํจ(์ ์ ์ ๋ณด)๊ณผ ํผ์(๋คํฌ๋ชจ๋)๋ฅผ ๋ค ์ฐ๊ฒจ๋ฃ๊ณ ํฌ์ฅํด์ ๋ฐฐ๋ฌํ๋ฉด, ํผ์์ ๊ด์ฌ ์๋ ์นํจ๋ฌ๋ฒ ์ปดํฌ๋ํธ๊น์ง ํฌ์ฅ์ง(๋ฉ๋ชจ๋ฆฌ ๊ป๋ฐ๊ธฐ ์ฃผ์) ๊ฐ๋ด์ ํฉ์ธ๋ ค ๋ฌด์กฐ๊ฑด ๋ฆฌ๋ ๋๋ง ๋ ธ๋์ ๋ฐ๊ฒ ๋๋ค.๊ทธ๋ฌ๋ฏ๋ก Context๋ ์ํ์ ๋จ์, ๋์๊ฐ ์ฝ๊ธฐ(State)์ ์ฐ๊ธฐ(Dispatch) ๋จ์๋ก ์๊ฒ ๋๋ ค๋ด ํ์ดํ ์ฌ๋ฌ ๊ฐ๋ก ๋ด๋ ค๊ฝ๋ ๊ฒ์ด ์๋์ด์ ๊ธฐ์ด ์์์ด๋ค.
๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
Redux ๊น๊ธฐ ๊ท์ฐฎ์์ ๊ทธ๋ฅ useContext ์์ ๋ชจ๋ ์ ๋ณด ๋ค ๋๋ ค๋ฃ๊ณ ํธํ๊ฒ ์ด๋ ค ํ๋๋ฐ, ๊ทธ๊ฒ ๋๋ฌธ์ ์๊ด๋ ์๋ ์ปดํฌ๋ํธ 100๊ฐ๊ฐ ๋ค ๋ ๋๋ง ๋
ธ๋์ ๋ฐ๊ณ ์์๋ค๋ ๋ฑ์ ๋์ด ์ญ ๋ฌ๋ค.
๐ก "๋ช ์ฌ(๊ฐ)์ ๋์ฌ(ํจ์) ๋ฐ๊ตฌ๋์กฐ์ฐจ ์ฐข์ด ๋ฒ๋ ค๋ผ! ๊ป๋ฐ๊ธฐ๋ง ๋ฐ๋์ด๋ ํ์ ํธ๋ฆฌ ์ ์ฒด๊ฐ ์ฟ๋๋ฏธ๊ฐ ๋๋ Context ๋ฐฉ์ฌ๋ฅ์ ๋ง๋ ์ต๊ณ ์ ์ ์ ์ด๋ค."
๋คํฌ๋ชจ๋ ์ค์์น ๋ฒํผ ํ๋ ๋๋ฌธ์ ๋ฒํผ ์์ ๊น์ง ๊น๋นก๊ฑฐ๋ฆฌ์ง ์๊ฒ ๋ง๋ค๋ ค๊ณ Dispatch ์ ์ฉ ํฌํ์ ๋ซ๋ ๊ธฐ๋ฒ์ ์์ ์์ ์ด์๋ค. ๋ฌด์์ ๊ธ๋ก๋ฒ ์ํ๋ผ๊ณ Context ํ๋๋ก ๊ธฐ์ ๋ฒ๋ ธ๋ ์ง๋๋ ์ ๋ฉ์ฒญํ ์ฝ๋๋ค์ ํ ๋ ํ ๋ ๋๋ ค๋ด๊ณ ์ถ์ด์ก๋ค. ์ง์ ๊ฐ์ ๋งฅ์ฃผ ํ ์บ ํ๋ฉด์ ๋ด ์ฝ๋ ์ํ ์ง์ฅ๋๋ ํ ๋ฒ ํํค์ณ๋ด์ผ๊ฒ ๋ค.
๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
Q1. useContext์ ๋์ ์๋ฆฌ๋ฅผ ๋น๋ ๊ฐ์ฅ ์ ํํ ๋ช
์ ๋ฅผ ๊ณ ๋ฅด์ธ์.
- A) "Context๋ ๊ตฌ๋ ์ค์ธ ํ์ ์ปดํฌ๋ํธ๋ค์๊ฒ ๋ฐ๊ตฌ๋ ๋ด๋ถ ์์ฑ(Property) ์ค ๋ด๊ฐ ์ฐ๋ ๊ฐ์ด ๋ณํ์ ๋๋ง ์ค๋งํธํ๊ฒ ์คํตํด ์ฃผ๋ ๋ด์ฅ ๋ฉ๋ชจ์ด์ ์ด์ ์ ํ๊ณ ์๋ค."
- B) "Context Provider์
value๋ก ๋์ ธ์ง๋ ๊ฐ์ฒด(๊ป๋ฐ๊ธฐ)์ ์ฐธ์กฐ ์ฃผ์(Object.is)๊ฐ ๋ณ๊ฒฝ๋๋ ์๊ฐ, ๊ทธ๊ฒ์ ๋ฃ๊ณ ์๋ ํ์์ ๋ชจ๋ ์ปดํฌ๋ํธ๋ค์ ์๋น ์์ด ๋ชจ์กฐ๋ฆฌ ๋ฆฌ๋ ๋๋ง ํ๊ฒฉ์ ๋ง๋๋ค." - C) "Context ์์ ์ํ(State)๊ฐ ๋๋ฌด ๋ณต์กํ๊ฒ ์ฝํ๋ฉด ๋ธ๋ผ์ฐ์ ๋ ๋ฌด๊ฑฐ์์ง๋ฏ๋ก, ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ๋ก Redux ์ ์ฅ์ ์๋ฒ๋ก ์ฎ๊ธด๋ค."
- D) "Context API๋ ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ํ๋ฌผ์ด๋ถ์๋ ์๋ฐฉํฅ ์ด๋ฒคํธ ํธ๋ฆฌ๊ฑฐ ์ ์ฉ ๋๊ตฌ๋ค."
โ ์ ๋ต: B
๐ก ์์ธ ํด์ค: ๋ฆฌ์กํธ Context ํญํฌ์(Waterfall) ์๋ฆฌ์ ํต์ฌ์
๋๋ค. ๋ฆฌ๋์ค(Redux)๋ ์ฅฌ์คํ ๋(Zustand)์ ์
๋ ํฐ(selector) ๊ธฐ๋ฒ๊ณผ ๋ค๋ฅด๊ฒ, ๋ด์ฅ Context๋ ๋ด๋ถ ๋ฐ์ดํฐ ์์ฑ์ด ๋ฌด์์ธ์ง ์ ํ ์์ง ๋ชปํ๊ณ ํ์
ํ ์ง๋ฅ๋ ์์ต๋๋ค. ๊ทธ์ ๋ง์ดํฌ ์ ๊ณต์(Provider)์ value๋ผ๋ ์ปค๋ค๋ ํต(๊ฐ์ฒด ์ฃผ์) ์์ฒด๊ฐ ๋ฐ๋๋ฉด ๊ทธ๋ฅ ํ์์ ์๋ ์ถ์ข
์ ์ปดํฌ๋ํธ๋ฅผ ๋ฌด์ง์ฑ์ผ๋ก ์ ์ ๋ฉฑ์ด ๋๊ณ ๋ ๋๋ง ๋ง์ผ๋ก ๋๊ณ ๋์ค๋ ๋ฌด์ํ์ง๋ง ๋จ์ ๋ฌด์ํ ์์กด์ฑ ์ฃผ์
๊ด์ ๋ถ๊ณผํฉ๋๋ค. (๊ทธ๋์ ํจ๋ถ๋ก ๋จ์ฉํ๋ฉด ์ตํ์์ ํฌ๊ฒ์ดํธ๊ฐ ์ด๋ฆฝ๋๋ค.)
Q2. ์ฑ๋ฅ ์ต์์ Context ํจํด์ธ "์ํ/์ก์ ๋ถ๋ฆฌ๋ฒ(Splitting)"์ ์ ์ฉํ์ ๋, ๋คํฌ๋ชจ๋๋ฅผ ์ ํํ๋ ์ค์์น ๋ฒํผ ์ปดํฌ๋ํธ ๋ด๋ถ์ ์ ์ฉ๋ ๋๋ผ์ด ์ต์ ํ ์ด๋์ ๋ฌด์์ธ๊ฐ์?
- A) ํ ๊ธ ๋ฒํผ ์ปดํฌ๋ํธ ์์ฒด๊ฐ ์ ์ญ ์ํ ์บ์์ ๋ค์ด๊ฐ ๋ธ๋ผ์ฐ์ ์๋ก๊ณ ์นจ์ ํด๋ ์๊ตฌ ์ ์ฅ๋๋ ๋ง๋ฒ.
- B) ํ ๊ธ ๋ฒํผ์ 10๋ฒ ๊ด์ ์ผ๋ก ํด๋ฆญํด์ ์ ์ญ ํ ๋ง State๊ฐ ์๋์ณ๋, ์ด ๋ฒํผ ์ปดํฌ๋ํธ ์๊ธฐ ์์ ์ ์ด์ฐจํผ State ํฌํ์ ํ๋ด์ง ์์๊ณ ํต์ ๊ถ(Dispatch ์ก์ ํฌํ) ๊ณต๊ฐ๋ง ์ก๊ณ ์์ผ๋ฏ๋ก, ๋ณธ์ธ ์ค์ค๋ก์ ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง ๋ฒ์ฉ์(๊น๋ฐ์ ์ฐ์ฐ)์ 100% ๋ชจ๋ฉดํ๊ณ ๋ฌด์ ์ํ๊ฐ ๋๋ค๋ ๊ธฐ์ .
- C) ์ก์ ํจ์ ์์ฒด๊ฐ ์น ์์ปค(Web Worker) ๋ด๋ถ ๋ฐฑ๊ทธ๋ผ์ด๋๋ก ๋ฐ๋ ค๊ฐ ๋ฒํผ์ ๋ ์ดํด์(์๋)๊ฐ ํ์ ํ๊ฒ ๋จ์ถ๋๋ ์ .
โ ์ ๋ต: B
๐ก ์์ธ ํด์ค: ํฌํ๋ก ์ฐข๊ณ ์ค๋ก์ง ์ก์ ์ฃผ์ฌ๊ธฐ(Dispatch)๋ง ๊ฝ์์ ์ฐ๋ฉด, ์ ๋ฐ์ ์ํ๊ฐ ์ด๋ป๊ฒ ํ์ค๋ฅด๋ ๋ง๋ ์ด ๋ฒํผ ๋์ ๊ทธ ๋ฐฉ์ฌ๋ฅ์ ๋ง์ง ์๋ ๊น๋ํ ๊ฒฉ๋ฆฌ๋ง์ด ํ์ฑ๋ฉ๋๋ค.
Q3. ์์ฒ ์ด๋ "Props Drilling์ด ๋๋ฌด ์ง๊ฒน๊ณ ์ปดํฌ๋ํธ ๋ช ๊น์ด ์ด์ ํ๋ ๊ฑฐ ๊ผด๋ ๋ณด๊ธฐ ์ซ์ด์. ์์ผ๋ก ๋ก๊ทธ์ธ ๋ฐ์ดํฐ๋ , ๊ฒ์์ฐฝ ๊ฒ์์ด๋ ์ปดํฌ๋ํธ ๋๊ธฐ๋ ๊ฑด ์น ๋ค ๋ฌด์กฐ๊ฑด Context API๋ฅผ ์ธ๋์." ๋ผ๊ณ ๋น๋ํ๊ฒ ์ธ์นฉ๋๋ค. ์ํธ๊ฐ Context์ ๋ฌด๋ถ๋ณ ๋จ์ฉ ์ ์ด๋๋๋ '์ปดํฌ๋ํธ์ ์ค๊ณ ๋ฏธํ์ ๋ถ๊ดด ์ธก๋ฉด(์ฌ์ฌ์ฉ์ฑ ๋ฐ์ด)'์ ๋ค์ด ์กฐ์ฉํ ๋ฐ๋ฐํ๋ ๋ง์ ์ฃผ๊ด์์ผ๋ก ์ ์ผ์์ค. (๋จ์ ์ฑ๋ฅ ์ ํ ์ด์๊ฐ ์๋!)
โ ์ ๋ต ๋ฐ ์ฃผ๊ด์ ํด์ค:
"์์ฒ ๋, ํ๋กญ์ค ๊ตฌ๋ฉ ๋ซ๊ธฐ๊ฐ ์ซ๋ค๊ณ ๋ชจ๋ ๊ฑธ Context ํ์ดํ๋ผ์ธ์ ์ฐ๊ฒฐํ๋ฉด ์๊ธฐ๋ ๊ฐ์ฅ ์น๋ช
์ ๋
์๋ ๋ฐ๋ก '์ปดํฌ๋ํธ์ ์ฌ์ฌ์ฉ ๋ถ๊ฐ๋ฅ(Coupling ์ง์ฅ)' ์ ์์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ปดํฌ๋ํธ(<Button>, <UserCard>)๋ฅผ ์ด์๊ฒ ํฌ์ฅํด์ ๋ถ๋ฆฌํ๋ ๊ฑด ๋์ค์ ์ ์ชฝ B ์ฌ์ด๋๋ฐ ๋ฉ๋ด๋ ์ ๋๋ค ํ๋ก์ ํธ์์ ์ ๋ผ๋ค๊ฐ ๊ทธ๋๋ก ์ฌ์กฐ๋ฆฝ(์ฌ์ฌ์ฉ)์ ํ๋ ค๋ ๋ชฉ์ ์ด์ฃ . ๋ง์ฝ ๊ทธ <UserCard> ์์ ๊ฐ์ ๋ก ์ปดํฌ๋ํธ ์ต์๋จ ์ฅ์์ ์๋ ๋ฑ๋ฑํ ํน์ UserContext๋ฅผ ๋ฏ์ด๋จน๋๋ก ํ์ดํ๋ผ์ธ(useContext ๋ก์ง)์ ์ฌ์ด๋ ๋ฒ๋ ธ๋ค๋ฉด?
๊ทธ ์ปดํฌ๋ํธ๋ ๋ฌด์กฐ๊ฑด ์์ฒ ๋์ด ์ธํ
ํ ํน์ Context.Provider ์ฐ์ฐ ์ด๋ถ ๋ฐ์์๋ง ์ด์๋จ๋ ๋
ธ์๊ฐ ๋ฉ๋๋ค. ๋ผ์ด๋ค ๋ด ๊ณณ์ ๋๋๋ฉด ํ์ดํ๊ฐ ๋๊ฒจ ์ฆ์ฌ(Error)ํด๋ฒ๋ฆฌ๊ณ ์ข
์์ฑ ์คํ๊ฒํฐ๊ฐ ํํ๋๋ฒ๋ฆฝ๋๋ค.
๊ทธ์ ๋ถ๋ชจ์์ ์์์ผ๋ก ์์ ์์ค์ธ 2~3๋จ๊ณ ๋ ๋ฒจ์ ํ๋กญ์ค ์ฐํ์ด๋ผ๋ฉด, ๋ ๋๋ฌ์ ๋ณด์ฌ๋ ์์งํ๊ฒ ๊ตฌ๋ฉ์ ๋ซ๊ณ ์ง(Props)์ ์ฅ์ฌ ๋๊ฒจ์ฃผ๋ ๊ฒ์ด ํจ์ฌ ์ปดํฌ๋ํธ์ ํ๋ถ์ฐฉ(ํฉ์ฑ/์ฌ์ฌ์ฉ)์ ์๋ฆ๋ต๊ณ ์์ํ๊ฒ ๋๋๋ ์ ์์
๋๋ค."