[React] useContext

๋ณ„์ดยท2025๋…„ 2์›” 21์ผ

useContext์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ธฐ ์ „์—, ์šฐ์„  React์—์„œ Context๋ž€ ๋ฌด์—‡์ธ์ง€๋ถ€ํ„ฐ ์ดํ•ดํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค. useContext๋Š” Context๋ฅผ ๋” ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ Hook์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๐Ÿ”Ž Context๋ž€?

React์—์„œ Context๋Š” ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ ์ „์ฒด์— ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ์ผ๋ฐ˜์ ์ธ React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ props๋ฅผ ํ†ตํ•ด ๋ถ€๋ชจ์—์„œ ์ž์‹์œผ๋กœ ์ „๋‹ฌ๋˜์ง€๋งŒ, Context๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ช…์‹œ์ ์œผ๋กœ props๋ฅผ ๊ฐ ๋ ˆ๋ฒจ๋งˆ๋‹ค ๋„˜๊ฒจ์ฃผ์ง€ ์•Š๊ณ ๋„ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ ์ „์ฒด์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค.

Context๊ฐ€ ํ•„์š”ํ•œ ์ด์œ 

React์—์„œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ props๋ฅผ ํ†ตํ•ด ์ „๋‹ฌํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ๊ฐ€ ๊นŠ์–ด์ง€๋ฉด ์—ฌ๋Ÿฌ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์•ผ ํ•˜๋Š” Props Drilling ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. Context๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด ์ค‘๊ฐ„ ์ปดํฌ๋„ŒํŠธ๋“ค์—๊ฒŒ props๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š๊ณ ๋„ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค. ํŠนํžˆ ํ…Œ๋งˆ, ๋กœ๊ทธ์ธ ์ƒํƒœ, ์–ธ์–ด ์„ค์ •๊ณผ ๊ฐ™์€ ์ „์—ญ์  ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•  ๋•Œ ๋งค์šฐ ์œ ์šฉํ•˜๋‹ค.

๐Ÿ’ก Context API

Context API๋Š” React์—์„œ Context๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ๋“ค์˜ ์ง‘ํ•ฉ์ด๋‹ค. createContext, Provider, Consumer ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ๊ฐœ๋…์œผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

1. createContext

Context ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์„ ์„ ํƒ์ ์œผ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

const ThemeContext = React.createContext('light');

2. Provider

Context์˜ ๊ฐ’์„ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์— ์ œ๊ณตํ•œ๋‹ค. Provider๋Š” value prop์„ ํ†ตํ•ด ๊ฐ’์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

<ThemeContext.Provider value={theme}>
  {/* ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋“ค */}
</ThemeContext.Provider>

3. Consumer

Context์˜ ๊ฐ’์„ ์†Œ๋น„(์‚ฌ์šฉ) ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์ด๋‹ค. useContext๊ฐ€ ๋„์ž…๋˜๊ธฐ ์ „์—๋Š” ์ฃผ๋กœ ์ด ๋ฐฉ์‹์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

<ThemeContext.Consumer>
  {theme => (
	<button style={{ background: theme === 'dark' ? 'black' : 'white' }}>
      {theme} ๋ชจ๋“œ  
    </button>
  )}
</ThemeContext.Consumer>

๐Ÿ’ก useContext Hook

useContext๋Š” Context API์˜ ์ผ๋ถ€๋กœ, Context์˜ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ React Hook์ด๋‹ค. ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ Context ๊ฐ’์— ์ ‘๊ทผํ•  ๋•Œ Consumer๋ณด๋‹ค ๋” ๊ฐ„๊ฒฐํ•˜๊ณ  ์ง๊ด€์ ์ธ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค.

const theme = useContext(ThemeContext);

์ด ํ›…์€ Context ๊ฐ์ฒด๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ ํ˜„์žฌ Context ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. Context์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด useContext๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” ์ž๋™์œผ๋กœ ๋ฆฌ๋ Œ๋”๋ง ๋œ๋‹ค.

