Front-end/React

React: Lifting State Up ๐Ÿ‹๏ธ‍โ™€๏ธ

xeunnie 2025. 2. 24. 01:00
728x90
๋ฐ˜์‘ํ˜•

React: Lifting State Up ๐Ÿ‹๏ธ‍โ™€๏ธ

 

React์—์„œ ์ƒํƒœ ๊ด€๋ฆฌ์˜ ๊ธฐ๋ณธ ์›์น™ ์ค‘ ํ•˜๋‚˜๋Š” ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋•Œ๋กœ๋Š” ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ ๊ฐ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•˜์ฃ . ์ด๋Ÿฐ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํŒจํ„ด์ด ๋ฐ”๋กœ **Lifting State Up(์ƒํƒœ ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ)**์ž…๋‹ˆ๋‹ค. React ๊ณต์‹ ๋ฌธ์„œ Lifting State Up์„ ๊ธฐ๋ฐ˜์œผ๋กœ, ๋” ๋งŽ์€ ์„ค๋ช…๊ณผ ์‹ค์ „ ์˜ˆ์ œ๋ฅผ ์ถ”๊ฐ€ํ•ด ์ƒ์„ธํžˆ ๋‹ค๋ค„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๐ŸŒŸ

 

Lifting State Up์ด๋ž€?

 

React์—์„œ๋Š” **์ƒํƒœ(state)**๊ฐ€ ์ผ๋ฐ˜์ ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๊ฑฐ๋‚˜ ์กฐ์ž‘ํ•ด์•ผ ํ•  ๋•Œ, ์ƒํƒœ๋ฅผ ๊ฐ ์ปดํฌ๋„ŒํŠธ์— ๋ถ„์‚ฐ์‹œํ‚ค๋Š” ๋Œ€์‹  ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ ๋Œ์–ด์˜ฌ๋ฆฌ๋Š” ๊ฒƒ์ด React์˜ ๊ถŒ์žฅ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

 

์™œ ์ƒํƒœ๋ฅผ ๋Œ์–ด์˜ฌ๋ฆด๊นŒ?

๋ฐ์ดํ„ฐ ๋™๊ธฐํ™”: ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•ด์•ผ ํ•  ๋•Œ, ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉด ๋ฐ์ดํ„ฐ์˜ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„: React๋Š” ๋ถ€๋ชจ์—์„œ ์ž์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋‹จ๋ฐฉํ–ฅ ํ๋ฆ„์„ ๊ฐ•์กฐํ•ฉ๋‹ˆ๋‹ค. ์ƒํƒœ๋ฅผ ๋Œ์–ด์˜ฌ๋ฆฌ๋ฉด ์ด ์›์น™์„ ์œ ์ง€ํ•˜๋ฉด์„œ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

 

Lifting State Up์˜ ๊ธฐ๋ณธ ์›๋ฆฌ

 

์˜ˆ์ œ: ๋‘ ์ž…๋ ฅ๊ฐ’์„ ๋™๊ธฐํ™”ํ•˜๋Š” ์˜จ๋„ ๋ณ€ํ™˜๊ธฐ ๋งŒ๋“ค๊ธฐ

 

React ๊ณต์‹ ๋ฌธ์„œ์˜ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ์ธ ์˜จ๋„ ๋ณ€ํ™˜๊ธฐ๋ฅผ ํ™•์žฅํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

1๏ธโƒฃ ์ปดํฌ๋„ŒํŠธ๋ณ„ ์—ญํ•  ๋ถ„๋ฆฌ

BoilingVerdict: ์˜จ๋„๊ฐ€ 100°C ์ด์ƒ์ผ ๋•Œ ๋ฌผ์ด ๋“๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

TemperatureInput: ์˜จ๋„๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š” ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค.

Calculator: ์ƒํƒœ๋ฅผ ๋Œ์–ด์˜ฌ๋ ค ๋‘ TemperatureInput ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋™๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

 

์ดˆ๊ธฐ ๊ตฌํ˜„ ์ฝ”๋“œ

 

function BoilingVerdict({ celsius }) {

  return celsius >= 100 ? <p>๋ฌผ์ด ๋“์–ด์š”!</p> : <p>๋ฌผ์ด ๋“์ง€ ์•Š์•„์š”.</p>;

}

 

function TemperatureInput({ scale, temperature, onTemperatureChange }) {

  const scaleNames = { c: "์„ญ์”จ", f: "ํ™”์”จ" };

 

  return (

    <fieldset>

      <legend>์˜จ๋„๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š” (๋‹จ์œ„: {scaleNames[scale]})</legend>

      <input

        value={temperature}

        onChange={(e) => onTemperatureChange(e.target.value)}

      />

    </fieldset>

  );

}

 

function Calculator() {

  const [temperature, setTemperature] = React.useState("");

  const [scale, setScale] = React.useState("c");

 

  const handleCelsiusChange = (temp) => {

    setScale("c");

    setTemperature(temp);

  };

 

  const handleFahrenheitChange = (temp) => {

    setScale("f");

    setTemperature(temp);

  };

 

  const tryConvert = (temp, convert) => {

    const input = parseFloat(temp);

    if (Number.isNaN(input)) return "";

    return (Math.round(convert(input) * 1000) / 1000).toString();

  };

 

  const celsius =

    scale === "f" ? tryConvert(temperature, (f) => ((f - 32) * 5) / 9) : temperature;

  const fahrenheit =

    scale === "c" ? tryConvert(temperature, (c) => (c * 9) / 5 + 32) : temperature;

 

  return (

    <div>

      <TemperatureInput

        scale="c"

        temperature={celsius}

        onTemperatureChange={handleCelsiusChange}

      />

      <TemperatureInput

        scale="f"

        temperature={fahrenheit}

        onTemperatureChange={handleFahrenheitChange}

      />

      <BoilingVerdict celsius={parseFloat(celsius)} />

    </div>

  );

}

 

