Atomic Design을 알아보자 (1): 개념, 아키텍처, 5단계 구조

Frontend

컴포넌트가 많아지기 시작하면 비슷한 고민이 반복됩니다. 버튼은 어디까지 공용으로 빼야 하는지, 작은 UI 조각과 큰 화면 블록의 경계는 어디인지, 페이지 구조를 어떻게 정리해야 하는지 같은 질문들입니다.

이럴 때 자주 언급되는 방식이 Atomic Design입니다. 이름은 익숙하지만 실제로는 atom, molecule, organism, template, page를 어디까지 나눠야 하는지가 더 어렵게 느껴질 때가 많습니다.

이 글은 Atomic Design 시리즈 1편입니다. 먼저 개념과 5단계 구조를 짧게 정리합니다.

Atomic Design이란?

Atomic Design은 브래드 프로스트(Brad Frost)가 제안한 UI 설계 방식으로, 화면을 작은 단위부터 큰 단위까지 계층적으로 나누어 생각하는 방법입니다.

핵심은 단순합니다.

  • 작은 UI 조각부터 시작하고
  • 점점 더 큰 조합으로 확장하며
  • 최종적으로 하나의 페이지를 구성한다

즉, "컴포넌트를 어떻게 계층적으로 이해할 것인가?"에 대한 하나의 기준이라고 볼 수 있습니다.

왜 이런 구조가 필요할까?

프론트엔드 프로젝트가 커질수록 UI는 자연스럽게 복잡해집니다.

  • 버튼, 인풋, 배지 같은 작은 요소가 생기고
  • 검색창, 카드, 리스트 아이템 같은 조합이 생기고
  • 헤더, 사이드바, 폼 영역처럼 더 큰 화면 블록이 생기고
  • 결국 하나의 페이지가 만들어집니다

이 과정에서 기준이 없으면 이런 문제가 생깁니다.

  • 비슷한 컴포넌트가 여러 버전으로 생김
  • 공용 컴포넌트와 화면 전용 컴포넌트 경계가 흐려짐
  • 작은 컴포넌트와 큰 컴포넌트가 한 폴더에 섞임
  • 화면 구조를 이해하기 어려워짐

Atomic Design은 이런 상황에서 컴포넌트의 크기와 역할을 단계적으로 나눠보는 기준을 제공합니다.

Atomic Design의 5단계

Atomic Design은 보통 아래 다섯 단계로 설명합니다.

flowchart TD
    atoms[Atoms] --> molecules[Molecules]
    molecules --> organisms[Organisms]
    organisms --> templates[Templates]
    templates --> pages[Pages]

작은 단위에서 시작해 점점 더 큰 조합으로 올라간다고 생각하면 이해하기 쉽습니다.

1. Atoms

Atoms는 더 이상 쪼개기 어려운 가장 작은 UI 단위입니다.

예를 들면:

  • 버튼
  • 인풋
  • 라벨
  • 아이콘
  • 아바타
  • 체크박스

보통 atom은 다음 특징을 가집니다.

  • 하나의 역할만 수행함
  • 재사용성이 높음
  • 도메인 지식이 거의 없음
  • 스타일이나 상태 표현은 있을 수 있지만 큰 맥락은 모름

예시:

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: 'primary' | 'secondary';
}
 
export function Button({ variant = 'primary', className = '', ...props }: ButtonProps) {
  const baseClass = 'rounded px-4 py-2 text-sm font-medium';
  const variantClass =
    variant === 'primary' ? 'bg-blue-600 text-white' : 'bg-gray-100 text-gray-900';
 
  return <button className={`${baseClass} ${variantClass} ${className}`} {...props} />;
}

이 버튼은 특정 도메인을 모르고, 다양한 곳에서 재사용할 수 있으므로 atom에 가깝습니다.

2. Molecules

Molecules는 여러 atom이 합쳐진 작은 기능 단위입니다.

예를 들면:

  • 검색 인풋 + 버튼
  • 라벨 + 인풋
  • 체크박스 + 텍스트
  • 아바타 + 사용자 이름

중요한 점은 molecule이 단순히 "atom 여러 개를 붙인 것"이 아니라, 하나의 작은 의미를 가지는 조합이라는 것입니다.

예시:

import { Button } from './button';
import { Input } from './input';
 
interface SearchFormProps {
  keyword: string;
  onChange: (value: string) => void;
  onSubmit: () => void;
}
 
export function SearchForm({ keyword, onChange, onSubmit }: SearchFormProps) {
  return (
    <div className="flex gap-2">
      <Input value={keyword} onChange={(e) => onChange(e.target.value)} />
      <Button onClick={onSubmit}>검색</Button>
    </div>
  );
}

이 컴포넌트는 인풋과 버튼을 조합해 "검색 입력"이라는 작은 의미를 만듭니다.

3. Organisms

Organisms는 molecule과 atom이 더 크게 조합된 화면 블록입니다.

예를 들면:

  • 헤더
  • 상품 목록 영역
  • 댓글 리스트
  • 로그인 폼 섹션
  • Todo 리스트 영역

organism은 이미 화면 안에서 독립적인 영역처럼 느껴지는 경우가 많습니다.