๐Ÿ“š useContext ํ™œ์šฉ ์˜ˆ์‹œ

// Context ์ƒ์„ฑํ•˜๊ธฐ
const ThemeContext = React.createContext('light');

// Provider๋กœ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์— ๋ฐ์ดํ„ฐ ์ œ๊ณตํ•˜๊ธฐ
function App() {
	const [theme, setTheme] = useState('light');
  
 	return (
    	<ThemeContext.Provider value={{ theme, setTheme }}>
      		<MainContent />
      	</ThemeContext.Provider>
    );
}

// useContext๋กœ ๋ฐ์ดํ„ฐ ์‚ฌ์šฉํ•˜๊ธฐ
function ThemedButton() {
	const { theme, setTheme } = useContext(ThemeContext);
  
  	return (
    	<button
      		style={{ background: theme === 'dark' ? 'black' : 'white' }}
		onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
        	ํ…Œ๋งˆ ๋ณ€๊ฒฝ
      	</button>
    );
}

โš ๏ธ useContext ์‚ฌ์šฉ์‹œ ์ฃผ์˜์‚ฌํ•ญ

1. ๋ Œ๋”๋ง ์ตœ์ ํ™”

Context ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ํ•ด๋‹น Context๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ์ž์ฃผ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฐ’๊ณผ ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฐ’์„ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

// ๋ถ„๋ฆฌ๋œ Context ์‚ฌ์šฉ
const ThemeContext = createContext('light');
const UserContext = createContext(null);

// App์—์„œ
<ThemeContext.Provider value={theme}>
	<UserContext.Provider value={user}>
    	<MainContent />
    </UserContext.Provider>
</ThemeContext.Provider>

2. ์ ์ ˆํ•œ ์‚ฌ์šฉ

props ์ „๋‹ฌ์ด ๊ฐ„๋‹จํ•˜๋ฉด Context๋ณด๋‹ค props๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋ช…ํ™•ํ•  ์ˆ˜ ์žˆ๋‹ค.
โ˜๐Ÿป ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ (ํ…Œ๋งˆ, ์–ธ์–ด, ์ธ์ฆ ๋“ฑ)
โœŒ๐Ÿป ๊นŠ์€ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ์—์„œ ๋ฐ์ดํ„ฐ ๊ณต์œ 
๐ŸคŸ๐Ÿป ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•ด์•ผ ํ•  ๋•Œ

3. ๋ฉ”๋ชจ์ด์ œ์ด์…˜

Context ๊ฐ’์ด ๊ฐ์ฒด์ธ ๊ฒฝ์šฐ, ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋ฉ”๋ชจ์ด์ œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

function App() {
	const [theme, setTheme] = useState('light');
  	const [user, setUser] = useState(null);
  
  	// ๋ฉ”๋ชจ์ด์ œ์ด์…˜๋œ Context ๊ฐ’
  	const tehmeContextValue = useMemo(() => {
    	return { theme, setTheme };
    }, [theme]);
  
  	return (
    	<ThemeContext.Provider value={themeContextValue}>
      		<MaineContent />
      	</ThemeContext.Provider>
    );
}

useContext Hook์€ React์˜ Context API๋ฅผ ๋” ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋„๊ตฌ์ด๋‹ค. Props Drilling ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ , ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ ์ „์ฒด์— ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค. ์ ์ ˆํžˆ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€ ๋ณด์ˆ˜์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋‹จ์ˆœํ•œ props ์ „๋‹ฌ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋‚˜, ๋ฆฌ๋ Œ๋”๋ง ์ตœ์ ํ™”๊ฐ€ ์ค‘์š”ํ•œ ๊ฒฝ์šฐ๋„ค๋Š” Context ์‚ฌ์šฉ์„ ์‹ ์ค‘ํ•˜๊ฒŒ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค. ๋Œ€๊ทœ๋ชจ ์ƒํƒœ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋Š” Redux๋‚˜ Zustand ๊ฐ™์€ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€