[React] React Hook, Webpack

yeonddoriยท2023๋…„ 9์›” 13์ผ
0

AID_WEB

๋ชฉ๋ก ๋ณด๊ธฐ
6/10

๐Ÿ“ React Hook

React์—์„œ ๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ Class๋ฅผ ์ด์šฉํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ํ•„์š” ์—†์ด,
state์™€ ์—ฌ๋Ÿฌ React ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.

ํ•„์š”์„ฑ

  • ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋„ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์ฒ˜๋Ÿผ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ชจ๋“ˆ๋กœ ํ™œ์šฉ ๊ฐ€๋Šฅ

useState

useState๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ Hook๋กœ, ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ ๊ฐ€๋ณ€์ ์ธ ์ƒํƒœ๋ฅผ ์ง€๋‹ˆ๊ณ  ์žˆ์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค. ๋งŒ์•ฝ์— ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•ด์•ผ ๋˜๋Š” ์ผ์ด ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ์ด Hook์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

import React, { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useEffect

useEffect๋Š” ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋  ๋•Œ๋งˆ๋‹ค ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์„ค์ • ํ•  ์ˆ˜ ์žˆ๋Š” Hook์ด๋‹ค.

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useContext

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

const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee"
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222"
  }
};

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

function App() {
  return (
    <ThemeContext.Provider value={themes.dark}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return (
    <button style={{ background: theme.background, color: theme.foreground }}>
      I am styled by theme context!
    </button>
  );
}

useRef

useRef๋Š” ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ ref๋ฅผ ์‰ฝ๊ฒŒ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค. .current ํ”„๋กœํผํ‹ฐ๋กœ ์ „๋‹ฌ๋œ ์ธ์ž(initialValue)๋กœ ์ดˆ๊ธฐํ™”๋œ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ref ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์ „ ์ƒ์• ์ฃผ๊ธฐ๋ฅผ ํ†ตํ•ด ์œ ์ง€๋œ๋‹ค.

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

์ถ”๊ฐ€ Hooks

๊ณต์‹๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด ์œ„์˜ Hook ๋‚ด์šฉ ์™ธ์˜ ๋‹ค๋ฅธ Hook ์ •๋ณด๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ ์ง์ ‘ Hook์„ ์ œ์ž‘ํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๋งŒ๋“  Hook์„ ๊ฐ€์ ธ๋‹ค ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

๐Ÿ“ Webpack

Webpack์€ ๋ชจ๋˜ JavaScript ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•œ ์ •์  ๋ชจ๋“ˆ ๋ฒˆ๋“ค๋Ÿฌ ์ด๋‹ค. ๊ฐ„๋‹จํ•˜๊ฒŒ ํ‘œํ˜„ํ•˜์ž๋ฉด ์—ฌ๋Ÿฌ ํŒŒ์ผ์„ ํ•˜๋‚˜ ์ด์ƒ์˜ ํŒŒ์ผ๋กœ ํ•ฉ์ณ์ฃผ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฒˆ๋“ค๋Ÿฌ๋กœ, webpack.config.js์—์„œ ์†์„ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ชจ๋“ˆ ๋ฒˆ๋“ค๋Ÿฌ
์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์„ฑํ•˜๋Š” ์ž์›(HTML, CSS, Javscript, Images ๋“ฑ)์„ ๋ชจ๋‘ ๊ฐ๊ฐ์˜ ๋ชจ๋“ˆ๋กœ ๋ณด๊ณ  ์ด๋ฅผ ์กฐํ•ฉํ•ด์„œ ๋ณ‘ํ•ฉ๋œ ํ•˜๋‚˜์˜ ๊ฒฐ๊ณผ๋ฌผ์„ ๋งŒ๋“œ๋Š” ๋„๊ตฌ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

ํ•ต์‹ฌ ์š”์†Œ

  1. Entry
    Webpack์ด ๋‚ด๋ถ€์˜ Dependency Graph๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๋ชจ๋“ˆ์ด๋‹ค. Webpack์€ entry๊ฐ€ ์˜์กดํ•˜๋Š” ๋‹ค๋ฅธ ๋ชจ๋“ˆ๊ณผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฐพ์•„๋‚ธ๋‹ค.
    ๊ธฐ๋ณธ๊ฐ’์€ ./src/index.js์ด์ง€๋งŒ, webpack ์„ค์ •์—์„œ entry ์†์„ฑ์„ ์„ค์ •ํ•˜์—ฌ ๋‹ค๋ฅธ entry๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
module.exports = {
  entry: './path/to/my/entry/file.js',
};

  1. Output
    Output ์†์„ฑ์€ ์ƒ์„ฑ๋œ ๋ฒˆ๋“ค์„ ๋‚ด๋ณด๋‚ผ ์œ„์น˜์™€ ์ด ํŒŒ์ผ์˜ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ webpack์— ์•Œ๋ ค์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
    ๊ธฐ๋ณธ ์ถœ๋ ฅ ํŒŒ์ผ์˜ ๊ฒฝ์šฐ์—๋Š” ./dist/main.js๋กœ, ์ƒ์„ฑ๋œ ๊ธฐํƒ€ ํŒŒ์ผ์˜ ๊ฒฝ์šฐ์—๋Š” ./dist ํด๋”๋กœ ์„ค์ •๋œ๋‹ค.
const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js',
  },
};

  1. Loaders
    Webpack์€ ๊ธฐ๋ณธ์ ์œผ๋กœ JavaScript์™€ JSON ํŒŒ์ผ๋งŒ ์ดํ•ดํ•˜๊ธฐ์— ์ด์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด webpack์ด ๋‹ค๋ฅธ ์œ ํ˜•์˜ ํŒŒ์ผ์„ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜, ๊ทธ๋“ค์„ ์œ ํšจํ•œ ๋ชจ๋“ˆ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ Dependency Graph์— ์ถ”๊ฐ€ํ•œ๋‹ค.

    ์ƒ์œ„ ์ˆ˜์ค€์—์„œ ๋กœ๋”๋Š” webpack ์„ค์ •์— ๋‘ ๊ฐ€์ง€ ์†์„ฑ์„ ๊ฐ€์ง„๋‹ค.

    1. ๋ณ€ํ™˜์ด ํ•„์š”ํ•œ ํŒŒ์ผ์„ ์‹๋ณ„ํ•˜๋Š” test ์†์„ฑ
    2. ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๋กœ๋”๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” use ์†์„ฑ