예시:

import { SearchForm } from './search-form';
import { FilterTabs } from './filter-tabs';
 
export function TodoToolbar() {
  return (
    <section className="space-y-4">
      <SearchForm keyword="" onChange={() => {}} onSubmit={() => {}} />
      <FilterTabs />
    </section>
  );
}

여기서는 여러 molecule과 atom이 모여 하나의 의미 있는 화면 블록을 만듭니다.

4. Templates

Templates는 페이지의 레이아웃 구조를 정의하는 단계입니다.

보통 template은:

  • 화면 배치에 집중하고
  • 실제 데이터보다는 자리와 구조를 설명하며
  • organism들을 어떤 순서와 형태로 배치할지 결정합니다

예를 들면:

  • 블로그 상세 레이아웃
  • 리스트 페이지 레이아웃
  • 대시보드 레이아웃

예시:

interface TodoPageTemplateProps {
  header: React.ReactNode;
  toolbar: React.ReactNode;
  summary: React.ReactNode;
  list: React.ReactNode;
}
 
export function TodoPageTemplate({ header, toolbar, summary, list }: TodoPageTemplateProps) {
  return (
    <main className="mx-auto max-w-2xl space-y-6 py-10">
      {header}
      {toolbar}
      {summary}
      {list}
    </main>
  );
}

이 단계는 "어떤 컴포넌트를 보여주느냐"보다 "페이지를 어떤 구조로 배치하느냐"에 더 가깝습니다.

5. Pages

Pages는 실제 데이터와 상태가 들어가 최종 화면이 완성되는 단계입니다.

template 위에 실제 콘텐츠를 얹고, 사용자가 보는 완성된 페이지를 만든다고 생각하면 됩니다.

예를 들면:

  • 실제 Todo 데이터가 들어간 Todo 페이지
  • 실제 상품 데이터가 들어간 상품 목록 페이지
  • 실제 사용자 정보가 들어간 마이페이지

즉, template이 틀이라면 page는 실제 데이터가 채워진 결과물입니다.

Atomic Design을 어떻게 이해하면 좋을까?

처음 보면 단계가 많아서 딱딱하게 느껴질 수 있습니다. 하지만 아래처럼 보면 조금 더 쉽습니다.

  • Atom: 가장 작은 UI 조각
  • Molecule: 작은 의미를 가진 조합
  • Organism: 화면에서 독립적인 큰 블록
  • Template: 페이지 구조
  • Page: 실제 데이터가 들어간 최종 화면

중요한 것은 이름 자체보다 컴포넌트의 크기와 책임을 구분하려는 관점입니다.

장점

1. UI 구조가 계층적으로 보인다

작은 단위에서 큰 단위까지 올라가는 흐름이 생겨 화면 구조를 이해하기 쉬워집니다.

2. 재사용 포인트를 찾기 쉽다

어떤 컴포넌트가 atom인지 molecule인지 구분하면 재사용 범위를 판단하기 쉬워집니다.

3. 디자인 시스템과 잘 맞는다

특히 버튼, 인풋, 태그, 카드처럼 반복되는 UI가 많은 프로젝트에서 효과적입니다.

4. 협업할 때 공통 언어가 생긴다

"이건 molecule 같다", "이건 organism으로 봐야 한다" 같은 식의 대화가 가능해집니다.

한계도 있다

Atomic Design은 UI 구조를 설명하는 데는 강하지만, 도메인이나 기능 중심 구조를 설명하는 데는 부족할 수 있습니다.

예를 들어:

  • 사용자 행동을 기준으로 나누는 데는 약함
  • API, 상태, 비즈니스 로직 구조까지는 설명하지 못함
  • 규모가 커질수록 atom/molecule 경계가 애매해질 수 있음

즉, Atomic Design은 컴포넌트 구조를 보는 관점에는 좋지만, 프로젝트 전체 아키텍처를 단독으로 설명하는 도구는 아닙니다.

어떤 프로젝트에 잘 맞을까?

다음과 같은 경우에 특히 잘 맞습니다.

  • 디자인 시스템을 함께 운영하는 프로젝트
  • UI 컴포넌트 재사용성이 중요한 서비스
  • 화면 구성 요소가 반복적으로 등장하는 프로젝트
  • 컴포넌트 구조를 명확히 정리하고 싶은 팀

반대로 도메인 로직과 기능 구조가 더 복잡한 프로젝트에서는 Atomic Design만으로는 부족할 수 있습니다.

다음 글에서 이어서 볼 내용

개념만 보면 감이 잘 안 올 수 있습니다. 다음 글에서는 Todo 앱을 기준으로 Atomic Design을 실제로 어떻게 나눌 수 있는지 살펴보겠습니다.

마무리

Atomic Design은 컴포넌트를 잘게 나누자는 이야기가 아니라, 작은 UI 조각부터 큰 화면 구조까지 일관된 단계로 이해해보자는 방식에 가깝습니다.

중요한 것은 모든 컴포넌트를 억지로 atom, molecule, organism에 끼워 맞추는 것이 아니라, 지금 프로젝트에서 어떤 기준으로 컴포넌트 책임을 나눌지 정하는 데 활용하는 것입니다.