๐Ÿ’ป Context(feat. ๋ฆฌ์•กํŠธ ๊ณต์‹๋ฌธ์„œ)

waterglassesยท2022๋…„ 10์›” 7์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
40/50
post-thumbnail

โš ๏ธ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์€ ์˜คํƒ€๋‚˜ ์ž˜๋ชป๋œ ์ •๋ณด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿ“ƒ ์˜ค๋Š˜ ๊ณต๋ถ€ํ•œ ๊ฒƒ

์–ธ์ œ context๋ฅผ ์จ์•ผ ํ• ๊นŒ

context๋Š” React ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ ์•ˆ์—์„œ ์ „์—ญ์ ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ณ ์•ˆ๋œ ๋ฐฉ๋ฒ•์ด๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ๋Š” ๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊พธ๋ฏธ๊ธฐ ์œ„ํ•ด theme props๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๋„˜๊ฒจ์ฃผ๊ณ  ์žˆ๋‹ค.

class App extends React.Component {
  render() {
    return <Toolbar theme="dark" />;
  }
}

function Toolbar(props) {
  // Toolbar ์ปดํฌ๋„ŒํŠธ๋Š” ๋ถˆํ•„์š”ํ•œ ํ…Œ๋งˆ prop๋ฅผ ๋ฐ›์•„์„œ
  // ThemeButton์— ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  // ์•ฑ ์•ˆ์˜ ๋ชจ๋“  ๋ฒ„ํŠผ์ด ํ…Œ๋งˆ๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค๋ฉด
  // ์ด ์ •๋ณด๋ฅผ ์ผ์ผ์ด ๋„˜๊ธฐ๋Š” ๊ณผ์ •์€ ๋งค์šฐ ๊ณคํ˜น์Šค๋Ÿฌ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  return (
    <div>
      <ThemedButton theme={props.theme} />
    </div>
  );
}

class ThemedButton extends React.Component {
  render() {
    return <Button theme={this.props.theme} />;
  }
}

context๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ค‘๊ฐ„์— ์žˆ๋Š” ์—˜๋ฆฌ๋จผํŠธ๋“ค์—๊ฒŒ props๋ฅผ ๋„˜๊ฒจ์ฃผ์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

// ThemeContext ๋งŒ๋“ค๊ธฐ
const ThemeContext = React.createContext('light');

