React Component Pattern

โœจ ๊ฐ•์€๋น„ยท2022๋…„ 6์›” 29์ผ
0

React

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

โš›๏ธ React Component Pattern

React๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž์œ ๋กญ๊ฒŒ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์งค ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋‹ค์–‘ํ•œ ํŒจํ„ด๋“ค์ด ์กด์žฌํ•œ๋‹ค. ๊ทธ ์ค‘์—์„œ ๋Œ€ํ‘œ์ ์ธ ์ปดํฌ๋„ŒํŠธ ํŒจํ„ด์„ ์•Œ์•„๋ณด์ž.

Presentational & Container Component

Container Component์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  Presentational Component์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ํŒจํ„ด์ด๋‹ค.

์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‚˜๋ˆ„๋Š” ์ด์œ ๊ฐ€ ๋ฌด์—‡์ผ๊นŒ?? ๐Ÿค”
ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ์— api ํ˜ธ์ถœ, ์ด๋ฒคํŠธ ํ•จ์ˆ˜, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง, ์ƒํƒœ๊ด€๋ฆฌ๊ฐ€ ๋ชจ๋‘ ๋‹ด๊ฒจ์žˆ์œผ๋ฉด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋น„๋Œ€ํ•ด์ ธ์„œ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ค์›Œ์ง„๋‹ค. ๊ทธ๋ž˜์„œ UI์™€ ๋กœ์ง์„ ๊ฐ๊ฐ Presentational Component์™€ Container Component๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ด€๋ฆฌํ•œ๋‹ค.

์˜ˆ์‹œ

// Before
// src/components/Login/LoginForm.js

const LoginForm = () => {
  const [form, setForm] = useState({
  	email: "",
    password: "",
  });
  
  const { email, password } = form;
  
  const onChange = (e) => {
  	const { name, value } = e.target;
    setForm({
      ...form,
      [name] : value,
    });
  }
  
  const onSubmit = (e) => {
  	e.preventDefault();
    console.log(form);
  }
  
  return (
  	<form onSubmit={onSubmit}>
      <div>
        <label>์ด๋ฉ”์ผ</label>
        <input type="text" value={email} name="email" onChange={onChange}/>
      </div>
      <div>
        <label>๋น„๋ฐ€๋ฒˆํ˜ธ</label>
        <input type="password" value={password} name="password" onChange={onChange}/>
      </div>
      <button type="submit">๋กœ๊ทธ์ธ</button>
    </form>
  );
}

export default LoginForm;
// After
// src/components/Login/LoginForm.container.js
const LoginFormContainer = () => {
  const [form, setForm] = useState({
  	email: "",
    password: "",
  });
  
  const { email, password } = form;
  
  const onChange = (e) => {
  	const { name, value } = e.target;
    setForm({
      ...form,
      [name] : value,
    });
  }
  
  const onSubmit = (e) => {
  	e.preventDefault();
    console.log(form);
  }
  
  return (
  	<LoginForm email={email} password={password} onChange={onChange} onSubmit={onSubmit}/>
  );
}

export default LoginFormContainer;
// src/components/Login/LoginForm.presenter.js

const LoginForm = ({ email, password, onChange, onSubmit }) => {
  return (
  	<form onSubmit={onSubmit}>
      <div>
        <label>์ด๋ฉ”์ผ</label>
        <input type="text" value={email} name="email" onChange={onChange}/>
      </div>
      <div>
        <label>๋น„๋ฐ€๋ฒˆํ˜ธ</label>
        <input type="password" value={password} name="password" onChange={onChange}/>
      </div>
      <button type="submit">๋กœ๊ทธ์ธ</button>
    </form>
  );
}

export default LoginForm;

Redux ์ฐฝ์‹œ์ž์ธ Dan Abramov๋Š” ๋” ์ด์ƒ ์ด ํŒจํ„ด์„ ์ด์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ํ–ˆ๋‹ค.
Component & Hooks ํŒจํ„ด์œผ๋กœ ๋Œ€์ฒด๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ณ , ์ด ํŒจํ„ด์€ UI๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋กœ์ง๊นŒ์ง€ ์žฌํ™œ์šฉ์ด ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
๐Ÿ‘‰ ์ฐธ๊ณ  - Presentational and Container Components


Component & Hooks

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

์˜ˆ์‹œ

// src/components/Login/LoginForm.js