๋™์ž‘ ๋ฐฉ์‹

Calculator์—์„œ ์ƒํƒœ(temperature, scale)๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์ƒํƒœ ๋ณ€๊ฒฝ ํ•ธ๋“ค๋Ÿฌ๋ฅผ props๋กœ ์ „๋‹ฌํ•˜์—ฌ TemperatureInput์ด ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

์ž…๋ ฅ๊ฐ’์€ ์„œ๋กœ ๋™๊ธฐํ™”๋˜๊ณ , BoilingVerdict๋Š” ์—…๋ฐ์ดํŠธ๋œ ์ƒํƒœ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ ์ ˆํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

 

์ƒํƒœ ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ์˜ ์žฅ๋‹จ์ 

 

โœ… ์žฅ์ 

1. ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ: ๊ณตํ†ต๋œ ์ƒํƒœ๋ฅผ ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ด€๋ฆฌํ•ด ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ ๊ฐ„์˜ ๋ฐ์ดํ„ฐ ๋ถˆ์ผ์น˜๋ฅผ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

2. ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„ ์œ ์ง€: React์˜ ํ•ต์‹ฌ ์ฒ ํ•™์ธ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ๋‹จ์ˆœํ•˜๊ณ  ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

3. ์œ ์ง€๋ณด์ˆ˜์„ฑ ์ฆ๊ฐ€: ์ƒํƒœ ๊ด€๋ฆฌ์™€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ํ•œ ๊ณณ์— ๋ชจ์ด๋ฏ€๋กœ ์ฝ”๋“œ๊ฐ€ ๋” ์ง๊ด€์ ์ž…๋‹ˆ๋‹ค.

 

โŒ ๋‹จ์ 

1. ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋น„๋Œ€ํ•ด์ง: ์ƒํƒœ์™€ ๋กœ์ง์ด ๋งŽ์•„์งˆ์ˆ˜๋ก ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. ์ค‘์ฒฉ๋œ ๊ตฌ์กฐ์—์„œ์˜ ์–ด๋ ค์›€: ์ƒํƒœ๋ฅผ ๋„ˆ๋ฌด ๋งŽ์ด ๋Œ์–ด์˜ฌ๋ฆฌ๋ฉด ๊นŠ๊ฒŒ ์ค‘์ฒฉ๋œ ์ปดํฌ๋„ŒํŠธ์—์„œ props๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ณผ์ •์ด ๊ธธ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ถ”๊ฐ€: Context์™€ ์ƒํƒœ ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ์˜ ์กฐํ™”

 

์ƒํƒœ ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ๋งŒ์œผ๋กœ๋Š” ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. React Context๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ „์—ญ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉด์„œ ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์˜ˆ์ œ: Context๋กœ ์ƒํƒœ ๊ณต์œ ํ•˜๊ธฐ

 

const TemperatureContext = React.createContext();

 

function TemperatureProvider({ children }) {

  const [temperature, setTemperature] = React.useState("");

  const [scale, setScale] = React.useState("c");

 

  const contextValue = {

    temperature,

    scale,

    setTemperature,

    setScale,

  };

 

  return (

    <TemperatureContext.Provider value={contextValue}>

      {children}

    </TemperatureContext.Provider>

  );

}

 

function TemperatureInputWithContext({ scale }) {

  const { temperature, scale: currentScale, setTemperature, setScale } =

    React.useContext(TemperatureContext);

 

  const handleChange = (temp) => {

    setScale(scale);

    setTemperature(temp);

  };

 

  const value =

    scale === "c"

      ? currentScale === "f"

        ? ((temperature - 32) * 5) / 9

        : temperature

      : currentScale === "c"

      ? temperature * 9 / 5 + 32

      : temperature;

 

  return (

    <fieldset>

      <legend>์˜จ๋„๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š” (๋‹จ์œ„: {scale === "c" ? "์„ญ์”จ" : "ํ™”์”จ"})</legend>

      <input

        value={value}

        onChange={(e) => handleChange(e.target.value)}

      />

    </fieldset>

  );

}

 

function App() {

  return (

    <TemperatureProvider>

      <TemperatureInputWithContext scale="c" />

      <TemperatureInputWithContext scale="f" />

    </TemperatureProvider>

  );

}

 

๊ฒฐ๋ก 

 

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

๊ฐ„๋‹จํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ์ƒํƒœ ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ๋งŒ์œผ๋กœ ์ถฉ๋ถ„ํ•˜์ง€๋งŒ,

Context API ๋˜๋Š” ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(e.g., Redux, Zustand)๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ๋ณต์žกํ•œ ์•ฑ์—์„œ๋„ ํšจ์œจ์ ์œผ๋กœ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๐ŸŒท์ „์„ค์˜ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์–ด๋ด…์‹œ๋‹น!๐ŸŒท

728x90
๋ฐ˜์‘ํ˜•