๐จ 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์ ๊ฐ์ฒด๋ฅผ ๋ฃ๋ ์ต์
์ ํ์
์ํฉ: "๋๋ size๋ฅผ Context์ ๋ฃ์ง๋ ์์๋๋ฐ ์ ํ์ ํธ๋ฆฌ๊ฐ ๋ค ํฐ์ง๊น?"
const DataContext = createContext(null);
function Layout() {
const [info, setInfo] = useState('data');
const size = useWindowSize(); // ๐จ ๋ฒ์ธ: ์ฐฝ ํฌ๊ธฐ 1px๋ง ๋ณํด๋ Layout์ ๋ฆฌ๋ ๋๋ง์ํด
return (
// ๐ฅ ์ฑ๋ฅ ์ฌ์์ ์ฃผ๋ฒ: {{ ... }} ์ค๊ดํธ ๋ ๊ฐ
<DataContext.Provider value={{ info, setInfo }}>
<PageArea />
</DataContext.Provider>
)
}๐ ์ '์ฑ๋ฅ ์ฌ์'์ธ๊ฐ? (ํต์ฌ ์์ฝ):
- ์ฆ์ ๋ถ์ด๋นต ๊ตฌ์๋ด๊ธฐ:
value={{ info, setInfo }}๋ ๋ฆฌ์กํธ์๊ฒ **"๋ ๋๋ง ๋๋ง๋ค ๋งค๋ฒ ์๋ก์ด ๊ฐ์ฒด ์ฃผ์๋ฅผ ์์ฑํ๋ผ"**๊ณ ๋ช ๋ นํ๋ ๊ฒ์ ๋๋ค. - ์ฐธ์กฐ๊ฐ ๋ถ์ผ์น ์ง์ฅ:
info๊ฐ์ด ํธ๋ ํ๋ ์ ๋ฐ๋์์ด๋, ๊ฐ์ฒด ์ฃผ์(0x001 -> 0x002) ๊ฐ ๋ฐ๋๊ฒ ๋๊ณ , ๋ฆฌ์กํธ Context ์์ง์ "๋ฐ์ดํฐ๊ฐ ๋ณํ๋ค"๊ณ ํ๋จํฉ๋๋ค. - ๋ฌด์ฐจ๋ณ ํผ๊ฒฉ:
DataContext๋ฅผ ๊ตฌ๋ ํ๋ ์ ๋ฐ๋ฐ๋ฅ์ ์๋ฐฑ ๊ฐ ์ปดํฌ๋ํธ๋ค์ ๋ถ๋ชจ๊ฐ ์ฐฝ ํฌ๊ธฐ ์กฐ์ (size)๋ก ํ๋ค๋ฆด ๋๋ง๋ค ๋ฌด์ง์ฑ์ผ๋ก ๊ฐ์ ๋ฆฌ๋ ๋๋ง ํญํ ์ ๋ง์ต๋๋ค.
โ
ํด๊ฒฐ์ฑ
: ๋๋ ๋๊ฒฐ (useMemo)
// ๐ง [info]๊ฐ ๋ณํ์ง ์๋ ํ, ๊ฐ์ฒด์ ์ฃผ์๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํฉ๋๋ค.
const memoizedValue = useMemo(() => ({ info, setInfo }), [info]);
return <DataContext.Provider value={memoizedValue}>{children}</DataContext.Provider>;์ด๋ ๊ฒ ํด์ผ ๋ถ๋ชจ๊ฐ ์๋ฌด๋ฆฌ ๋ฆฌ๋ ๋๋งํด๋, ํ์ ํธ๋ฆฌ๋ ํ์จ์ ์ ์งํ ์ ์์ต๋๋ค.
๐ ์ด๋ฒ์ ๋ฐฐ์ด ๋ด์ฉ ์ด์ ๋ฆฌ
| ๋น๊ต ํญ๋ชฉ | ๐ฆ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(Zustand, Redux) | โก ์์ Context API |
|---|---|---|
| ๋ ๋๋ง ๋ฐฉ์ด | ๊ฐ๋ฅ: ๊ฐ์ด ์ ๋ฐ๋์์ผ๋ฉด Selector๋ก ์ปท! ๋ ๋๋ง ๋ฌดํจํ | ๋ถ๊ฐ๋ฅ: ํฌ์ฅ์ง(value ์ฃผ์)๊ฐ ๋ฐ๋๋ฉด ํ์ ํธ๋ฆฌ๋ ๊ฐ์ ๋ฆฌ๋ ๋๋ง |
| ์ด์์ ์ธ ์ค๊ณ ๋ฐฉ์ | ์๋ง์ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ๋จ์ผ ๊ฑฐ๋ ์คํ ์ด(Store) ๋ก ์ด์ ๊ฐ๋ฅ | ๋ ๋๋ง ์ค์ผ์ ๋ง๊ธฐ ์ํด ๊ด์ฌ์ฌ๋ณ๋ก ์์ญ ๊ฐ์ Context๋ก ์ชผ๊ฐ์ผ ํจ |
๐ก ํ ์ค๋ก ๊ธฐ์ตํ๊ธฐ
Context๋ ์ฐ๋ฒ์ด์ธ , ๋ฐฐ๋ฏผ๊ณผ ๊ฐ๋ค. ์์ ์นํจ(์ ์ ์ ๋ณด)๊ณผ ํผ์(๋คํฌ๋ชจ๋)๋ฅผ ๋ค ์ฐ๊ฒจ๋ฃ๊ณ ํฌ์ฅํด์ ๋ฐฐ๋ฌํ๋ฉด, ํผ์์ ๊ด์ฌ ์๋ ์นํจ๋ฌ๋ฒ ์ปดํฌ๋ํธ๊น์ง ํฌ์ฅ์ง(๋ฉ๋ชจ๋ฆฌ ๊ป๋ฐ๊ธฐ ์ฃผ์) ๊ฐ๋ด์ ํฉ์ธ๋ ค ๋ฌด์กฐ๊ฑด ๋ฆฌ๋ ๋๋ง ๋ ธ๋์ ๋ฐ๊ฒ ๋๋ค.
๊ทธ๋ฌ๋ฏ๋ก Context๋ ์ํ์ ๋จ์, ๋์๊ฐ ์ฝ๊ธฐ(State)์ ์ฐ๊ธฐ(Dispatch) ๋จ์๋ก ์๊ฒ ๋๋ ค๋ด ํ์ดํ ์ฌ๋ฌ ๊ฐ๋ก ๋ด๋ ค๊ฝ๋ ๊ฒ์ด ์๋์ด์ ๊ธฐ์ด ์์์ด๋ค.
๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
Q1. useContext์ ๋์ ์๋ฆฌ๋ฅผ ๊ฐ์ฅ ์ ํํ๊ฒ ์ค๋ช
ํ ๋ช
์ ๋ฅผ ๊ณ ๋ฅด์ธ์.
- A) "Context๋ ๊ตฌ๋ ์ค์ธ ํ์ ์ปดํฌ๋ํธ๋ค์๊ฒ ๋ฐ๊ตฌ๋ ๋ด๋ถ ์์ฑ(Property) ์ค ๋ด๊ฐ ์ฐ๋ ๊ฐ์ด ๋ณํ์ ๋๋ง ๋ ๋๋ง์ ๋ฉ์ถฐ์ฃผ๋ ๋ด์ฅ ๋ฉ๋ชจ์ด์ ์ด์ ์ ํ๊ณ ์๋ค."
- B) "Context Provider์
value๋ก ๋์ ธ์ง๋ ๊ฐ์ฒด์ ์ฐธ์กฐ ์ฃผ์(Object.is)๊ฐ ๋ณ๊ฒฝ๋๋ ์๊ฐ, ๊ทธ๊ฒ์ ๋ฃ๊ณ ์๋ ํ์์ ๋ชจ๋ ์ปดํฌ๋ํธ๋ค์ ๊ฐ์ ๋ก ๋ฆฌ๋ ๋๋ง๋๋ค." - C) "Context ์์ ์ํ(State)๊ฐ ๋๋ฌด ๋ณต์กํ๊ฒ ์ฝํ๋ฉด ๋ธ๋ผ์ฐ์ ์ฑ๋ฅ์ด ์ ํ๋๋ฏ๋ก, ๋ฆฌ์กํธ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ๋ก ๋ฐฑ๊ทธ๋ผ์ด๋ ์๋ฒ๋ก ์ฎ๊ธด๋ค."
- D) "Context API๋ ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ํ๋ฌผ๊ธฐ ์ํ ์๋ฐฉํฅ ์ด๋ฒคํธ ํธ๋ฆฌ๊ฑฐ ์ ์ฉ ๋๊ตฌ๋ค."
โ ์ ๋ต: B
๐ก ์์ธ ํด์ค: ๋ฆฌ์กํธ Context ํญํฌ์(Waterfall) ์๋ฆฌ์ ํต์ฌ์
๋๋ค. Redux๋ Zustand์ ์
๋ ํฐ(selector) ๊ธฐ๋ฒ๊ณผ ๋ค๋ฅด๊ฒ, ๋ด์ฅ Context๋ ๋ด๋ถ ๋ฐ์ดํฐ ์์ฑ์ด ๋ณํ๋์ง๋ฅผ ๊ฐ๋ณ์ ์ผ๋ก ํ์
ํ์ง ๋ชปํฉ๋๋ค. ๊ทธ์ ์ ๊ณต์(Provider)์ value๋ก ์ ๋ฌ๋ ๊ฐ์ฒด ์ฃผ์(์ฐธ์กฐ๊ฐ) ์์ฒด๊ฐ ๋ฐ๋๋ฉด ํ์ ๊ตฌ๋
์ปดํฌ๋ํธ๋ฅผ ๋ชจ๋ ๋ค์ ๊ทธ๋ฆฌ๋ ๋จ์ํ ์์กด์ฑ ์ฃผ์
๋๊ตฌ์ ๊ฐ๊น์ต๋๋ค.
Q2. ์ฑ๋ฅ ์ต์ ํ ํจํด์ธ "์ํ/์ก์ ๋ถ๋ฆฌ๋ฒ(Splitting)"์ ์ ์ฉํ์ ๋, ๋คํฌ๋ชจ๋๋ฅผ ์ ํํ๋ ์ค์์น ๋ฒํผ ์ปดํฌ๋ํธ๊ฐ ์ป๋ ์ด์ ์ ๋ฌด์์ธ๊ฐ์?
- A) ํ ๊ธ ๋ฒํผ ์ปดํฌ๋ํธ ์์ฒด๊ฐ ์ ์ญ ์ํ ์บ์์ ๋ค์ด๊ฐ ๋ธ๋ผ์ฐ์ ์๋ก๊ณ ์นจ์ ํด๋ ์๊ตฌ ์ ์ฅ๋๋ค.
- B) ์ค์ง ๋์(Action) ํฌํ๋ง ๊ตฌ๋ ํ๋ฏ๋ก ๋ ๋๋ง ์์ธ์ธ ์ํ(State) ํฌํ๊ณผ ๊ฒฉ๋ฆฌ๋์ด, ์ ์ญ ํ ๋ง ๊ฐ์ด ๋ณํ๋๋ผ๋ ์ค์์น ๋ฒํผ ์์ ์ ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ๊ฒช์ง ์๋๋ค.
- C) ์ก์ ํจ์ ์์ฒด๊ฐ ์น ์์ปค(Web Worker) ๋ด๋ถ ๋ฐฑ๊ทธ๋ผ์ด๋๋ก ๋ฐ๋ ค๊ฐ ๋ฒํผ์ ๋ฐ์ ์๋๊ฐ ํ์ ํ๊ฒ ๋จ์ถ๋๋ค.
โ ์ ๋ต: B
๐ก ์์ธ ํด์ค: ์ํ(๊ฐ)์ ์ก์ (ํจ์) Context๋ฅผ ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ชผ๊ฐ๋ฉด, ๊ฐ์ ํ๋ฉด์ ๊ทธ๋ฆด ํ์๊ฐ ์๊ณ ๋จ์ง ์ก์ ๋ง ์คํํ๋ ์ปดํฌ๋ํธ(์: ๋ฒํผ)๋ '์ก์ Context'๋ง ๊ตฌ๋ ํ๋ฉด ๋ฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ์ํ ๊ฐ ๋ณ๊ฒฝ์ผ๋ก ์ธํด ๋ฐ์ํ๋ ๋ ๋๋ง ํ๋์ ์๋ฒฝํ๊ฒ ํผํด ๊ฐ ์ ์๋ ๊น๋ํ ๊ฒฉ๋ฆฌ๋ง์ด ํ์ฑ๋ฉ๋๋ค.
Q3. ์์ฒ ์ด๋ "Props ๊ณ์ธต์ ๋ฐ๋ผ ๋ฐ์ดํฐ๋ฅผ ๋๊ธฐ๋ ๊ฒ(Props Drilling)์ด ํผ๊ณคํ๋, ์์ผ๋ก๋ ๋ก๊ทธ์ธ ๋ฐ์ดํฐ๋ ๊ฒ์์ด๋ ๋ฌป์ง๋ ๋ฐ์ง์ง๋ ์๊ณ ๋ฌด์กฐ๊ฑด Context API์ ๋ด์์ ์ฐ๊ฒ ๋ค"๋ผ๊ณ ๋งํฉ๋๋ค. Context ๋จ์ฉ ์ ์ด๋๋๋ ๊ธฐ๋ฅ ์ธ์ ์ธ '์ค๊ณ ๊ตฌ์กฐ์ (์ํคํ ์ฒ) ๋ฌธ์ '๋ฅผ ๊ตฌ์ฒด์ ์ผ๋ก ์์ ํ์์ค.
โ ์ ๋ต ๋ฐ ์ฃผ๊ด์ ํด์ค:
์์ฒ ๋์ฒ๋ผ ์ปดํฌ๋ํธ ๊น์ด๊ฐ ์กฐ๊ธ ๊น๋ค๊ณ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ Context ํ์ดํ๋ผ์ธ์ ์ฐ๊ฒฐํด ๋ฒ๋ฆฌ๋ฉด, '์ปดํฌ๋ํธ์ ๋
๋ฆฝ์ฑ๊ณผ ์ฌ์ฌ์ฉ์ฑ(Coupling ๋ฌธ์ )' ์ด ํฌ๊ฒ ํผ์๋ฉ๋๋ค.
์ฐ๋ฆฌ๊ฐ <UserCard> ์ปดํฌ๋ํธ๋ฅผ ์์๊ฒ ๋ถ๋ฆฌํ๋ ์ด์ ๋ ๋์ค์ ์ฌ์ด๋๋ฐ ๋ฉ๋ด๋ ๋ค๋ฅธ ๋ผ์ฐํธ ํ์ด์ง์์ ๊ทธ๋๋ก ์ฌ์ฌ์ฉํ๊ธฐ ์ํจ์
๋๋ค. ๊ทธ๋ฐ๋ฐ ๊ทธ <UserCard> ์์ ํน์ ํ์ด์ง ์ต์๋จ์๋ง ์กด์ฌํ๋ UserContext๋ฅผ ์ง์ ๊ตฌ๋
ํ๋๋ก ๋ก์ง(useContext)์ ํ๋์ฝ๋ฉํด ๋ฒ๋ฆฐ๋ค๋ฉด?
๊ทธ ์ปดํฌ๋ํธ๋ ๋ฌด์กฐ๊ฑด ์์ฒ ๋์ด ์ธํ
ํ ํน์ Context ์ฐ์ฐ ๋ฐ์์๋ ์๋ฌ๋ฅผ ๋ฟ์ผ๋ฉฐ ๋์ํ์ง ์๊ฒ ๋ฉ๋๋ค. ์ฌ์ฌ์ฉ ๋ถ๊ฐ๋ฅํ ์์กด์ ์ธ ๋ฉ์ด๋ฆฌ๊ฐ ๋๋ ๊ฒ์ด์ฃ .
๋ฐ๋ผ์ ๋ถ๋ชจ์์ ์์์ผ๋ก 2~3๋จ๊ณ ์ ๋์ ์์ ๊ณ์ธต์ด๋ผ๋ฉด, ์ฝ๊ฐ ๋ฒ๊ฑฐ๋กญ๋๋ผ๋ ๋ช
์์ ์ผ๋ก Props๋ฅผ ๋ฐ๋ผ ๋ฐ์ดํฐ๋ฅผ ๋ด๋ ค์ฃผ๋ ๊ฒ์ด ์ปดํฌ๋ํธ์ ๋
๋ฆฝ์ฑ(ํฉ์ฑ/์ฌ์ฌ์ฉ)์ ์ฐ์ํ๊ฒ ์ ์งํ๋ ๋ฆฌ์กํธ์ ์ ์ ์ค๊ณ์
๋๋ค.
๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
Redux ๊น๊ธฐ ๊ท์ฐฎ์์ ๊ทธ๋ฅ useContext ์์ ๋ชจ๋ ์ ๋ณด ๋ค ๋๋ ค๋ฃ๊ณ ํธํ๊ฒ ์ด๋ ค ํ๋๋ฐ, ๊ทธ๊ฒ ๋๋ฌธ์ ์๊ด๋ ์๋ ์ปดํฌ๋ํธ 100๊ฐ๊ฐ ๋ค ๋ ๋๋ง ๋
ธ๋์ ๋ฐ๊ณ ์์๋ค๋ ๋ฑ์ ๋์ด ์ญ ๋ฌ๋ค.
๐ก "๋ช ์ฌ(๊ฐ)์ ๋์ฌ(ํจ์) ๋ฐ๊ตฌ๋์กฐ์ฐจ ์ฐข์ด ๋ฒ๋ ค๋ผ! ๊ป๋ฐ๊ธฐ๋ง ๋ฐ๋์ด๋ ํ์ ํธ๋ฆฌ ์ ์ฒด๊ฐ ์ฟ๋๋ฏธ๊ฐ ๋๋ ๋ ๋๋ง ์ค์ผ์ ๋ง๋ ์ต๊ณ ์ ์ ์ ์ด๋ค."
๋คํฌ๋ชจ๋ ์ค์์น ๋ฒํผ ํ๋ ๋๋ฌธ์ ๋ฒํผ ์์ ๊น์ง ๊น๋นก๊ฑฐ๋ฆฌ์ง ์๊ฒ ๋ง๋ค๋ ค๊ณ Dispatch ์ ์ฉ ํฌํ์ ๋ซ๋ ๊ธฐ๋ฒ์ ์์ ์์ ์ด์๋ค. ๋ฌด์์ ๊ธ๋ก๋ฒ ์ํ๋ผ๊ณ Context ํ๋๋ก ๊ธฐ์ ๋ฒ๋ ธ๋ ์ง๋๋ ์ ๋นํจ์จ์ ์ธ ์ฝ๋๋ค์ ํ ๋ ํ ๋ ๋๋ ค๋ด๊ณ ์ถ์ด์ก๋ค. ์ง์ ๊ฐ์ ๋งฅ์ฃผ ํ ์บ ํ๋ฉด์ ๋ด ์ฝ๋ ์ํ ์ง์ฅ๋๋ ํ ๋ฒ ํํค์ณ๋ด์ผ๊ฒ ๋ค.