๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป dev

โš›๏ธ ๋ฆฌ์•กํŠธ ํŒจํ„ด : Compound Components (ํ•ฉ์„ฑ ์ปดํฌ๋„ŒํŠธ)

โš›๏ธ ๋ฆฌ์•กํŠธ๋กœ ๊ฐœ๋ฐœํ•˜๋‹ค ๋ณด๋ฉด state ๊ด€๋ฆฌ๋ฅผ ์ž˜ํ•˜๊ธฐ ์œ„ํ•ด ์ฃผ์˜๋ฅผ ๋งŽ์ด ํ•˜๊ณค ํ•œ๋‹ค.
๐Ÿ—๏ธ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ํƒ€๊ณ  ๋‚ด๋ ค ๊ฐ€๋ฉฐ ์‚ฌ์šฉ์ฒ˜๊นŒ์ง€ ํ”„๋กญ์Šค๋กœ ์ „๋‹ฌํ•ด์•ผ ํ•˜๋‹ค ๋ณด๋ฉด context api๋‚˜ ๋ฆฌ๋•์Šค ๋“ฑ์˜ ๋„๊ตฌ๋“ค๋„ ์ข…์ข… ํ™œ์šฉํ•˜๊ธฐ๋„ ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋ฐฉ๋ฒ•๋“ค์€ ์ฝ”๋“œ๋ฅผ ๋ณต์žกํ•˜๊ฒŒ ํ•˜๊ฑฐ๋‚˜ ์ข€ ๊ณผ๋„ํ•œ ์ ‘๊ทผ์ผ ๋•Œ๊ฐ€ ์žˆ๋‹ค.

๐Ÿ”… ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ฆฌ์•กํŠธ ์ž์ฒด์˜ ๊ธฐ๋Šฅ์œผ๋กœ๋„ ํ”„๋กญ์Šค ์ „๋‹ฌ์„ ํšจ์œจ์ ์œผ๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•๋“ค์ด ์žˆ๋Š”๋‹ค. ๋จผ์ € ์ปดํŒŒ์šด๋“œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ• ๋งŒํ•œ ๋ฌธ์ œ ์ƒํ™ฉ์ธ prop drilling๊ณผ ๋ฆฌ์•กํŠธ ๋‚ด๋ถ€์ ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•๋“ค์ธ context api์™€ ์ปดํŒŒ์šด๋“œ ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด์ž.

๐Ÿช› Prop drilling

"drilling"์ด๋ผ๋Š” ๋ง์—์„œ ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ๋“ฏ์ด ๋“œ๋ฆด๋กœ ๊ตฌ๋ฉ์„ ๋šซ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ์•„๋ฌด๋Ÿฐ ๊ด€๊ณ„๋„ ์—†๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉ์ฒ˜๊นŒ์ง€ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์ด์˜ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๋šซ๊ณ  ๊ฐˆ ๊ฒฝ์šฐ๋ฅผ prop drilling์ด๋ผ๊ณ  ํ•œ๋‹ค. ์ฆ‰, prop drilling ๋Š” ์ค‘์ฒฉ๋œ ์ปดํฌ๋„ŒํŠธ ๋ ˆ์ด์–ด๋“ค ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ณ„์† ์ „๋‹ฌํ•˜์—ฌ, ๊นŠ์ด ์ค‘์ฒฉ๋œ ์‚ฌ์šฉ์ฒ˜ ์ปดํฌ๋„ŒํŠธ๊นŒ์ง€ ์ „๋‹ฌํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์ผ์ปซ๋Š”๋‹ค. ์ด๋ ‡๊ฒŒ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•˜๋‹ค ๋ณด๋ฉด ์‚ฌ์šฉ์ฒ˜์— ๋„๋‹ฌํ•˜๊ธฐ๊นŒ์ง€ ๋ถˆํ•„์š”ํ•œ ์ค‘๊ฐ„ ๋‹จ๊ณ„ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๊ฑฐ์ณ๊ฐ€์•ผ ํ•œ๋‹ค.

 

์ข…์ข… ์ค‘์ฒฉ๋œ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๋‹ค๋ฃจ๋‹ค ๋ณด๋ฉด prop drilling์„ ๊ฒฝํ—˜ํ•ด ๋ดค์„ ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ drop down ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ ๋‹ค๊ณ  ํ•ด๋ณด์ž.

Solution 1 : Context API

Context API๋Š” context provider๋กœ ๊ฐ์‹ผ ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๋“ค ๊ฐ„์—  state๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.