const path = require('path');

module.exports = {
  output: {
    filename: 'my-first-webpack.bundle.js',
  },
  module: {
    rules: [{ test: /\.txt$/, use: 'raw-loader' }],
  },
};

  1. Plugins
    ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํ™œ์šฉํ•˜์—ฌ ๋ฒˆ๋“ค์„ ์ตœ์ ํ™”ํ•˜๊ฑฐ๋‚˜ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์ฃผ์ž… ๋“ฑ๊ณผ ๊ฐ™์€ ๊ด‘๋ฒ”์œ„ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ๋‹ค.
    ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด require()๋ฅผ ํ†ตํ•ด ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์š”์ฒญํ•˜๊ณ  plugins ๋ฐฐ์—ด์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์˜ต์…˜์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๊ณ , ๋‹ค๋ฅธ ๋ชฉ์ ์œผ๋กœ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ new ์—ฐ์‚ฐ์ž๋กœ ํ˜ธ์ถœํ•˜์—ฌ ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); // ๋‚ด์žฅ plugin์— ์ ‘๊ทผํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ

module.exports = {
  module: {
    rules: [{ test: /\.txt$/, use: 'raw-loader' }],
  },
  plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
};

  1. Mode
    mode๋ฅผ development, production ๋˜๋Š” none์œผ๋กœ ์„ค์ •ํ•˜๋ฉด webpack์— ๋‚ด์žฅ๋œ ํ™˜๊ฒฝ๋ณ„ ์ตœ์ ํ™”๋ฅผ ํ™œ์„ฑํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.
    ๊ธฐ๋ณธ๊ฐ’์€ production์ด๋‹ค.
module.exports = {
  mode: 'production',
};

  1. Browser Compatibility
    Webpack์€ ES5๊ฐ€ ํ˜ธํ™˜๋˜๋Š” ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์ง€์›ํ•œ๋‹ค(๋‹จ, IE8 ์ดํ•˜๋Š” ์ง€์›๋˜์ง€ ์•Š๋Š”๋‹ค). ๊ตฌํ˜• ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์ง€์›ํ•˜๋ ค๋ฉด ์ด๋Ÿฌํ•œ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ํด๋ฆฌํ•„์„ ๋กœ๋“œํ•ด์•ผ ํ•œ๋‹ค.
module.exports = {
  entry: {
    'main': './src/index.js',
    'polyfills': './src/polyfills/index.js',
    'detect.polyfills': './src/polyfills/detect.js'
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: '[name].js'
  },
  // ...
}

๐Ÿช„ ๋งˆ์น˜๋ฉด์„œ

์•„์ง webpack dev server๋ฅผ ํ•ซ๋กœ๋”ฉํ•  ๋•Œ์™€ npm start๋กœ ๊ฐœ๋ฐœํ•  ๋•Œ์˜ ์ฐจ์ด์ ์„ ์ž˜ ๋ชจ๋ฅด๊ฒ ๋‹ค. ๋‘˜์ด ์„œ๋กœ ์—ฐ๊ด€์ด ๋˜์–ด์žˆ์ง€ ์•Š์•„์„œ webpack์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ํ•ซ๋กœ๋”ฉ์ด ํ•„์ˆ˜์ธ์ง€ ๋” ์•Œ์•„๋ด์•ผ ํ•  ๊ฒƒ ๊ฐ™๋‹ค.

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