Front-end/Good Front

Compound Components๋ž€? ๐Ÿ’ก

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

Compound Components๋ž€? ๐Ÿ’ก

 

**Compound Components(์ปดํŒŒ์šด๋“œ ์ปดํฌ๋„ŒํŠธ)**๋Š” React์—์„œ ์œ ์—ฐํ•˜๊ณ  ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ UI ์ปดํฌ๋„ŒํŠธ๋ฅผ ์„ค๊ณ„ํ•˜๊ธฐ ์œ„ํ•œ ํŒจํ„ด์ด์—์š”. ์ด ํŒจํ„ด์„ ํ™œ์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์˜ ๊ด€๊ณ„๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๋‚˜ํƒ€๋‚ด๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ๋” ์ง๊ด€์ ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

 

์‰ฝ๊ฒŒ ๋งํ•ด, ์ปดํฌ๋„ŒํŠธ๋ฅผ “์ƒ์œ„-ํ•˜์œ„ ๊ด€๊ณ„”๋กœ ๋ฌถ์–ด์„œ ๋™์ž‘ํ•˜๋„๋ก ์„ค๊ณ„ํ•˜๋Š” ๊ฑฐ์˜ˆ์š”. ๊ทธ๋Ÿผ Compound Components์˜ ์ •์˜์™€ ์žฅ์ , ๊ทธ๋ฆฌ๊ณ  ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์•Œ์•„๋ณผ๊นŒ์š”? ๐Ÿ˜Š

 

Compound Components์˜ ์ •์˜

 

Compound Components๋Š” ์ปจํ…Œ์ด๋„ˆ ์ปดํฌ๋„ŒํŠธ์™€ ์—ฌ๋Ÿฌ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•จ๊ป˜ ๋™์ž‘ํ•˜๋„๋ก ์„ค๊ณ„๋œ ํŒจํ„ด์ด์—์š”.

์ปจํ…Œ์ด๋„ˆ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ , ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋Š” ์ด๋ฅผ ์ฐธ์กฐํ•ด ํ•„์š”ํ•œ UI์™€ ๋™์ž‘์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿ› ๏ธ ์‚ฌ์šฉ ์˜ˆ์‹œ: Tab ์ปดํฌ๋„ŒํŠธ

 

import React, { useState, createContext, useContext } from "react";

 

const TabContext = createContext();

 

const Tabs = ({ children }) => {

  const [activeTab, setActiveTab] = useState(0);

  return (

    <TabContext.Provider value={{ activeTab, setActiveTab }}>

      <div className="tabs">{children}</div>

    </TabContext.Provider>

  );

};

 

const TabList = ({ children }) => <div className="tab-list">{children}</div>;

 

const Tab = ({ children, index }) => {

  const { activeTab, setActiveTab } = useContext(TabContext);

  return (

    <button

      className={`tab ${activeTab === index ? "active" : ""}`}

      onClick={() => setActiveTab(index)}

    >

      {children}

    </button>

  );

};

 

const TabPanels = ({ children }) => {

  const { activeTab } = useContext(TabContext);

  return <div className="tab-panels">{children[activeTab]}</div>;

};

 

const TabPanel = ({ children }) => <div className="tab-panel">{children}</div>;

 

// ์‚ฌ์šฉ ์˜ˆ์‹œ

export default function App() {

  return (

    <Tabs>

      <TabList>

        <Tab index={0}>Tab 1</Tab>

        <Tab index={1}>Tab 2</Tab>

        <Tab index={2}>Tab 3</Tab>

      </TabList>

      <TabPanels>

        <TabPanel>Content 1</TabPanel>

        <TabPanel>Content 2</TabPanel>

        <TabPanel>Content 3</TabPanel>

      </TabPanels>

    </Tabs>

  );

}

 

๐Ÿ” ์ฝ”๋“œ ๋ถ„์„

1. Tabs: ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ ์ƒํƒœ(activeTab)๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋“ค์—๊ฒŒ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

2. TabList: ํƒญ ๋ฒ„ํŠผ๋“ค์„ ๊ทธ๋ฃนํ™”ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

3. Tab: ๊ฐœ๋ณ„ ํƒญ ๋ฒ„ํŠผ์œผ๋กœ, ํด๋ฆญํ•˜๋ฉด activeTab ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

4. TabPanels: ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ ํƒญ์˜ ์ฝ˜ํ…์ธ ๋ฅผ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.

5. TabPanel: ๊ฐ ํƒญ์˜ ์ฝ˜ํ…์ธ ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

 

์™œ Compound Components๋ฅผ ์‚ฌ์šฉํ• ๊นŒ?

 

1๏ธโƒฃ UI ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ๋ช…ํ™•ํžˆ ํ‘œํ˜„

 