useContext ํ›…์„ ํ†ตํ•ด ํ•ด๋‹น state๋‚˜ context์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

 

์œ„์˜ drop down ์ปดํฌ๋„ŒํŠธ๋ฅผ context api๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•œ๋ฒˆ ๋งŒ๋“ค์–ด๋ณด์ž.

  • DropDownContext.jsx : ๋“œ๋กญ๋‹ค์šด ์—ด๋ฆผ/๋‹ซํž˜ state ๊ด€๋ฆฌ
import React, { createContext, useContext, useState } from 'react';

// Create the context
const DropdownContext = createContext();

// Create a custom hook to use the DropdownContext
const useDropdown = () => {
  return useContext(DropdownContext);
};

// Create the provider component
const DropdownProvider = ({ children }) => {
  const [isOpen, setIsOpen] = useState(false);

  const toggleDropdown = () => {
    setIsOpen(prevState => !prevState);
  };

  const value = {
    isOpen,
    toggleDropdown,
  };

  return (
    <DropdownContext.Provider value={value}>
      {children}
    </DropdownContext.Provider>
  );
};

export { DropdownProvider, useDropdown };

 

  • DropDown.jsx : ๋“œ๋กญ๋‹ค์šด ์ „์ฒด๋ฅผ ๊ฐ์Œ€ ๋ฉ”์ธ ์ปดํฌ๋„ŒํŠธ
import React from 'react';

const Dropdown = ({ children }) => {
  return (
    <div className="dropdown">
      {children}
    </div>
  );
};

export default Dropdown;

 

  • DropdownItems.jsx : ๋“œ๋กญ๋‹ค์šด ์„ ํƒ ํ•ญ๋ชฉ๋“ค
import React from 'react';

const DropdownItems = () => {
  const items = ['Item 1', 'Item 2', 'Item 3'];

  return items.map(item => <p key={item}>{item}</p>);
};

export default DropdownItems;
  • DropdownMenu.jsx : ๋“œ๋กญ๋‹ค์šด ์—ด๋ฆผ/๋‹ซํž˜ ์— ๋”ฐ๋ผ ๋ณด์ผ ๋ฉ”๋‰ด
import React from 'react';
import { useDropdown } from './DropdownContext';

const DropdownMenu = ({ children }) => {
  const { isOpen } = useDropdown();

  return (
    isOpen ? (
      <div className="dropdown-menu">
        {children}
      </div>
    ) : null
  );
};

export default DropdownMenu;

 

  • DropdownToggle.jsx : ๋“œ๋กญ๋‹ค์šด ์—ด๋ฆผ/๋‹ซํž˜ ๋ฒ„ํŠผ
import React from 'react';
import { useDropdown } from './DropdownContext';

const DropdownToggle = ({ children }) => {
  const { toggleDropdown } = useDropdown();

  return (
    <button className="dropdown-toggle" onClick={toggleDropdown}>
      {children}
    </button>
  );
};

export default DropdownToggle;
  • App.jsx : ์‚ฌ์šฉ
import React from 'react';
import { DropdownProvider } from './DropdownContext';
import Dropdown from './Dropdown';
import DropdownToggle from './DropdownToggle';
import DropdownMenu from './DropdownMenu';
import DropdownItems from './DropdownItems';
const App = () => {
  return (
    <div className='App'>
      <DropdownProvider>
        <Dropdown>
          <DropdownToggle>Toggle Dropdown</DropdownToggle>
          <DropdownMenu>
            <DropdownItems />
          </DropdownMenu>
        </Dropdown>
      </DropdownProvider>
    </div>
  );
};
export default App;

 

contextAPI๋ฅผ ํ†ตํ•ด์„œ dropdown ์—ฌ๋‹ซ์Œ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. Prop drilling ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿ‘‰ react playground : https://playcode.io/1961630

 

contextAPI_dropdown_example

Try this online contextAPI_dropdown_example playground with instant live preview and console. Easy & Fast. Experiment yourself.

playcode.io


 

ํ•˜์ง€๋งŒ contextAPI๋กœ ์ž‘์„ฑํ–ˆ์„ ๋•Œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ์ ๋“ค์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.

