
Atomic Design은 컴포넌트를 작은 단위(원자) 부터 시작해 점점 큰 단위(조직/페이지)로 조립하는 UI 설계 방법론 이다.
복잡한 UI를 계층적이고 체계적으로 구성할 수 있게 도와준다.
“작은 컴포넌트를 먼저 만들고, 이걸 조립해서 점점 큰 컴포넌트를 만든다” 이다.
| 단계 | 설명 | React 예시 |
|---|---|---|
| Atoms (원자) | 가장 작은 단위, 쪼개질 수 없음 | Button, Input, Label, Icon |
| Molecules (분자) | 원자들이 모여 기능을 수행 | Input + Label 조합, SearchBar |
| Organisms (유기체) | 여러 분자가 모여 완성된 UI 블록 | Header, Card, Sidebar |
| Templates (템플릿) | 유기체를 배치해 페이지 구조 형성 | 상품 리스트 템플릿, 대시보드 뷰 템플릿 |
| Pages (페이지) | 실제 데이터와 연결된 완성 페이지 | ProductDetailPage, MyProfilePage |
프로젝트 구조 예시
/src
/components
/atoms
Button.tsx
Input.tsx
Label.tsx
/molecules
InputWithLabel.tsx
SearchBar.tsx
/organisms
Header.tsx
Footer.tsx
ProductCard.tsx
/templates
ProductListTemplate.tsx
/pages
ProductListPage.tsx
1. Atoms (원자)
// components/atoms/Button.tsx
import React from 'react';
export const Button = ({ children, onClick }: { children: React.ReactNode; onClick: () => void }) => {
return (
<button onClick={onClick} className="px-4 py-2 bg-blue-500 text-white rounded">
{children}
</button>
);
};
👉 작고 독립적인 버튼 하나. (이 자체로 의미를 가짐)
2. Molecules (분자)
// components/molecules/SearchBar.tsx
import React from 'react';
import { Input } from '../atoms/Input';
import { Button } from '../atoms/Button';
export const SearchBar = ({ onSearch }: { onSearch: (query: string) => void }) => {
const [query, setQuery] = React.useState("");
return (
<div className="flex space-x-2">
<Input value={query} onChange={(e) => setQuery(e.target.value)} />
<Button onClick={() => onSearch(query)}>Search</Button>
</div>
);
};
👉 Input + Button 조합 = 새로운 기능(검색)을 가짐.
3. Organisms (유기체)
// components/organisms/Header.tsx
import React from 'react';
import { SearchBar } from '../molecules/SearchBar';
export const Header = () => {
return (
<header className="flex items-center justify-between p-4 bg-gray-100">
<h1 className="text-xl font-bold">WeKick</h1>
<SearchBar onSearch={(query) => console.log("Searching for", query)} />
</header>
);
};
👉 여러 분자들(SearchBar 등)이 모여서 하나의 UI 블록(헤더)이 됨.
4. Templates (템플릿)
// components/templates/ProductListTemplate.tsx
import React from 'react';
import { ProductCard } from '../organisms/ProductCard';
export const ProductListTemplate = ({ products }: { products: Product[] }) => {
return (
<div className="grid grid-cols-2 gap-4">
{products.map((product) => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
};
👉 페이지 레이아웃 구조를 담당. 데이터는 아직 들어오지 않았음.
5. Pages (페이지)
// components/pages/ProductListPage.tsx
import React from 'react';
import { ProductListTemplate } from '../templates/ProductListTemplate';
import { productsMock } from '../../mocks/productsMock';
export const ProductListPage = () => {
return <ProductListTemplate products={productsMock} />;
};
👉 템플릿에 진짜 데이터를 주입해서 완성된 페이지.
| 장점 | 설명 |
|---|---|
| 재사용성 | 작은 컴포넌트 단위로 쪼개면, 어디서든 쉽게 재사용 가능 |
| 유지보수성 | 기능 추가/수정할 때 전체 구조를 깨지 않고 부분만 수정 가능 |
| 명확한 계층 | 프로젝트 구조가 명확해져 협업/리팩토링 시 유리 |
| 스케일 확장 | 서비스가 커져도 관리 가능한 컴포넌트 시스템 유지 |