โณ

4. useContext

4.1 useContext๋ž€?

4.1.1. ์ปจํ…์ŠคํŠธ ์ •์˜

ย 
์ปดํฌ๋„ŒํŠธ ๊ฐ„์˜ ๋ฐ์ดํ„ฐ(state)๋ฅผ ์ „๋‹ฌํ•˜๋ ค๋ฉด props๋ฅผ ์ด์šฉํ•˜์—ฌ ์ „๋‹ฌํ•ด์•ผ๋งŒ ํ–ˆ์Šต๋‹ˆ๋‹ค. props๋ฅผ ํ†ตํ•œ ์ „๋‹ฌ ๋ฐฉ๋ฒ•์€, ๋ถ€๋ชจ์š”์†Œ์—์„œ ์ž์‹์š”์†Œ๋กœ๋งŒ ์ง„ํ–‰๋˜๋ฉฐ ๋ถ€๋ชจ-์ž์‹ ์ปดํฌ๋„ŒํŠธ์˜ ๊นŠ์ด๊ฐ€ ๊นŠ์–ด์งˆ์ˆ˜๋ก ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ปดํฌ๋„ŒํŠธ๋ผ๋„ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด props๋ฅผ ๋„˜๊ฒจ์ค˜์•ผ ํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 4-1๊ทธ๋ฆผ 4-1
๊ทธ๋ฆผ 4-1
ย 
๋น„๊ต์  ์ž‘์€ ๊ทœ๋ชจ์˜ ํ”„๋กœ์ ํŠธ์˜ ๊ฒฝ์šฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ฒจ์ค„ ๋•Œ์—” ๊ฐ„๋‹จํ•œ ์ž‘์—…์œผ๋กœ ํšจ์œจ์ ์œผ๋กœ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทœ๋ชจ๊ฐ€ ์žˆ๋Š” ํ”„๋กœ์ ํŠธ์ผ์ˆ˜๋ก ์ปดํฌ๋„ŒํŠธ์˜ ๊นŠ์ด๊ฐ€ ๊นŠ์–ด์ง€๊ณ  ๋ฐ์ดํ„ฐ์˜ ์ „๋‹ฌ์ด ๋งŽ์•„์ง‘๋‹ˆ๋‹ค. props๊ฐ€ ํ•„์š”ํ•œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹ˆ๋”๋ผ๋„, ๊ทธ ์•„๋ž˜ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด props๋ฅผ ์ „๋‹ฌํ•ด์•ผ ํ•˜๋Š” ๋ถˆํ•„์š”ํ•˜๊ณ  ๋ฐ˜๋ณต์ ์ธ ์ž‘์—…์ด ์ด๋ฃจ์–ด์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 4-2๊ทธ๋ฆผ 4-2
๊ทธ๋ฆผ 4-2
ย 
์ด๋Ÿฌํ•œ ํ˜„์ƒ์„ props๊ฐ€ ๋“œ๋ฆด๋กœ ๋šซ๊ณ  ๋“ค์–ด๊ฐ„๋‹ค๊ณ  ํ‘œํ˜„ํ•˜์—ฌ props drilling์ด๋ผ๊ณ  ๋ถˆ๋ฆฝ๋‹ˆ๋‹ค. ์ปจํ…์ŠคํŠธ๋Š” ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ ์•ˆ์—์„œ ์ „์—ญ์ ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ณ ์•ˆ๋œ ๋ฐฉ๋ฒ•์ด๊ธฐ ๋•Œ๋ฌธ์— props drilling ํ˜„์ƒ์„ ๋ง‰์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 4-3๊ทธ๋ฆผ 4-3
๊ทธ๋ฆผ 4-3
ย 
์ „์—ญ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์œผ๋‹ˆ, 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;
App.jsx
ย 
Context.jsx
Context๋Š” ๋”ฐ๋กœ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•ด์ฃผ๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.createContext์•ˆ์—๋Š” ๋ฐ์ดํ„ฐ์˜ ์ดˆ๊นƒ๊ฐ’์ด ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. ๋‹จ, ์ด ์ดˆ๊ธฐ๊ฐ’์€ Context.Provider ๋ฅผ ํ†ตํ•ด value ๊ฐ’์„ ์„ค์ •ํ•ด์ฃผ์ง€ ์•Š์•˜์„ ๋•Œ, ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.
ย 
import { createContext } from "react"; export const MenuContext = createContext(null);
Context.jsx
ย 
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> ); }
Customer1.jsx ์™€ Customer2.jsx
ย 

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>; }
Customer1.jsx ์™€ Customer2.jsx
ย 
App.jsx
์•„๋ž˜ ์˜ˆ์ œ์™€ ๊ฐ™์ด Context.Provider ํƒœ๊ทธ๋กœ ๊ฐ์‹ธ์ฃผ์ง€ ์•Š๊ณ ๋„ ์ปจํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
import Customer1 from "./Customer1"; import Customer2 from "./Customer2"; function App() { return ( <> <Customer1 /> <Customer2 /> </> ); } export default App;
App.jsx
ย 
Context .jsx
์•„๋ž˜์˜ ์˜ˆ์‹œ์™€ ๊ฐ™์ด createContext์˜ ์ดˆ๊นƒ๊ฐ’์„ ๋ฐ”๋กœ ์„ค์ •ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
ย 
import { createContext } from "react"; const Menu = { ์•„๋ฉ”๋ฆฌ์นด๋…ธ: "3500", ์นดํŽ˜๋ผ๋–ผ: "4000", }; export const MenuContext = createContext(Menu);
Context .jsx
ย 

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();
Context.jsx
ย 
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;
App.jsx
ย 
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> ); }
Store.jsx
ย 

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-4๊ทธ๋ฆผ 4-4
๊ทธ๋ฆผ 4-4
ย 

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> );
index.js
ย 
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} /> </> ); }
App.jsx
ย 
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;
Main.jsx
ย 
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;
KPopList.jsx
ย 
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;
Button.jsx
ย 