1. ์„ฑ๋Šฅ ์ด์Šˆ : context value๋ฅผ ์—…๋ฐ์ดํŠธํ•  ๊ฒฝ์šฐ, ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋žœ๋”๋ง์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.
๋ฆฌ์•กํŠธ์—์„œ๋Š” ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ state ๋ณ€ํ™”๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋ฌด์กฐ๊ฑด ๋ฆฌ๋žœ๋”๋ง์ด ๋ฐœ์ƒํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ๊ณต์œ ํ•œ context๊ฐ€ app ์ „์ฒด์— ์“ฐ์ผ ๊ฒฝ์šฐ, ์—ฌ๊ธฐ์ €๊ธฐ์„œ ์œˆ์น˜ ์•Š์€ ๋ฆฌ๋žœ๋”๋ง์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

2. ํ…Œ์ŠคํŠธ ๋ณต์žก๋„ ์ฆ๊ฐ€ : ํ”„๋กญ์Šค ๊ธฐ๋ฐ˜์œผ๋กœ state ๊ด€๋ฆฌ๋ฅผ ํ•˜๋Š” ๊ฒฝ์šฐ๋ณด๋‹ค ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ธฐ๊ฐ€ ๊นŒ๋‹ค๋กญ๋‹ค. mock๋‚˜ ์ ์ ˆํ•œ context value๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€์ ์œผ๋กœ ์„ธํŒ…์„ ํ•ด์•ผ ํ•˜๊ณ  ์œ ๋‹› ํ…Œ์ŠคํŠธ ๊ณผ์ •์„ ๋” ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

3. ๋ฌด๋ถ„๋ณ„ํ•œ ๋‚จ์šฉ ๊ฐ€๋Šฅ์„ฑ ์ฆ๊ฐ€ : state๊ด€๋ฆฌ๊ฐ€ ๋„ˆ๋ฌด ์‰ฌ์›Œ์ง„๋‹ค๋Š” ์ƒ๊ฐ์— ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์˜ state๋ฅผ context API๋กœ ๊ณต์œ ํ•˜๋ฉด ๋˜์ง€ ์•Š๋ƒ ์‹ถ์„ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ปดํฌ๋„ŒํŠธ ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋„ˆ๋ฌด ๋†’์•„์ ธ์„œ ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ธฐ๋„ ์œ ์ง€ํ•˜๊ธฐ๋„ ์–ด๋ ค์›Œ์ง„๋‹ค. 
์œ„์˜ ๊ฒฝ์šฐ์—์„œ๋„ ํ•˜๋‚˜์˜ ๊ธฐ๋Šฅ์„ ์œ„ํ•ด ์ฝ”๋“œ ์—ฌ๊ธฐ์ €๊ธฐ๋ฅผ ๋„˜๋‚˜๋“ค์–ด์•ผ ํ•œ๋‹ค๋Š” ๋ถˆํŽธํ•จ์„ ๋Š๊ผˆ์„ ์ˆ˜๋„ ์žˆ๋‹ค.

4. ํƒ€์ž… ์•ˆ์ •์„ฑ ๊ฒฐ์—ฌ : Context value๋“ค์€ ๋””ํดํŠธ๋กœ ํƒ€์ž… ์ฒดํฌ๊ฐ€ ๋˜์ง€ ์•Š์•„์„œ ์ปดํŒŒ์ผ๋Ÿฌ๋‚˜ ๊ฐœ๋ฐœ ๋„๊ตฌ๋“ค์ด context value์˜ ํƒ€์ž…์ด ๋ถ€์ ์ ํ•˜๊ฒŒ ๋ณ€๊ฒฝ๋˜๊ฑฐ๋‚˜ ์‚ฌ์šฉ๋˜์–ด๋„ ๊ฐ์ง€ํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๋‹ค. 

5. ํ™•์žฅ์„ฑ ๊ฒฐ์—ฌ : ๊ทœ๋ชจ๊ฐ€ ์žˆ๋Š” ์„œ๋น„์Šค์˜ ๊ฒฝ์šฐ context api ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ๋‹ค. ์—ฌ๋Ÿฌ ์˜์กด์„ฑ๊ณผ context๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ณผ์ •์—์„œ ์ค‘๋ณต๊ณผ ์ผ๊ด€์„ฑ์„ ํ—ค์น˜๋Š” ์ผ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

6. ๊ฐœ๋ฐœ ๋„๊ตฌ์™€ ๋ฏธ๋“ค์›จ์–ด ๋ถ€์žฌ : ๋ฆฌ๋•์Šค์™€ ๊ฐ™์€ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋„๊ตฌ๋“ค๊ณผ๋Š” ๋‹ฌ๋ฆฌ context api ์ž์ฒด์ ์œผ๋กœ ๋””๋ฒ„๊น…์ด๋‚˜ ํ…Œ์ŠคํŠธ ๋“ฑ์„  ๋„์™€์ค„ ๋„๊ตฌ๋“ค์ด ์—†๋‹ค๋Š” ์ ์—์„œ ์•„์‰ฝ๋‹ค.