class App extends React.Component {
  render() {
    // Provider๋ฅผ ์ด์šฉํ•ด ํ•˜์œ„ ํŠธ๋ฆฌ์— ํ…Œ๋งˆ ๊ฐ’์„ ๋ณด๋‚ด์ค€๋‹ค.
    // ์•„๋ž˜ ์˜ˆ์‹œ์—์„œ๋Š” dark๋ฅผ ํ˜„์žฌ ์„ ํƒ๋œ ํ…Œ๋งˆ ๊ฐ’์œผ๋กœ ๋ณด๋‚ธ๋‹ค.
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// ์ด์   ์ค‘๊ฐ„์— ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ผ์ผ์ด ํ…Œ๋งˆ๋ฅผ ๋„˜๊ฒจ์ค„ ํ•„์š”๊ฐ€ ์—†๋‹ค.
function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
  // ํ˜„์žฌ ์„ ํƒ๋œ ํ…Œ๋งˆ ๊ฐ’์„ ์ฝ๊ธฐ ์œ„ํ•ด contextType์„ ์ง€์ •ํ•˜๊ณ  ๊ฐ€์žฅ ๊ฐ€๊นŒ์ด ์žˆ๋Š” ํ…Œ๋งˆ Provider๋ฅผ
  // ์ฐพ์•„ ๊ทธ ๊ฐ’์„ ์‚ฌ์šฉ, ํ˜„์žฌ ์„ ํƒ๋œ ํ…Œ๋งˆ๋Š” dark์ด๋‹ค.
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}

context๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ๊ณ ๋ คํ•  ๊ฒƒ

context์˜ ์ฃผ๋œ ์šฉ๋„๋Š” ๋‹ค์–‘ํ•œ ๋ ˆ๋ฒจ์—ย ๋งŽ์€ย ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ context๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ๊ฐ€ ์–ด๋ ค์›Œ์ง

์—ฌ๋Ÿฌ ๋ ˆ๋ฒจ์— ๊ฑธ์ณ props ๋„˜๊ธฐ๋Š” ๊ฑธ ๋Œ€์ฒดํ•˜๋Š” ๋ฐ์— context๋ณด๋‹คย ์ปดํฌ๋„ŒํŠธ ํ•ฉ์„ฑ์ด ๋” ๊ฐ„๋‹จํ•œ ํ•ด๊ฒฐ์ฑ…์ผ ์ˆ˜๋„ ์žˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ ํ•ฉ์„ฑ์ด๋ž€

์•„๋ž˜์ฒ˜๋Ÿผ props๋ฅผ ๊ณ„์† ์ „๋‹ฌํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ

<Page user={user} avatarSize={avatarSize} />
<PageLayout user={user} avatarSize={avatarSize} />
<NavigationBar user={user} avatarSize={avatarSize} />
<Link href={user.permalink}>
  <Avatar user={user} size={avatarSize} />
</Link>

Avatar ์ปดํฌ๋„ŒํŠธ ์ž์ฒด๋ฅผ ๋„˜๊ฒจ์ฃผ๋ฉด context๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ด๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

function Page(props) {
  const user = props.user;
  const userLink = (
    <Link href={user.permalink}>
      <Avatar user={user} size={props.avatarSize} />
    </Link>
  );
  return <PageLayout userLink={userLink} />;
}

<Page user={user} avatarSize={avatarSize} />
<PageLayout userLink={...} />
<NavigationBar userLink={...} />
{props.userLink}

์ œ์–ด์˜ ์—ญ์ „(IoC)์„ ์ด์šฉํ•˜๋ฉด ๋„˜๊ฒจ์ค˜์•ผ ํ•˜๋Š” props ์ˆ˜๋Š” ์ค„๊ณ  ์ตœ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์˜ ์ œ์–ด๋ ฅ์€ ๋” ์ปค์ง€๊ธฐ ๋•Œ๋ฌด๋„น ๋” ๊น”๋”ํ•œ ์ฝ”๋“œ๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ณต์žกํ•œ ๋กœ์ง์„ ์ƒ์œ„๋กœ ์˜ฌ๋ฆฌ๋ฉด ์ปดํฌ๋„ŒํŠธ๋Š” ๋” ๋‚œํ•ดํ•ด์ง€๊ณ  ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋Š” ๋” ์œ ์—ฐํ•ด์ ธ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•ญ์ƒ ์˜ณ์€ ๋ฐฉ๋ฒ•์€ ์•„๋‹ˆ๋‹ค.

๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ํŠธ๋ฆฌ ์•ˆ ์—ฌ๋Ÿฌ ๋ ˆ๋ฒจ์ด ์žˆ๋Š” ๋งŽ์€ ์ปดํฌ๋„ŒํŠธ์— ์ฃผ์–ด์•ผ ํ•  ๊ฒฝ์šฐ, ๋ฐ์ดํ„ฐ ๊ฐ’์ด ๋ณ€ํ•  ๋•Œ๋งˆ๋‹ค ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์— ๋„๋ฆฌ ๋งํ•˜๋Š” ๊ฒƒ์ด context์ด๋‹ค.

API

React.createContext

const MyContext = React.createContext(defaultValue);

context ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค. Context ๊ฐ์ฒด๋ฅผ ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•  ๋•Œ React๋Š” ํŠธ๋ฆฌ ์ƒ์œ„์—์„œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์ด ์žˆ๋Š” ์ง์ด ๋งž๋Š” Provider๋กœ๋ถ€ํ„ฐ ํ˜„์žฌ ๊ฐ’์„ ์ฝ๋Š”๋‹ค.

defaultValue๋Š” ์ ์ ˆํ•œ Provider๋ฅผ ์ฐพ์ง€ ๋ชปํ–ˆ์„ ๋•Œ๋งŒ ์“ฐ์ด๋Š” ๊ฐ’์ด๋‹ค. ์ฆ‰, ๊ฐ’์„ ๋„ฃ์–ด๋„ provider๊ฐ€ ์กด์žฌํ•˜๋ฉด ์ฝ์ง€ ์•Š๋Š”๋‹ค.

Context.Provider

<MyContext.Provider value={/* ์–ด๋–ค ๊ฐ’ */}>

Provider๋Š” context๋ฅผ ๊ตฌ๋…ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์—๊ฒŒ context์˜ ๋ณ€ํ™”๋ฅผ ์•Œ๋ฆฌ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. value prop์„ ๋ฐ›์•„์„œ ์ด ๊ฐ’์„ ํ•˜์œ„์— ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ ์ „๋‹ฌํ•œ๋‹ค.

Provider์˜ value๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ๋‹ค์‹œ ๋ Œ๋”๋ง ๋œ๋‹ค. ๊ฐ’์ด ๋ฐ”๋€Œ์—ˆ๋Š”์ง€ ์—ฌ๋ถ€๋Š” Object.is์™€ ๋™์ผํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•œ๋‹ค.

Class.contextType

class MyClass extends React.Component {
  componentDidMount() {
    let value = this.context;
    /* MyContext์˜ ๊ฐ’์„ ์ด์šฉํ•œ ์ฝ”๋“œ */
  }
  componentDidUpdate() {
    let value = this.context;
  }
  componentWillUnmount() {
    let value = this.context;
  }
  render() {
    let value = this.context;
  }
}
MyClass.contextType = MyContext;

React.createContext()๋กœ ์ƒ์„ฑํ•œ Context ๊ฐ์ฒด๋ฅผ ์›ํ•˜๋Š” ํด๋ž˜์Šค์˜ย contextType ํ”„๋กœํผํ‹ฐ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ํ”„๋กœํผํ‹ฐ๋ฅผ ํ™œ์šฉํ•ด ํด๋ž˜์Šค ์•ˆ์—์„œย this.context๋ฅผ ์ด์šฉํ•ด ํ•ด๋‹น Context์˜ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด Provider๋ฅผ ์ฐพ์•„ ๊ทธ ๊ฐ’์„ ์ฝ์„ ์ˆ˜ ์žˆ๊ณ ์ด ๊ฐ’์€ render๋ฅผ ํฌํ•จํ•œ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ ์ƒ๋ช…์ฃผ๊ธฐ ๋งค์„œ๋“œ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹จ, Class.contextType์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•˜๋‚˜์˜ context๋งŒ ๊ตฌ๋…ํ•  ์ˆ˜ ์žˆ๋‹ค.

Context.Consumer

<MyContext.Consumer>
  {value => /* context ๊ฐ’์„ ์ด์šฉํ•œ ๋ Œ๋”๋ง */}
</MyContext.Consumer>

context ๋ณ€ํ™”๋ฅผ ๊ตฌ๋…ํ•˜๋Š” React ์ปดํฌ๋„ŒํŠธ์ด๋‹ค. ์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ context๋ฅผ ๊ตฌ๋…ํ•  ์ˆ˜ ์žˆ๋‹ค. Context.Consumer์˜ ์ž์‹์€ ํ•จ์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” context์˜ ํ˜„์žฌ๊ฐ’์„ ๋ฐ›๊ณ  React๋…ธ๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

Context.displayName

Context ๊ฐ์ฒด๋Š” displayName ๋ฌธ์ž์—ด ์†์„ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ฌธ์ž์—ด์„ ์‚ฌ์šฉํ•ด์„œ context๋ฅผ ์–ด๋–ป๊ฒŒ ๋ณด ์—ฌ์ค„ ์ง€ ๊ฒฐ์ •ํ•œ๋‹ค.

const MyContext = React.createContext(/* some value */);
MyContext.displayName = 'MyDisplayName';

<MyContext.Provider> // "MyDisplayName.Provider" in DevTools
<MyContext.Consumer> // "MyDisplayName.Consumer" in DevTools

Hook

useContext

const value = useContext(MyContext);

context๊ฐ์ฒด๋ฅผ ๋ฐ›์•„ ๊ทธ context์˜ ํ˜„์žฌ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. context์˜ ํ˜„์žฌ ๊ฐ’์€ ํŠธ๋ฆฌ ์•ˆ์—์„œ ์ด Hook์„ ํ˜ธ์ถœํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์ด์— ์žˆ๋Š”ย <MyContext.Provider>์˜ย valueย prop์— ์˜ํ•ด ๊ฒฐ์ •๋œ๋‹ค.

useContext๋ฅผ ํ˜ธ์ถœํ•œ ์ปดํฌ๋„ŒํŠธ๋Š” context ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ํ•ญ์ƒ ๋ฆฌ๋ Œ๋”๋ง ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฆฌ๋ Œ๋”๋ง ํ•˜๋Š” ๊ฒƒ์— ๋น„์šฉ์ด ๋งŽ์ด ๋“ ๋‹ค๋ฉด,ย ๋ฉ”๋ชจ์ด์ œ์ด์…˜์„ ์‚ฌ์šฉํ•ด ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

useContext(MyContext)๋Š” ํด๋ž˜์Šค์—์„œ์˜ย static contextType = MyContextย ๋˜๋Š”ย <MyContext.Consumer>์™€ ๊ฐ™๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์ฃผ์˜์‚ฌํ•ญ

๋‹ค์‹œ ๋ Œ๋”๋งํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์ •ํ•  ๋•Œ ์ฐธ์กฐ๋ฅผ ํ™•์ธํ•˜๊ธฐ ๋•Œ๋ฌธ์—, Provider์˜ ๋ถ€๋ชจ๊ฐ€ ๋ Œ๋”๋ง ๋  ๋•Œ๋งˆ๋‹ค ๋ถˆํ•„์š”ํ•˜๊ฒŒ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‹ค์‹œ ๋ Œ๋”๋ง ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜๋„ ์žˆ๋‹ค.

class App extends React.Component {
  render() {
    return (
      <MyContext.Provider value={{something: 'something'}}>
        <Toolbar />
      </MyContext.Provider>
    );
  }
}

์ด๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ถ€๋ชจ์˜ state๊ฐ’์œผ๋กœ ๋Œ์–ด์˜ฌ๋ฆฌ๋ฉด ๋œ๋‹ค.

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: {something: 'something'},
    };
  }

  render() {
    return (
      <MyContext.Provider value={this.state.value}>
        <Toolbar />
      </MyContext.Provider>
    );
  }
}