4.3.5. ์‹คํ–‰ํ™”๋ฉด

ย 
์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 4-5๊ทธ๋ฆผ 4-5
๊ทธ๋ฆผ 4-5
ย 
โ€˜๋ ˆ๋“œ๋ฒจ๋ฒณ ๋…ธ๋ž˜ ์ฐพ๊ธฐโ€™ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ์˜ ๋…ธ๋ž˜ ์ค‘ ๋ ˆ๋“œ๋ฒจ๋ฒณ ๋…ธ๋ž˜๋งŒ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 4-6๊ทธ๋ฆผ 4-6
๊ทธ๋ฆผ 4-6
ย 
โ€˜๋‚จ์ž ์•„ํ‹ฐ์ŠคํŠธ ๋…ธ๋ž˜ ์ฐพ๊ธฐโ€™ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ์˜ ๋…ธ๋ž˜ ์ค‘ ๋‚จ์ž ์•„ํ‹ฐ์ŠคํŠธ์˜ ๋…ธ๋ž˜๋งŒ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 4-7๊ทธ๋ฆผ 4-7
๊ทธ๋ฆผ 4-7
ย 
โ€˜์—ฌ์ž ์•„ํ‹ฐ์ŠคํŠธ ๋…ธ๋ž˜ ์ฐพ๊ธฐโ€™ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ์˜ ๋…ธ๋ž˜ ์ค‘ ์—ฌ์ž ์•„ํ‹ฐ์ŠคํŠธ์˜ ๋…ธ๋ž˜๋งŒ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 

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-8๊ทธ๋ฆผ 4-8
๊ทธ๋ฆผ 4-8
ย 

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};
context.jsx
ย 
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> );
index.js
ย 
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;
App.jsx
ย 
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;
Main.jsx
ย 
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;
KPopList.jsx
ย 
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;
Button.jsx
ย 
์‹คํ–‰ํ™”๋ฉด
์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 4-9๊ทธ๋ฆผ 4-9
๊ทธ๋ฆผ 4-9
ย 
โ€˜๋ ˆ๋“œ๋ฒจ๋ฒณ ๋…ธ๋ž˜ ์ฐพ๊ธฐโ€™ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ์˜ ๋…ธ๋ž˜ ์ค‘ ๋ ˆ๋“œ๋ฒจ๋ฒณ ๋…ธ๋ž˜๋งŒ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 4-10๊ทธ๋ฆผ 4-10
๊ทธ๋ฆผ 4-10
ย 
โ€˜๋‚จ์ž ์•„ํ‹ฐ์ŠคํŠธ ๋…ธ๋ž˜ ์ฐพ๊ธฐโ€™ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ์˜ ๋…ธ๋ž˜ ์ค‘ ๋‚จ์ž ์•„ํ‹ฐ์ŠคํŠธ์˜ ๋…ธ๋ž˜๋งŒ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 4-11๊ทธ๋ฆผ 4-11
๊ทธ๋ฆผ 4-11
ย 
โ€˜์—ฌ์ž ์•„ํ‹ฐ์ŠคํŠธ ๋…ธ๋ž˜ ์ฐพ๊ธฐโ€™ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ์˜ ๋…ธ๋ž˜ ์ค‘ ์—ฌ์ž ์•„ํ‹ฐ์ŠคํŠธ์˜ ๋…ธ๋ž˜๋งŒ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 4-12๊ทธ๋ฆผ 4-12
๊ทธ๋ฆผ 4-12
ย 
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; }
App.css
ย 

4.4.4. ์ •๋ฆฌ

ย 
Context API์™€ useContext Hook์„ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ์ดํ„ฐ์™€ ๊ด€๋ จ๋œ ์ฝ”๋“œ๋ฅผ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด์˜ ํŠน์ • ๊ฐ’์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ useContext Hook์„ ์‚ฌ์šฉํ•ด ํ•„์š”ํ•œ ๊ฐ’๋งŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์ด ๋†’์•„์ง‘๋‹ˆ๋‹ค.
ย