Solution 2 : Compound Components

Compound Component๋Š” ์—ด๊ฑฐ ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์•”๋ฌต์ ์ธ state๋ฅผ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๊ณต์œ ํ•˜๋„๋ก ์„ค๊ณ„ํ•˜๋Š” ๋ฆฌ์•กํŠธ ํŒจํ„ด์ด๋‹ค.

์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๋“ค ๊ฐ„์— ๊ฐ™์€ state๊ณผ ๋กœ์ง์„ ๊ณต์œ ํ•ด์•ผ ํ•  ๊ฒฝ์šฐ ์ด ํŒจํ„ด์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ,

์ด์ „ contextAPI๋กœ ์ž‘์„ฑํ–ˆ๋˜ ๋“œ๋กญ๋‹ค์šด ์ฝ”๋“œ๋ฅผ Compound Components๋กœ ๊ตฌํ˜„ํ•ด ๋ณด์ž.

 

  • Dropdown.jsx : ๋“œ๋กญ๋‹ค์šด ๊ด€๋ จ Compound Components
import React, { useState } from 'react';

// Dropdown component
const Dropdown = ({ children }) => {
  const [isOpen, setIsOpen] = useState(false);

  const toggleDropdown = () => {
    setIsOpen(prevState => !prevState);
  };

  return (
    <div className="dropdown">
      {children.map((child,index) => React.cloneElement(child,{ isOpen, toggleDropdown })
    )}
    </div>
  );
};

// DropdownToggle component
const DropdownToggle = ({ children, toggleDropdown }) => {
  return (
    <button className="dropdown-toggle" onClick={toggleDropdown}>
      {children}
    </button>
  );
};

// DropdownMenu component
const DropdownMenu = ({ children, isOpen }) => {
  return isOpen ? <div className="dropdown-menu">{children}</div> : null;
};

const DropdownItems = () => {
  const items = ['Item 1', 'Item 2', 'Item 3'];
  return items.map(item => <p key={item}>{item}</p>);
};

Dropdown.Toggle = DropdownToggle;
Dropdown.Menu = DropdownMenu;
Dropdown.Items = DropdownItems;

export default Dropdown;

 

โš ๏ธ ์‚ฌ์‹ค React.cloneElement ์‚ฌ์šฉ์€ ๊ถŒ์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.  ๋‹ค์Œ ์‹œ๊ฐ„์—๋Š” ๋Œ€์ฒดํ•˜์—ฌ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•๋“ค์„ ์‚ดํŽด๋ณด์ž.  
<div className="dropdown"> 
	{children.map((child,index) => React.cloneElement(child,{ isOpen, toggleDropdown }) )} 
</div>โ€‹

 

  • App.jsx : ์‚ฌ์šฉ
import React from 'react';
import Dropdown from './Dropdown';

export function App() {
  return (
    <div className='App'>
      <Dropdown>
      <Dropdown.Toggle>Toggle Dropdown</Dropdown.Toggle>
      <Dropdown.Menu>
        <Dropdown.Items/>
      </Dropdown.Menu>
    </Dropdown>
    </div>
  );
}

 

๐Ÿ‘‰ react playground : https://1961651.playcode.io

 

React Playground

Upgrade to Personal Prop plan to remove the introduction. The introduction appears once for every user.

1961651.playcode.io

 

์ด์ „ contextAPI๋ฅผ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ๋ณด๋‹ค ๊น”๋”ํ•˜๊ณ  ์ง๊ด€์ ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  Dropdown.Toggle์€ ํ† ๊ธ€ ๋ฒ„ํŠผ ๊ธฐ๋Šฅ๋งŒ, Dropdown.Menu๋Š” ์—ด๋ ธ์„ ๋•Œ๋งŒ ๋ฉ”๋‰ด๋“ค์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋Šฅ๋งŒ, Dropdown.Items๋Š” ์•„์ดํ…œ ๋‚˜์—ด ๊ธฐ๋Šฅ๋งŒ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ๊ฐ€ ์ž˜๋œ๋‹ค.

 

Compound Components๋ฅผ ์‚ฌ์šฉ ์‹œ ์žฅ์ ๋“ค๋กœ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