Tabs, TabList, TabPanels ๊ฐ™์€ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์™€ ๋ฐ€์ ‘ํ•˜๊ฒŒ ์—ฐ๊ฒฐ๋œ ๊ด€๊ณ„์ž„์„ ์ฝ”๋“œ ๊ตฌ์กฐ์ƒ์œผ๋กœ ๋ช…ํ™•ํžˆ ๋“œ๋Ÿฌ๋‚ผ ์ˆ˜ ์žˆ์–ด์š”.

 

2๏ธโƒฃ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ๊ฐœ์„ 

 

์ปดํฌ๋„ŒํŠธ๋ฅผ ์„ ์–ธ์ ์œผ๋กœ ์ž‘์„ฑํ•˜๊ฒŒ ๋งŒ๋“ค์–ด ์‚ฌ์šฉ์ž(๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž) ์ž…์žฅ์—์„œ ์ง๊ด€์ ์ด๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

 

3๏ธโƒฃ ์œ ์—ฐ์„ฑ ์ฆ๊ฐ€

 

์‚ฌ์šฉ์ž๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž์œ ๋กญ๊ฒŒ ๊ตฌ์„ฑํ•˜๊ฑฐ๋‚˜ ์ˆœ์„œ๋ฅผ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์–ด ๋” ๋‹ค์–‘ํ•œ UI๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

Compound Components๋ฅผ ์„ค๊ณ„ํ•  ๋•Œ์˜ ํ•ต์‹ฌ ํฌ์ธํŠธ

 

1๏ธโƒฃ Context API ํ™œ์šฉ

 

์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ , Context๋ฅผ ํ†ตํ•ด ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ปดํฌ๋„ŒํŠธ ๊ฐ„ ๋ฐ์ดํ„ฐ ๊ณต์œ ๋ฅผ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

2๏ธโƒฃ Props.children ์‚ฌ์šฉ

 

React์˜ props.children์„ ํ™œ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜๋Š” ๋Œ€๋กœ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

3๏ธโƒฃ ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ„ ๊ฒฐํ•ฉ๋„ ๋‚ฎ์ถ”๊ธฐ

 

๊ฐ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅํ•˜๋„๋ก ์„ค๊ณ„ํ•˜์„ธ์š”. ์ด๋ฅผ ํ†ตํ•ด ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋†’์•„์ง‘๋‹ˆ๋‹ค.

 

Compound Components์˜ ํ™œ์šฉ ์‚ฌ๋ก€

 

๐ŸŒŸ 1. Accordion

 

<Accordion>

  <AccordionItem>

    <AccordionHeader>Header 1</AccordionHeader>

    <AccordionPanel>Content 1</AccordionPanel>

  </AccordionItem>

  <AccordionItem>

    <AccordionHeader>Header 2</AccordionHeader>

    <AccordionPanel>Content 2</AccordionPanel>

  </AccordionItem>

</Accordion>

 

๐ŸŒŸ 2. Form

 

<Form>

  <FormField label="Username">

    <Input type="text" />

  </FormField>

  <FormField label="Password">

    <Input type="password" />

  </FormField>

</Form>

 

Compound Components๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ฃผ์˜ํ•  ์ 

1. ๋ณต์žก๋„๋ฅผ ์กฐ์ ˆํ•˜์„ธ์š”

๋„ˆ๋ฌด ๋งŽ์€ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค๋ฉด ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์–ด์š”. ์ ์ ˆํ•œ ์ถ”์ƒํ™”๋ฅผ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

2. Context ์‚ฌ์šฉ ์‹œ ์ตœ์ ํ™” ํ•„์š”

Context ๊ฐ’์ด ์ž์ฃผ ๋ณ€๊ฒฝ๋˜๋ฉด ๋ชจ๋“  ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋  ์ˆ˜ ์žˆ์œผ๋‹ˆ React.memo์™€ ๊ฐ™์€ ์ตœ์ ํ™” ๊ธฐ๋ฒ•์„ ํ™œ์šฉํ•˜์„ธ์š”.

3. ๋ช…ํ™•ํ•œ ๋ฌธ์„œํ™”

Compound Components ํŒจํ„ด์€ ์„ค๊ณ„๊ฐ€ ๋ณต์žกํ•ด์งˆ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์œผ๋ฏ€๋กœ, ์‚ฌ์šฉ์ž(๊ฐœ๋ฐœ์ž)๋ฅผ ์œ„ํ•œ ๋ช…ํ™•ํ•œ ๋ฌธ์„œํ™”๊ฐ€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

 

๊ฒฐ๋ก 

 

Compound Components๋Š” UI ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ๋ช…ํ™•ํžˆ ํ•˜๊ณ , ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ•๋ ฅํ•œ ํŒจํ„ด์ด์—์š”. Context API, props.children, ๊ทธ๋ฆฌ๊ณ  React์˜ ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜ ์„ค๊ณ„ ์ฒ ํ•™์„ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ๋”์šฑ ์œ ์—ฐํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์‰ฌ์šด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

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

728x90
๋ฐ˜์‘ํ˜•