๋Ÿฌ๋ถ ํ”„๋กœ์ ํŠธ context ์ฝ”๋“œ ๋œฏ์–ด๋ณด๊ธฐ

UserContext/index.js

import React, { createContext, useContext, useReducer } from 'react'
import useActions from './actions'
import { reducer } from './reducer'

export const useUserContext = () => {
  const context = useContext(UserContext)
  if (context === undefined) {
    throw new Error('useUserContext was used outside of its Provider')
  }
  return context
}

const UserContext = createContext()

const UserContextProvider = ({ children }) => {
  const [currentUserState, dispatch] = useReducer(reducer, initialUserData)
  const { onAuth, onLogin, onLogout, onSignUp, onUpdate } = useActions(dispatch)

  return (
    <UserContext.Provider
      value={{ currentUserState, onAuth, onLogin, onLogout, onSignUp, onUpdate }}
    >
      {children}
    </UserContext.Provider>
  )
}

export default UserContextProvider

useContextํ›…์„ ์‚ฌ์šฉํ•ด์„œ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค์‹œ ๋ Œ๋”๋ง ํ•˜๋„๋ก ๊ตฌ์„ฑํ•˜์˜€๋‹ค. ๋˜ํ•œ useReducerํ›…๋„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์œ ์ € ์ •๋ณด๋ฅผ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€๋‹ค.