1. ์žฌ์‚ฌ์šฉ์„ฑ ์ฆ๊ฐ€ : Compound component ๋‚ด ๊ฐœ๋ณ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ฌ๋Ÿฌ ๊ตฐ๋ฐ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ฝ”๋“œ ๋ณต์žก๋„๋ฅผ ์ค„์ด๊ณ  ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์‰ฝ๋‹ค.

2. ์œ ์—ฐ์„ฑ ์ฆ๊ฐ€ : ํ”„๋กญ์Šค ์ „๋‹ฌ ๊ฑฑ์ •์„ ์ค„์ด๊ณ  ์ปค์Šคํ…€ ํ™”ํ•˜๊ณ  ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

3. ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ : Compound component์˜ ๊ฐ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋Š” ํ•˜๋‚˜์˜ ๊ธฐ๋Šฅ์„ ๋‹ด๋‹นํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ „์ฒด ์ฝ”๋“œ์— ์˜ํ–ฅ์„ ์ค„ ๊ฑฑ์ • ์—†์ด ์œ ์ง€๋ณด์ˆ˜๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค. 

4. ์ง๊ด€์  API  : ๊ฐ ๊ด€๋ จ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ฐ์‹ธ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๋™๋ฃŒ ๊ฐœ๋ฐœ์ž๋“ค ๋˜ํ•œ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ํŒจํ„ด์ด๋‹ค.

5. ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์— ์šฉ์ด : Compound component ํŒจํ„ด์€ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ํ™•์žฅํ•˜๊ธฐ ์‰ฝ๋„๋ก ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด, ์ด์ „์˜ Item์„ ๋ฐ”๊พธ๊ณ  ์‹ถ์„ ๋•Œ Dropdown.Items๋งŒ ๋ณ€๊ฒฝํ•ด ์ฃผ๋ฉด ๋œ๋‹ค. 

6. Prop Drilling ๊ฐ์†Œ : props๋ฅผ ํ†ตํ•ด state๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋Œ€์‹  ์—˜๋ฆฌ๋จผํŠธ๋“ค์„ ์ž์‹์œผ๋กœ ์ „๋‹ฌํ•œ๋‹ค.

7.  ์œ ์ง€๋ณด์ˆ˜ ์šฉ์ด : props๋ฅผ ์ถ”์ ํ•˜๋Š” ๊ณผ์ •๋„ ์ค„์ด๊ณ , state ๊ณต์œ  ๋ฐฉ์‹์ด ๋” ๋‹จ์ˆœํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋””๋ฒ„๊น…์ด ์‰ฌ์›Œ์ง„๋‹ค.

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

์˜ค๋Š˜์€ prop drilling์ด ์–ด๋–ค ๊ฑด์ง€, ๊ทธ๋ฆฌ๊ณ  ๋ฆฌ์•กํŠธ ๋‚ด๋ถ€์ ์ธ ๊ธฐ๋Šฅ๋“ค๋กœ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•๋“ค ์ค‘ contextAPI์™€ compound components pattern์— ๋Œ€ํ•ด ์‚ดํŽด๋ดค๋‹ค.
๋‹ค๋ฆ„์ด ์•„๋‹ˆ๋ผ vinylify ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๋ฉด์„œ compound components ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑธ ์ฒ˜์Œ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค. 
์˜์™ธ๋กœ ์ƒํƒœ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋“ค์—ฌ์˜จ๋‹ค๋˜๊ฐ€ ๋ณต์žกํ•œ ๋ฌด์–ธ๊ฐ€๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” ์ ์ ˆํ•œ ๋‚ด๋ถ€ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๊ฐ€๋Š” ์‹œ๊ฐ„์ด์—ˆ๋‹ค.
vinylify์—์„œ์˜ compound components ํ™œ์šฉ ๋Œ€ํ•ด์„œ๋Š” ํšŒ๊ณ  ๊ฒธ ๋‹ค์Œ ์‹œ๊ฐ„์— ๋‹ค๋ค„๋ณด๋„๋ก ํ•˜๊ฒ ๋‹ค.

๐Ÿ“š References

https://react.dev/reference/react/useContext

 

useContext – React

The library for web and native user interfaces

react.dev

 

https://medium.com/@vitorbritto/react-design-patterns-compound-component-pattern-ec247f491294

 

React Design Patterns: Compound Component Pattern

How to avoid prop drilling and write elegant components with implicit state sharing

medium.com