const LoginForm = () => {
  const { form, onChange, onSubmit } = useLogin();
  const { email, password } = form;
  
  return (
  	<form onSubmit={onSubmit}>
      <div>
        <label>์ด๋ฉ”์ผ</label>
        <input type="text" value={email} name="email" onChange={onChange}/>
      </div>
      <div>
        <label>๋น„๋ฐ€๋ฒˆํ˜ธ</label>
        <input type="password" value={password} name="password" onChange={onChange}/>
      </div>
      <button type="submit">๋กœ๊ทธ์ธ</button>
    </form>
  );
}

export default LoginForm;
// src/components/Login/useLogin.js

const useLogin = () => {
  const [form, setForm] = useState({
  	email: "",
    password: "",
  });
  
  const { email, password } = form;
  
  const onChange = (e) => {
  	const { name, value } = e.target;
    setForm({
      ...form,
      [name] : value,
    });
  }
  
  const onSubmit = (e) => {
  	e.preventDefault();
    console.log(form);
  }
  
  return { form, onChange, onSubmit };
}

export default useLogin;

Atomic design pattern

๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ Atom ๋‹จ์œ„์—์„œ ์‹œ์ž‘ํ•˜์—ฌ ํ•˜๋‚˜์”ฉ ๊ฒฐํ•ฉํ•˜๋Š” ํŒจํ„ด์„ ๋งํ•œ๋‹ค.

  • UI ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋งค์šฐ ๋›ฐ์–ด๋‚˜ ๋น ๋ฅธ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ•˜์ง€๋งŒ ๋””์ž์ธ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ์ดˆ๊ธฐ ๋น„์šฉ์ด ๋งŽ์ด ๋“ค๊ณ , ๋กœ์ง๊ณผ ์ƒํƒœ๋“ค์ด page ๋‹จ์œ„์—์„œ props drilling์„ ํ†ตํ•ด ์ „๋‹ฌ๋œ๋‹ค.
  • ๋””์ž์ธ์ด ์™„์„ฑ๋˜์–ด ๋””์ž์ธ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•˜๊ธฐ ํŽธํ•˜๋‹ค๋ฉด, atomic design pattern์„ ์ž˜ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ธฐํš๊ณผ ๋””์ž์ธ์ด ์ž์ฃผ ๋ณ€๊ฒฝ๋˜๋‹ค๋ฉด ์‚ฌ์šฉํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

Atom
input, button๊ณผ ๊ฐ™์€ HTML ํƒœ๊ทธ๋‚˜ ์ตœ์†Œ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„ ๊ฐ€์žฅ ์ž‘์€ ๋‹จ์œ„์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งํ•œ๋‹ค.

Molecules

  • Atom๋“ค์ด ์ตœ์†Œ์˜ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ์กฐํ•ฉํ•œ ์ปดํฌ๋„ŒํŠธ
  • ex) ๋กœ๊ทธ์ธ ์ž…๋ ฅ์ฐฝ : input 2๊ฐœ + button 1๊ฐœ

Organisms

  • layout ๋‹จ์œ„๋กœ Molecules๊ณผ Atom์„ ์กฐํ•ฉํ•œ ์ปดํฌ๋„ŒํŠธ
  • ex) Header, Navigatioon, Footer ๋“ฑ

Templates

  • Organisms๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ํŽ˜์ด์ง€๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ
  • ํ•˜์ง€๋งŒ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด๊ฐ€์ง€ ์•Š๊ณ  ๋ฐ์ดํ„ฐ์˜ ํ๋ฆ„์ด๋‚˜ ๋ ˆ์ด์•„์›ƒ๋งŒ ๋ณด์—ฌ์ค€๋‹ค.
  • ๊ฐ์ฒด ์ง€ํ•ญ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ class์™€ ๋น„์Šทํ•˜๋‹ค.

Pages

  • Template์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์€ ์ปดํฌ๋„ŒํŠธ

๐Ÿ‘€ ๋ฆฌ์•กํŠธ์—๋Š” ๋‹ค์–‘ํ•œ ์ปดํฌ๋„ŒํŠธ ํŒจํ„ด์ด ์žˆ์ง€๋งŒ, ๊ทธ ์ค‘์—์„œ ์ •๋‹ต์€ ์—†๋‹ค. ๊ฐ๊ธฐ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ ํ™˜๊ฒฝ์— ๋งž๋Š” ์ปดํฌ๋„ŒํŠธ ํŒจํ„ด์„ ์„ ํƒํ•ด์•ผ ํ•˜๊ณ , ๋˜ํ•œ ํŒ€์›๋“ค์˜ ๊ฒฝํ—˜์„ ๊ณ ๋ คํ•˜์—ฌ ์ ํ•ฉํ•œ ์ปดํฌ๋„ŒํŠธ ํŒจํ„ด์„ ์„ ํƒํ•ด์•ผ ํ•œ๋‹ค!!

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