๋˜ํ•œ action์„ value๋กœ ๋„˜๊ฒจ ํ–‰ํ•ด์ง„ action์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์ƒํƒœ ๋ณ€ํ™˜์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•˜์˜€๋‹ค.

App.js

import UserContextProvider from '@contexts/UserContext'
import AppRouter from '@routes'

function App() {
  return (
    <UserContextProvider>
      <AppRouter />
    </UserContextProvider>
  )
}

export default App

App.js ์ฆ‰ ๋ชจ๋“  ํŽ˜์ด์ง€์—์„œ ์œ ์ € ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— App์„ Provider๋กœ ๊ฐ์‹ธ์„œ ์ „๋‹ฌ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€๋‹ค.

useActions

const useActions = (dispatch) => {
  const onLogin = useCallback(
    async (userInfo) => {
      dispatch({ type: SET_LOADING })

      const { user, token } = await login(userInfo)
      setItem('jwt_token', token)

      dispatch({ type: SET_USER, payload: { user, token } })
    },
    [dispatch]
  )

  return {
      onLogin
	}
}

export default useActions

useActions๋ฅผ ๋งŒ๋“ค์–ด dispatch๋ฉ”์„œ๋“œ๋กœ ํƒ€์ž…์„ ๋„ฃ์–ด ์ƒํ™ฉ์— ๋งž๊ฒŒ ์ƒํƒœ๊ฐ€ ์ €์žฅ๋  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€๋‹ค.

reducer

import { SET_USER } from './constants'

export const reducer = (state, { type, payload }) => {
  switch (type) {
    case SET_USER:
      return {
        ...state,
        currentUser: payload.user,
        token: payload.token,
      }
    default:
      throw new Error(`Unknown action type: ${type}`)
  }
}

๋‹ค์Œ๊ณผ ๊ฐ™์ด reducer๋ฅผ ๋งŒ๋“ค์–ด dispatch ๋ฉ”์„œ๋“œ์™€ ์ง์˜ ํ˜•ํƒœ๋กœ state๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€๋‹ค.

๐Ÿ”ฅ ๋Š๋‚€์ 

๋Ÿฌ๋ถ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•  ๋•Œ context๋กœ ์œ ์ € ์ •๋ณด๋ฅผ ๊ด€๋ฆฌ ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜์˜€๋Š”๋ฐ ์‹œ๊ฐ„์ด ์กฐ๊ธˆ ์ง€๋‚˜์„œ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ–ˆ์—ˆ๋Š”์ง€ ์กฐ๊ธˆ ๊ฐ€๋ฌผ๊ฐ€๋ฌผํ–ˆ๋‹ค.
์ด๋ฒˆ์— ๋‹ค์‹œ ๊ณต๋ถ€ํ•˜๋ฉด์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ๋œฏ์–ด๋ณด์•˜๋Š”๋ฐ ์–ด๋–ป๊ฒŒ context๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€ ํ”„๋กœ์ ํŠธ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ๋‹ค์‹œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ข‹์•˜๋‹ค.

Refer

profile
๋งค ์ˆœ๊ฐ„ ์„ฑ์žฅํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

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