4.1 useContext๋?4.1.1. ์ปจํ
์คํธ ์ ์4.1.2. Context ์ข
๋ฅ4.2 useContext ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ4.2.1. ๊ธฐ์กด์ contextAPI๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ4.2.2. useContext ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ4.2.3. useState ์ํ๊ฐ ๋๊ฒจ์ฃผ๊ธฐ4.3. Props Drilling4.3.1. ์์ ์ค๋ช
4.3.2. src ํด๋ ๊ตฌ์กฐ4.3.3. ์ปดํฌ๋ํธ ๊ตฌ์กฐ4.3.4. ๊ฐ ํ์ผ์ ๋ํ ์ค๋ช
4.3.5. ์คํํ๋ฉด4.3.6. Props Drilling์ ๋ฌธ์ ์ 4.4 Context API์ useContext Hook์ ์ฌ์ฉํด props drilling ํด๊ฒฐํ๊ธฐ4.4.1. src ํด๋ ๊ตฌ์กฐ4.4.2. ์ปดํฌ๋ํธ ๊ตฌ์กฐ4.4.3. ๊ฐ ํ์ผ์ ๋ํ ์ค๋ช
4.4.4. ์ ๋ฆฌ
4.1 useContext๋?
4.1.1. ์ปจํ ์คํธ ์ ์
ย
์ปดํฌ๋ํธ ๊ฐ์ ๋ฐ์ดํฐ(state)๋ฅผ ์ ๋ฌํ๋ ค๋ฉด props๋ฅผ ์ด์ฉํ์ฌ ์ ๋ฌํด์ผ๋ง ํ์ต๋๋ค. props๋ฅผ ํตํ ์ ๋ฌ ๋ฐฉ๋ฒ์, ๋ถ๋ชจ์์์์ ์์์์๋ก๋ง ์งํ๋๋ฉฐ ๋ถ๋ชจ-์์ ์ปดํฌ๋ํธ์ ๊น์ด๊ฐ ๊น์ด์ง์๋ก ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ง ์๋ ์ปดํฌ๋ํธ๋ผ๋ ์์ ์ปดํฌ๋ํธ๊ฐ ์ฌ์ฉํ๋ค๋ฉด props๋ฅผ ๋๊ฒจ์ค์ผ ํ๋ ๋ฒ๊ฑฐ๋ก์์ด ์์์ต๋๋ค.
ย
ย
๋น๊ต์ ์์ ๊ท๋ชจ์ ํ๋ก์ ํธ์ ๊ฒฝ์ฐ ๋ฐ์ดํฐ๋ฅผ ๋๊ฒจ์ค ๋์ ๊ฐ๋จํ ์์
์ผ๋ก ํจ์จ์ ์ผ๋ก ์์
ํ ์ ์์ต๋๋ค. ํ์ง๋ง ๊ท๋ชจ๊ฐ ์๋ ํ๋ก์ ํธ์ผ์๋ก ์ปดํฌ๋ํธ์ ๊น์ด๊ฐ ๊น์ด์ง๊ณ ๋ฐ์ดํฐ์ ์ ๋ฌ์ด ๋ง์์ง๋๋ค. props๊ฐ ํ์ํ ์์ ์ปดํฌ๋ํธ๊ฐ ์๋๋๋ผ๋, ๊ทธ ์๋ ์์ ์ปดํฌ๋ํธ์๊ฒ ์ ๋ฌํ๊ธฐ ์ํด props๋ฅผ ์ ๋ฌํด์ผ ํ๋ ๋ถํ์ํ๊ณ ๋ฐ๋ณต์ ์ธ ์์
์ด ์ด๋ฃจ์ด์ง๊ฒ ๋ฉ๋๋ค.
ย
ย
์ด๋ฌํ ํ์์ props๊ฐ ๋๋ฆด๋ก ๋ซ๊ณ ๋ค์ด๊ฐ๋ค๊ณ ํํํ์ฌ props drilling์ด๋ผ๊ณ ๋ถ๋ฆฝ๋๋ค. ์ปจํ
์คํธ๋ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ ํธ๋ฆฌ ์์์ ์ ์ญ์ ์ด๋ผ๊ณ ๋ณผ ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ ์ ์๋๋ก ๊ณ ์๋ ๋ฐฉ๋ฒ์ด๊ธฐ ๋๋ฌธ์ props drilling ํ์์ ๋ง์ ์ ์์ต๋๋ค.
ย
ย
์ ์ญ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๊ณ ์ฌ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ผ๋, props๋ฅผ ๋๊ฒจ์ฃผ๋ ๋ฐฉ์์ ์ฌ์ฉํ์ง ์๊ณ ์ปจํ
์คํธ๋ง ์ฐ๋ฉด ๋๊ฒ ๋ค! ๋ผ๊ณ ์๊ฐํ ์ ์์ต๋๋ค. ํ์ง๋ง ๊ท๋ชจ๊ฐ ์์ ํ๋ก์ ํธ๋ผ๋ฉด props๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ํจ์ฌ ํจ์จ์ ์ผ ์ ์์ผ๋ ํจ์จ์ฑ์ ์๊ฐํ์ฌ ์ฌ์ฉํ๋๊ฒ ์ข์ต๋๋ค.
ย
4.1.2. Context ์ข ๋ฅ
ย
๋ฆฌ์กํธ์์ ๊ณต์์ ์ผ๋ก Context API๋ฅผ ํตํด useContext Hook์ ์ฌ์ฉํ๊ธฐ ์ ์๋ ์๋ฏธ์๋ props drilling์ ํผํ๊ธฐ ์ํด Context API๊ฐ ์๋, ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ต๋๋ค. MobX, xstate, recoil, zustand ๋ฑ ์ํ๊ด๋ฆฌ๋ฅผ ์ํ ์ฌ๋ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์กด์ฌํ๋ฉฐ Context API ์์ ์ ๊ณตํ๋ ๊ธฐ๋ฅ ์ธ์ ๊ธฐ๋ฅ์ ํ์ฉํด์ผ ํ๋์ง ํ์ธํ๊ณ ํจ์จ์ฑ์ ๋ฐ์ ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ํํด์ผ ํฉ๋๋ค.
ย
๊ท๋ชจ๊ฐ ํฐ ํ๋ก์ ํธ์์ ๋๋์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ์ฌ์ฉํ ๋ Context API ๋ณด๋ค ๋์ ๋ฒ์ฉ์ฑ์ ๊ฐ์ง ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ ํจ์จ์ ์ผ๋ก ์ฐ์ด๋ฉฐ, side effect, memoization, data serialization ๋ฑ์ ๊ธฐ๋ฅ ๋ฑ์ ํ์ฉํด์ผ ํ ๋ ์ ํ๋ฉ๋๋ค.
ย
๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ฌ๋ฌ ๊ธฐ๋ฅ๊ณผ ๋ฒ์ฉ์ฑ์์ ์ด์ ์ ๊ฐ๊ฒ๋๋ ๋ฆฌ์กํธ์๋
React.createContext
์ useContext
๊ฐ ๋ฑ์ฅํ๊ฒ ๋์๊ณ ํ๋ฐํ๊ฒ ์ฌ์ฉ๋๊ณ ์์ต๋๋ค.ย
4.2 useContext ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
๊ธฐ์กด์ contextAPI๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ๊ณผ
useContext
๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋๋์ด ์์ ๋ก ํ์ธํ๊ฒ ์ต๋๋ค.4.2.1. ๊ธฐ์กด์ contextAPI๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ
contextAPI ๋
Context.Provider
์ Context.Consumer
๋ฅผ ์ฌ์ฉํ์ฌ์ผ ํฉ๋๋ค. ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํด์ฃผ๊ณ ์ถ์ ์ปจํ
์คํธ๋ฅผ Context.Provider
๋ก ๊ฐ์ธ์ค๋๋ค. ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌ๋ฐ๊ณ ์ถ์ ์์น์์
Context.Consumer
๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ์ ์๋๋ก ํฉ๋๋ค.ย
App.jsx
Context.Provider
์ ์์ฑ์ผ๋ก๋ ์ ๋ฌํด์ฃผ๊ณ ์ถ์ ๊ฐ์ value ๋ฅผ ํตํด์ ์ ๋ฌํ ์ ์์ต๋๋ค.ย
import Customer1 from "./Customer1"; import Customer2 from "./Customer2"; import { MenuContext } from "./Context"; function App() { return ( <MenuContext.Provider value={{ ์๋ฉ๋ฆฌ์นด๋ ธ: "3500", ์นดํ๋ผ๋ผ: "4000", }} > <Customer1 /> <Customer2 /> </MenuContext.Provider> ); } export default App;
ย
Context.jsx
Context๋ ๋ฐ๋ก ํ์ผ์ ์์ฑํ์ฌ ์ฌ์ฉํด์ฃผ๋๋ก ํ์์ต๋๋ค.
createContext
์์๋ ๋ฐ์ดํฐ์ ์ด๊น๊ฐ์ด ๋ค์ด๊ฐ๋๋ค. ๋จ, ์ด ์ด๊ธฐ๊ฐ์ Context.Provider
๋ฅผ ํตํด value ๊ฐ์ ์ค์ ํด์ฃผ์ง ์์์ ๋, ์๋ํฉ๋๋ค.ย
import { createContext } from "react"; export const MenuContext = createContext(null);
ย
Customer1.jsx ์ Customer2.jsx
์๋ ์์ ์ฒ๋ผ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ ํ์ ์ปดํฌ๋ํธ์์
MenuContext.Consumer
ํ๊ทธ๋ก ๊ฐ์ธ์ฃผ์ด ์ฌ์ฉํด์ฃผ์ด์ผ ํฉ๋๋ค.ย
/* Customer1.jsx */ import { MenuContext } from "./Context"; export default function Customer1() { return ( <MenuContext.Consumer> {(price) => <div>1๋ฒ ๊ณ ๊ฐ๋์ {price.์๋ฉ๋ฆฌ์นด๋ ธ}์์ ์ง๋ถํฉ๋๋ค. </div>} </MenuContext.Consumer> ); } /* Customer2.jsx */ import { MenuContext } from "./Context"; export default function Customer2() { return ( <MenuContext.Consumer> {(price) => <div>2๋ฒ ๊ณ ๊ฐ๋์ {price.์นดํ๋ผ๋ผ}์์ ์ง๋ถํฉ๋๋ค. </div>} </MenuContext.Consumer> ); }
4.2.2. useContext ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ
useContext
๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฌํ ๋ณต์กํจ์ด ์ค์ด๋ญ๋๋ค.ย
Customer1.jsx ์ Customer2.jsx
useContext(MenuContext)
๋ฅผ ํตํด ์ปจํ
์คํธ๋ฅผ ๋ฐ๋ก ํธ์ถํ๊ณ , ์ปจํ
์คํธ ๋ด์ ๋ณ์๋ฅผ ์ฌ์ฉํด์ฃผ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.ย
import { useContext } from "react"; import { MenuContext } from "./Context"; export default function Customer1() { const price = useContext(MenuContext); return <div>1๋ฒ ๊ณ ๊ฐ๋์ {price.์๋ฉ๋ฆฌ์นด๋ ธ}์์ ์ง๋ถํฉ๋๋ค. </div>; } /*--------------------------------------------------------------*/ /* Customer2.jsx */ import { useContext } from "react"; import { MenuContext } from "./Context"; export default function Customer2() { const price = useContext(MenuContext); return <div>2๋ฒ ๊ณ ๊ฐ๋์ {price.์นดํ๋ผ๋ผ}์์ ์ง๋ถํฉ๋๋ค. </div>; }
ย
App.jsx
์๋ ์์ ์ ๊ฐ์ด
Context.Provider
ํ๊ทธ๋ก ๊ฐ์ธ์ฃผ์ง ์๊ณ ๋ ์ปจํ
์คํธ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.ย
import Customer1 from "./Customer1"; import Customer2 from "./Customer2"; function App() { return ( <> <Customer1 /> <Customer2 /> </> ); } export default App;
ย
Context .jsx
์๋์ ์์์ ๊ฐ์ด
createContext
์ ์ด๊น๊ฐ์ ๋ฐ๋ก ์ค์ ํด์ฃผ๋ฉด ๋ฉ๋๋ค.ย
import { createContext } from "react"; const Menu = { ์๋ฉ๋ฆฌ์นด๋ ธ: "3500", ์นดํ๋ผ๋ผ: "4000", }; export const MenuContext = createContext(Menu);
ย
4.2.3. useState ์ํ๊ฐ ๋๊ฒจ์ฃผ๊ธฐ
useContext
๋ฅผ ํตํด์ useState
์ ๋์ ์ํ๊ด๋ฆฌ ๊ฐ๋ ์ฒ๋ฆฌํด์ค ์ ์์ต๋๋ค.๊ฐ๋จํ ์๋์ ์์ ๋ฅผ ํตํด ์์๋ณด๊ฒ ์ต๋๋ค.
ย
Context.jsx
Context.jsx ํ์ผ์ ์๋ก์ด ์ปจํ
์คํธ๋ฅผ ๋ง๋ค์ด์ค๋๋ค.
ย
import { createContext } from "react"; const Menu = { ์๋ฉ๋ฆฌ์นด๋ ธ: "3500", ์นดํ๋ผ๋ผ: "4000", }; export const MenuContext = createContext(Menu); export const OpenContext = createContext();
ย
App.jsx
useState
๋ฅผ ํตํด ์๋ก ์ํ ๊ฐ์ ์์ฑํด์ค๋๋ค.Context.Provider
์ ๊ฐ์ผ๋ก isOpen
๊ณผ setIsOpen
์ ๋๊ฒจ์ค๋๋ค.ย
/*App.jsx*/ import { useState } from "react"; import Customer1 from "./Customer1"; import Customer2 from "./Customer2"; import Store from "./Store"; import { OpenContext } from "./Context"; function App() { const [isOpen, setIsOpen] = useState(false); return ( <div className="App"> <OpenContext.Provider value={{ isOpen, setIsOpen }}> <Store /> <Customer1 /> <Customer2 /> </OpenContext.Provider> </div> ); } export default App;
ย
Store.jsx
์๋ก Store.jsx ํ์ผ์ ๋ง๋ค์ด์ค๋๋ค.
๊ฐ๊ฒ๋ฅผ ์ด๊ณ ๋ซ๋ ๋ฒํผ์ ๊ฐ์ง๋ฉฐ,
useContext
๋ฅผ ํตํด์ ๊ฐ์ ธ์จ setIsOpen
์ผ๋ก ๋ฒํผ ํด๋ฆญ์ isOpen
์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋๋ก ํด์ค๋๋ค.ย
import { useContext } from "react"; import { OpenContext } from "./Context"; export default function Store() { const { isOpen, setIsOpen } = useContext(OpenContext); const ClickOpen = () => { setIsOpen(true); }; const ClickClose = () => { setIsOpen(false); }; return ( <div> ๊ฐ๊ฒ๋ฌธ์ด {isOpen ? "์ด๋ ธ์ต๋๋ค" : "๋ซํ์ต๋๋ค"} <br /> <button onClick={ClickOpen}>๊ฐ๊ฒ๋ฌธ ์ด๊ธฐ</button> <button onClick={ClickClose}>๊ฐ๊ฒ๋ฌธ ๋ซ๊ธฐ</button> </div> ); }
ย
4.3. Props Drilling
Props drilling์ด๋ ์ค์ฒฉ๋ ์ฌ๋ฌ ๊ณ์ธต์ ์ปดํฌ๋ํธ์ props๋ฅผ ์ ๋ฌํด ์ฃผ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๋จ๊ณ์ ์ผ๋ก ์ผ์ผ์ด props๋ฅผ ๋๊ฒจ์ฃผ๋ค๋ณด๋ ํด๋น props๋ฅผ ์ฌ์ฉํ์ง ์๋ ์ปดํฌ๋ํธ๋ค์๋ ๋ฐ์ดํฐ๊ฐ ์ ๊ณต๋๋ ๋ฌธ์ ์ ์ด ์กด์ฌํฉ๋๋ค. ์ปดํฌ๋ํธ์ ๊น์ด๊ฐ ๊น์ด์ง์๋ก ๋ฃจํธ ์ปดํฌ๋ํธ์์ ์ตํ์ ์ปดํฌ๋ํธ๋ก๋ถํฐ ์์ฐจ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๊ต์ฅํ ๋นํจ์จ์ ์ด๊ณ ์ ์ง๋ณด์ ๋ํ ์ด๋ ค์์ง ๊ฒ์
๋๋ค.
ย
4.3.1. ์์ ์ค๋ช
์๋์ ์์ ๋ props drilling์ ์์์
๋๋ค. ์ปดํฌ๋ํธ๋
App
, Main
, KPopList
, Button
์ผ๋ก ์ด 4๊ฐ์ด๋ฉฐ, props๋ data
, playlist
, setPlaylist
๊ฐ ๊ฐ์ฒด์ ํํ๋ก ํ์์ ๋ฐ๋ผ ๊ฐ ์ปดํฌ๋ํธ๋ง๋ค ๋จ๊ณ์ ์ผ๋ก ์ ๋ฌ๋ฉ๋๋ค. ์ ๋ฌ๋ฐ์ props๋ฅผ ์ด์ฉํด์ ์ผ์ดํ ๋ฆฌ์คํธ ์ค ๋ ๋๋ฒจ๋ฒณ ๋
ธ๋์ ๋จ์ ์ํฐ์คํธ ๋
ธ๋, ์ฌ์ ์ํฐ์คํธ ๋
ธ๋๋ฅผ ์ถ๋ ฅํฉ๋๋ค. ๋ชจ๋ ํ์ ์ปดํฌ๋ํธ๋ค์ ๋ฃจํธ ์ปดํฌ๋ํธ์์ props๋ก ์ ๋ฌ๋ ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์์ต๋๋ค.ย
4.3.2. src ํด๋ ๊ตฌ์กฐ
src ํด๋์ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
โโ src โ โ โ โโ components โ โโ Button.jsx โ โโ KPopList.jsx โ โโ Main.jsx โ โโ App.css โโ App.jsx โโ index.js
4.3.3. ์ปดํฌ๋ํธ ๊ตฌ์กฐ
์ปดํฌ๋ํธ๋
App
, Main
, KPopList
, Button
์ผ๋ก ์ด 4๊ฐ์ด๋ฉฐ, ๊ฐ ์ปดํฌ๋ํธ๋ง๋ค props๋ก data
, playlist
, setPlaylist
์ ์ ํ์ ์ผ๋ก ์ ๋ฌ๋ฉ๋๋ค. ๋ชจ๋ ํ์ ์ปดํฌ๋ํธ๋ค์ ๋ฃจํธ ์ปดํฌ๋ํธ์์ props๋ก ์ ๋ฌ๋ ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์์ต๋๋ค. ย
ย
4.3.4. ๊ฐ ํ์ผ์ ๋ํ ์ค๋ช
index.js
// index.js import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <React.StrictMode> <App /> </React.StrictMode> );
ย
App.jsx
App ์ปดํฌ๋ํธ์์ ๋ ๋๋งํ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ , useState๋ฅผ ์ด์ฉํ์ฌ ์ํ ๊ฐ๊ณผ data์ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ํจ์๋ฅผ ์ค์ ํ ํ
data
, playlist
, setPlaylist
๋ฅผ ํ์ ์ปดํฌ๋ํธ์ธ Main
์ ์ ๋ฌํฉ๋๋ค. // App.jsx import Main from "./components/Main"; import "./App.css"; import { useState } from "react"; export default function App() { const data = [ { title: "Psycho", artist: "Red Velvet", releaseDate: "2019.12.23", gender: "female", }, { title: "Feel My Rhythm", artist: "Red Velvet", releaseDate: "2022.03.21", gender: "female", }, { title: "Beatbox", artist: "NCT DREAM", releaseDate: "2022.05.30", gender: "male", }, { title: "Attention", artist: "NewJeans", releaseDate: "2022.08.01", gender: "female", }, { title: "Rush Hour", artist: "Crush (Feat. j-hope of BTS)", releaseDate: "2022.09.22", gender: "male", }, ]; const [playlist, setPlaylist] = useState(data); return ( <> <h1>K-POP ํ๋ ์ด ๋ฆฌ์คํธ</h1> <Main data={data} playlist={playlist} setPlaylist={setPlaylist} /> </> ); }
ย
Main.jsx
Main ์ปดํฌ๋ํธ๋ ํ๋ ์ด๋ฆฌ์คํธ๋ฅผ ํํฐ๋งํ๊ธฐ ์ํ ๋ฒํผ 3๊ฐ์ KPopList ์ปดํฌ๋ํธ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ํ์ ์ปดํฌ๋ํธ์ธ Button ์ปดํฌ๋ํธ์ KPopList ์ปดํฌ๋ํธ๋ props๋ฅผ ๊ณ์ํด์ ์ ๋ฌ๋ฐ์ต๋๋ค.
//Main.jsx import React from "react"; import Button from "./Button"; import KPopList from "./KPopList"; // data, playlist, setPlaylist๋ฅผ props๋ก ์ ๋ฌ๋ฐ์ ํ, ํ์ ์ปดํฌ๋ํธ์ props๋ฅผ ์ ๋ฌํฉ๋๋ค. function Main({ data, playlist, setPlaylist }) { return ( <> <Button data={data} setPlaylist={setPlaylist}> ๐๐ป ๋ ๋๋ฒจ๋ฒณ ๋ ธ๋ ์ฐพ๊ธฐ </Button> <Button data={data} setPlaylist={setPlaylist}> ๐ค ๋จ์ ์ํฐ์คํธ ๋ ธ๋ ์ฐพ๊ธฐ </Button> <Button data={data} setPlaylist={setPlaylist}> ๐ต ์ฌ์ ์ํฐ์คํธ ๋ ธ๋ ์ฐพ๊ธฐ </Button> <KPopList playlist={playlist} /> </> ); } export default Main;
ย
KPopList.jsx
KPopList ์ปดํฌ๋ํธ์์๋ ํํฐ๋ง๋ ํ๋ ์ด๋ฆฌ์คํธ๋ฅผ ๋ ๋๋งํฉ๋๋ค.
playlist
๋ฅผ props๋ก ์ ๋ฌ๋ฐ์์ ๋ชจ๋ ๋ฐ์ดํฐ์ ์ ๋ณด๋ฅผ ์ ๋ชฉ, ์ํฐ์คํธ, ๋ฐ๋งค์ผ ์์ผ๋ก ๋ ๋๋งํฉ๋๋ค. // KPopList.jsx import React from "react"; import { v4 as uuidv4 } from "uuid"; // playlist๋ฅผ props๋ก ์ ๋ฌ๋ฐ์ต๋๋ค. function KPopList({ playlist }) { return ( <ul> {playlist.map((song) => ( <li key={uuidv4()}> <h3>{song.title}</h3> <strong>{song.artist} </strong> <span>({song.releaseDate})</span> </li> ))} </ul> ); } export default KPopList;
ย
Button.jsx
Button ์ปดํฌ๋ํธ์์๋ props๋ก
data
, setPlaylist
๋ฅผ ์ ๋ฌ๋ฐ์ ๋ฒํผ์ ํด๋ฆญํจ์ ๋ฐ๋ผ ํ๋ ์ด๋ฆฌ์คํธ๋ฅผ ํํฐ๋งํ๊ณ playlist
์ํ ๊ฐ์ ๋ณ๊ฒฝํฉ๋๋ค. ํ๋ฉด์๋ ๊ฐ ๋ฒํผ์ ํด๋นํ๋ ๋
ธ๋์ ์ ๋ณด๋ฅผ ๋ ๋๋งํฉ๋๋ค.//Button.jsx import React from "react"; // props๋ก data, setPlaylist ๋ฅผ ์ ๋ฌ๋ฐ์ต๋๋ค. function Button({ data, setPlaylist, children }) { // ๋ฒํผ์ ๋ด์ฉ์ ๋ฐ๋ผ ํ๋ ์ด๋ฆฌ์คํธ๋ฅผ ํํฐ๋งํฉ๋๋ค. let result = [...data]; if (children === "๐๐ป ๋ ๋๋ฒจ๋ฒณ ๋ ธ๋ ์ฐพ๊ธฐ") { result = data.filter((song) => song.artist === "Red Velvet"); } if (children === "๐ค ๋จ์ ์ํฐ์คํธ ๋ ธ๋ ์ฐพ๊ธฐ") { result = data.filter((song) => song.gender === "male"); } if (children === "๐ต ์ฌ์ ์ํฐ์คํธ ๋ ธ๋ ์ฐพ๊ธฐ") { result = data.filter((song) => song.gender === "female"); } const handleClick = () => { setPlaylist(result); }; console.log(data); return <button onClick={handleClick}>{children}</button>; } export default Button;
ย
4.3.5. ์คํํ๋ฉด
์ฝ๋๋ฅผ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ํ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
โ๋ ๋๋ฒจ๋ฒณ ๋
ธ๋ ์ฐพ๊ธฐโ ๋ฒํผ์ ๋๋ฅด๋ฉด ํ๋ ์ด๋ฆฌ์คํธ์ ๋
ธ๋ ์ค ๋ ๋๋ฒจ๋ฒณ ๋
ธ๋๋ง ๋ํ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
ย
โ๋จ์ ์ํฐ์คํธ ๋
ธ๋ ์ฐพ๊ธฐโ ๋ฒํผ์ ๋๋ฅด๋ฉด ํ๋ ์ด๋ฆฌ์คํธ์ ๋
ธ๋ ์ค ๋จ์ ์ํฐ์คํธ์ ๋
ธ๋๋ง ๋ํ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
ย
โ์ฌ์ ์ํฐ์คํธ ๋
ธ๋ ์ฐพ๊ธฐโ ๋ฒํผ์ ๋๋ฅด๋ฉด ํ๋ ์ด๋ฆฌ์คํธ์ ๋
ธ๋ ์ค ์ฌ์ ์ํฐ์คํธ์ ๋
ธ๋๋ง ๋ํ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
ย
4.3.6. Props Drilling์ ๋ฌธ์ ์
Props Drilling์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ง ์๋ย
App
์ ์ง๊ณ ์์ ์ปดํฌ๋ํธ ๋ํ props๋ฅผ ์ ๋ฌ๋ฐ์์ผ ํ๋ค๋ ์ ์
๋๋ค. Main
ย ์ปดํฌ๋ํธ๋ ์์ ์ปดํฌ๋ํธ์ย props๋ฅผ ๋ด๋ ค์ฃผ๊ธฐ๋ง ํ ๋ฟ ์ง์ ํ์๋ก ํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ์ ์ผ๋ก ๋นํจ์จ์ ์
๋๋ค. KPopList
์ปดํฌ๋ํธ์ Button
์ปดํฌ๋ํธ๊ฐย ๋ฐ์ดํฐ๋ฅผ ์ง์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์๋ณด์
๋๋ค. useContext๋ ์ ์ญ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ๊ธฐ ๋๋ฌธ์ ์ค๊ฐ ๋ค๋ฆฌ ์ญํ ๋ง ํ๋ ์ปดํฌ๋ํธ๋ฅผ ๊ฑด๋๋ฐ๊ณ ๋ฐ์ดํฐ๊ฐ ์ง์ ์ ์ผ๋ก ํ์ํ ์ปดํฌ๋ํธ์์ ๋ฐ๋ก ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋๋ก ํฉ๋๋ค. ๋ฐ๋ผ์ ์์ ๊ฐ์ด ๋ชจ๋ ํ์ ์ปดํฌ๋ํธ์ props๊ฐ ์ ๋ฌ๋๋ ๋ฌธ์ ๋ฅผ ํผํ ์ ์์ต๋๋ค.
ย
4.4 Context API์ useContext Hook์ ์ฌ์ฉํด props drilling ํด๊ฒฐํ๊ธฐ
Context API์ useContext Hook์ ์ฌ์ฉํ๋ฉด ์ปดํฌ๋ํธ๋ง๋ค ์๋ฏธ์๋ props๋ฅผ ๋๊ฒจ์ฃผ์ง ์์๋ ์ปดํฌ๋ํธ ํธ๋ฆฌ ์ ์ฒด์ ํน์ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค. ์ด์ ์ฑํฐ์ ํ๋ ์ด๋ฆฌ์คํธ ์์ ๋ฅผ Context API์ useContext Hook์ ์ฌ์ฉํ์ฌ ๋ค์ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
ย
4.4.1. src ํด๋ ๊ตฌ์กฐ
src ํด๋์ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. context.jsx ํ์ผ์ ์์ฑํด ์ปจํ
์คํธ ๊ด๋ จ ์ฝ๋๋ฅผ ๋ถ๋ฆฌํ์ต๋๋ค.
src โ โโ components โ โโ Button.jsx โ โโ KPopList.jsx โ โโ Main.jsx โ โโ context โ โโ context.jsx โ โโ App.css โโ App.jsx โโ index.js
ย
4.4.2. ์ปดํฌ๋ํธ ๊ตฌ์กฐ
์ด์ ์ฑํฐ์ ๋์ผํ ์์ ๋ฅผ ๊ตฌํํ๋ฏ๋ก ์ปดํฌ๋ํธ์ ๊ตฌ์กฐ๋ ๋์ผํฉ๋๋ค. ๋จ, ์ปจํ
์คํธ ๊ฐ์ฒด ๋ด์ ์ปดํฌ๋ํธ ํธ๋ฆฌ ์ ์ฒด์์ ์ฌ์ฉํ ๊ฐ ๋๋ ํจ์๋ฅผ ์ ์ฅํ๊ณ useContext Hook์ ์ฌ์ฉํด ์ํ๋ ๊ฐ์ด๋ ํจ์๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์์ props drilling๊ณผ ์ฐจ์ด๊ฐ ์์ต๋๋ค.
ย
ย
4.4.3. ๊ฐ ํ์ผ์ ๋ํ ์ค๋ช
context.jsx
๋จผ์ , ํ๋ ์ด๋ฆฌ์คํธ ๋ฐ์ดํฐ๋ฅผ ๋ณ๋๋ก ๊ด๋ฆฌํ๊ธฐ ์ํด context.jsx ํ์ผ์ ์์ฑํฉ๋๋ค.
React.createContext
๋ฅผ ์ฌ์ฉํด ์ปจํ
์คํธ ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค. ํด๋น ์ปจํ
์คํธ ๊ฐ์ฒด๋ฅผ ๊ตฌ๋
ํ ์ปดํฌ๋ํธ๋ค์ ๋ฌถ๊ธฐ ์ํ Provider๋ฅผ ๋ฆฌํดํ๋ KPopContextProvider ์ปดํฌ๋ํธ๋ฅผ ์์ฑํฉ๋๋ค. KPopContextProvider๋ก ๊ฐ์ธ์ง๋ ํ์ ์ปดํฌ๋ํธ๋ค์ data
, playlist
, setPlaylist
๋ฅผ ์ปจํ
์คํธ ๊ฐ์ฒด๋ฅผ ํตํด ์ ๊ทผํ ์ ์๊ฒ ๋ฉ๋๋ค.ย
import {createContext, useState} from "react"; const data = [ { title: "Psycho", artist: "Red Velvet", releaseDate: "2019.12.23", gender: "female", }, { title: "Feel My Rhythm", artist: "Red Velvet", releaseDate: "2022.03.21", gender: "female", }, { title: "Beatbox", artist: "NCT DREAM", releaseDate: "2022.05.30", gender: "male", }, { title: "Attention", artist: "New Jeans", releaseDate: "2022.08.01", gender: "female", }, { title: "Rush Hour", artist: "Crush (Feat. j-hope of BTS)", releaseDate: "2022.09.22", gender: "male", }, ]; // createContext()๋ฅผ ์ฌ์ฉํ์ฌ context ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค. const KPopContext = createContext(); // Provider ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌํดํ๋ KPopContextProvider๋ฅผ ์์ฑํฉ๋๋ค. const KPopContextProvider = ({children}) => { const [playlist, setPlaylist] = useState(data); return ( <KPopContext.Provider value={{data, playlist, setPlaylist}}> {children} </KPopContext.Provider> ) }; export {KPopContext, KPopContextProvider};
ย
index.js
App ์ปดํฌ๋ํธ์ ํ์ ์ปดํฌ๋ํธ ์ ์ฒด์ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด context.jsx์์ ์์ฑํ KPopContextProvider ์ปดํฌ๋ํธ๋ก App ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ธ์ค๋๋ค.
ย
import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; import {KPopContextProvider} from "./context/context"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <React.StrictMode> <KPopContextProvider> <App /> </KPopContextProvider> </React.StrictMode> );
ย
App.jsx
Context API๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค๋ฉด props๋ฅผ ์ ๋ฌํ๊ธฐ ์ํด ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ง ์๋ App ์ปดํฌ๋ํธ์์๋ props ๊ฐ์ ์ ๋ฌํด์ผ ํฉ๋๋ค. ํ์ง๋ง Context API๋ฅผ ์ฌ์ฉํ๋ฉด props drilling ํ์์ด ์ฌ๋ผ์ง๊ณ , ์ฝ๋์ ๊ฐ๋
์ฑ์ด ๊ฐ์ ๋ฉ๋๋ค. ๋ฐ๋ผ์, App ์ปดํฌ๋ํธ๋ props ์ ๋ฌ ์์ด ์ฝ๋๊ฐ ๊น๋ํด์ง๋๋ค.
ย
import "./App.css"; import Main from "./components/Main"; function App() { return ( <> <h1>K-POP ํ๋ ์ด ๋ฆฌ์คํธ</h1> <Main /> </> ); } export default App;
ย
Main.jsx
Main ์ปดํฌ๋ํธ๋ ํ๋ ์ด๋ฆฌ์คํธ๋ฅผ ํํฐ๋งํ๊ธฐ ์ํ ๋ฒํผ 3๊ฐ์ KPopList ์ปดํฌ๋ํธ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
ย
import React from "react"; import Button from "./Button"; import KPopList from "./KPopList"; function Main() { return ( <main> <Button>๐๐ป ๋ ๋๋ฒจ๋ฒณ ๋ ธ๋ ์ฐพ๊ธฐ</Button> <Button>๐ค ๋จ์ ์ํฐ์คํธ ๋ ธ๋ ์ฐพ๊ธฐ</Button> <Button>๐ต ์ฌ์ ์ํฐ์คํธ ๋ ธ๋ ์ฐพ๊ธฐ</Button> <KPopList /> </main> ); } export default Main;
ย
KPopList.jsx
KPopList ์ปดํฌ๋ํธ์์๋ ํํฐ๋ง๋ ํ๋ ์ด๋ฆฌ์คํธ๋ฅผ ๋ ๋๋งํฉ๋๋ค.
useContext
๋ฅผ ์ฌ์ฉํด ์ปจํ
์คํธ ๊ฐ์ฒด ๋ด์ playlist
์ํ ๊ฐ์ ๊ฐ์ ธ์ค๊ณ ํน์ ๋
ธ๋์ ์ ๋ชฉ, ์ํฐ์คํธ, ๋ฐ๋งค์ผ์ ๋ ๋๋งํฉ๋๋ค.ย
import React, {useContext} from "react"; import {v4 as uuidv4} from "uuid"; import {KPopContext} from "../context/context"; function KPopList() { const {playlist} = useContext(KPopContext); return ( <ul> {playlist.map((song) => ( <li key={uuidv4()}> <h3>{song.title}</h3> <strong>{song.artist} </strong> <span>({song.releaseDate})</span> </li> ))} </ul> ); } export default KPopList;
ย
Button.jsx
Button ์ปดํฌ๋ํธ์์๋ ๋ฒํผ์ ํด๋ฆญํจ์ ๋ฐ๋ผ ํ๋ ์ด๋ฆฌ์คํธ๋ฅผ ํํฐ๋งํ๊ณ
playlist
์ํ ๊ฐ์ ๋ณ๊ฒฝํฉ๋๋ค. ย
import React, {useContext} from "react"; import {KPopContext} from "../context/context"; function Button({children}) { const {data, setPlaylist} = useContext(KPopContext); // ๋ฒํผ์ ๋ด์ฉ์ ๋ฐ๋ผ ํ๋ ์ด๋ฆฌ์คํธ๋ฅผ ํํฐ๋งํฉ๋๋ค. let result = [...data]; if (children === "๐๐ป ๋ ๋๋ฒจ๋ฒณ ๋ ธ๋ ์ฐพ๊ธฐ") { result = data.filter((song) => song.artist === "Red Velvet"); } if (children === "๐ค ๋จ์ ์ํฐ์คํธ ๋ ธ๋ ์ฐพ๊ธฐ") { result = data.filter((song) => song.gender === "male"); } if (children === "๐ต ์ฌ์ ์ํฐ์คํธ ๋ ธ๋ ์ฐพ๊ธฐ") { result = data.filter((song) => song.gender === "female"); } const handleClick = () => { setPlaylist(result); }; return <button onClick={handleClick}>{children}</button>; } export default Button;
ย
์คํํ๋ฉด
์ฝ๋๋ฅผ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ํ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
โ๋ ๋๋ฒจ๋ฒณ ๋
ธ๋ ์ฐพ๊ธฐโ ๋ฒํผ์ ๋๋ฅด๋ฉด ํ๋ ์ด๋ฆฌ์คํธ์ ๋
ธ๋ ์ค ๋ ๋๋ฒจ๋ฒณ ๋
ธ๋๋ง ๋ํ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
โ๋จ์ ์ํฐ์คํธ ๋
ธ๋ ์ฐพ๊ธฐโ ๋ฒํผ์ ๋๋ฅด๋ฉด ํ๋ ์ด๋ฆฌ์คํธ์ ๋
ธ๋ ์ค ๋จ์ ์ํฐ์คํธ์ ๋
ธ๋๋ง ๋ํ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
โ์ฌ์ ์ํฐ์คํธ ๋
ธ๋ ์ฐพ๊ธฐโ ๋ฒํผ์ ๋๋ฅด๋ฉด ํ๋ ์ด๋ฆฌ์คํธ์ ๋
ธ๋ ์ค ์ฌ์ ์ํฐ์คํธ์ ๋
ธ๋๋ง ๋ํ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
ย
App.css
์์ ์์ ์์ ์ฌ์ฉํ CSS ์์ฑ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
ย
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;500;600&display=swap"); * { font-family: "Noto Sans", sans-serif; } ul { padding: 0; margin: 0; } li { padding: 10px 5px; list-style: none; } li + li { border-top: 1px solid #bdbdbd; } h3 { margin: 0; line-height: 32px; font-size: 20px; } button { border: none; background-color: #dfebff; color: #007aff; padding: 7px 15px; border-radius: 32px; font-size: 15px; font-weight: 700; cursor: pointer; margin: 3px; } strong { font-weight: 500; }
ย
4.4.4. ์ ๋ฆฌ
Context API์ useContext Hook์ ์ฌ์ฉํ๋ฉด ์ปดํฌ๋ํธ์์ ๋ฐ์ดํฐ์ ๊ด๋ จ๋ ์ฝ๋๋ฅผ ๋ถ๋ฆฌํ ์ ์๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ปดํฌ๋ํธ ๋ด์์ ์ปจํ
์คํธ ๊ฐ์ฒด์ ํน์ ๊ฐ์ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ useContext Hook์ ์ฌ์ฉํด ํ์ํ ๊ฐ๋ง ๊ฐ์ ธ์ฌ ์ ์์ผ๋ฏ๋ก ์ฝ๋์ ๊ฐ๋
์ฑ์ด ๋์์ง๋๋ค.
ย