Atomic Design을 알아보자 (3): React/Next.js 실무 적용
이 글은 Atomic Design 시리즈 3편입니다.
Atomic Design은 개념으로 이해할 때보다 실제 프로젝트에 적용하려고 할 때 더 많은 질문이 생깁니다. 특히 React와 Next.js에서는 컴포넌트 구조뿐 아니라 폴더 구조, 디자인 시스템, Server Component와 Client Component 경계까지 함께 봐야 하기 때문입니다.
이번 글에서는 Atomic Design을 실무적으로 적용할 때 자주 고민하게 되는 지점을 정리해보겠습니다.
React 프로젝트에서는 보통 어떻게 나눌까?
Atomic Design을 React에 적용하면 보통 아래처럼 폴더 구조를 생각하게 됩니다.
src/
components/
atoms/
button.tsx
input.tsx
checkbox.tsx
molecules/
todo-input-form.tsx
todo-filter-tabs.tsx
todo-list-item.tsx
organisms/
todo-toolbar.tsx
todo-list.tsx
todo-summary.tsx
templates/
todo-page-template.tsx
pages/
todo-page.tsx이 구조의 장점은 명확합니다.
- 컴포넌트 크기와 책임을 한눈에 파악하기 쉬움
- 작은 UI 단위부터 큰 화면 단위까지 단계적으로 관리 가능
- 디자인 시스템과 화면 컴포넌트를 연결하기 쉬움
하지만 실제 프로젝트에서는 여기서 바로 한 가지 고민이 생깁니다. 모든 컴포넌트를 꼭 Atomic Design 단계에 맞춰 넣어야 할까? 라는 질문입니다.
모든 컴포넌트를 억지로 맞출 필요는 없다
Atomic Design은 기준을 주는 방식이지, 모든 컴포넌트에 꼬리표를 강제로 붙이는 규칙은 아닙니다.
예를 들면 아래 같은 경우는 경계가 애매할 수 있습니다.
TodoListItem을 molecule로 볼지 organism으로 볼지SearchBar를 molecule로 볼지 organism으로 볼지Header를 organism으로 볼지 template 일부로 볼지
이럴 때 중요한 것은 정답을 맞히는 것이 아니라:
- 팀이 같은 기준으로 판단하고 있는지
- 그 기준이 실제 유지보수에 도움이 되는지
입니다.
즉, Atomic Design은 분류 그 자체보다 컴포넌트 책임을 정리하는 과정에 더 의미가 있습니다.
디자인 시스템과는 어떻게 연결될까?
Atomic Design은 디자인 시스템과 자주 같이 언급됩니다. 두 개념이 완전히 같지는 않지만, 겹치는 지점이 많기 때문입니다.
보통은 아래처럼 연결됩니다.
atoms: 디자인 시스템의 기본 UI 자산molecules: 기본 UI 자산을 조합한 반복 패턴organisms: 실제 제품 화면에서 쓰이는 큰 블록
예를 들어:
Button,Input,Checkbox는 디자인 시스템에 가까운 atomSearchForm,SelectField는 조합형 moleculeHeader,Sidebar,TodoToolbar는 제품 UI에 가까운 organism
즉, 디자인 시스템이 재사용 가능한 UI 자산의 집합이라면, Atomic Design은 그것들을 어떤 단계로 조합할지 보는 관점이라고 생각하면 이해하기 쉽습니다.
Template와 Page는 어디까지 나눠야 할까?
실무에서 가장 애매한 단계 중 하나가 template와 page입니다.
Template
template은 레이아웃 구조를 설명하는 단계입니다.
- 헤더가 위에 있고
- 콘텐츠 영역이 가운데 있고
- 사이드 영역이 옆에 있고
- 어떤 순서로 배치되는지
를 설명합니다.
예시:
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>
);
}Page
page는 실제 데이터와 상태가 들어간 최종 화면입니다.
import { TodoPageTemplate } from './todo-page-template';
import { TodoList } from './todo-list';
import { TodoToolbar } from './todo-toolbar';
import { TodoSummary } from './todo-summary';
export function TodoPage() {
const todos = [
{ id: '1', title: 'Atomic Design 정리하기', completed: false },
{ id: '2', title: '실무 적용 글 쓰기', completed: true },
];
return (
<TodoPageTemplate
header={<h1 className="text-3xl font-bold">Todo List</h1>}
toolbar={<TodoToolbar />}
summary={<TodoSummary todos={todos} />}
list={<TodoList todos={todos} />}
/>
);
}정리하면:
Template: 구조와 배치Page: 실제 데이터와 상태가 들어간 결과
입니다.
Next.js에서는 어떻게 볼 수 있을까?
Next.js App Router를 쓰면 page.tsx라는 파일이 이미 존재하기 때문에, Atomic Design의 Page와 개념이 섞여 보일 수 있습니다.
이럴 때는 아래처럼 이해하는 편이 좋습니다.
- Next.js의
app/.../page.tsx는 프레임워크 엔트리 포인트 - Atomic Design의
Page는 실제 UI 결과물에 가까운 컴포넌트
예를 들면:
src/
app/
todos/
page.tsx
components/
templates/
todo-page-template.tsx
pages/
todo-page.tsx그리고 app/todos/page.tsx에서는 실제로 Atomic Design의 page 컴포넌트를 불러오는 방식으로 둘 수 있습니다.
import { TodoPage } from '@/components/pages/todo-page';
export default function Page() {
return <TodoPage />;
}이렇게 하면 프레임워크 파일과 UI 구조를 분리해서 볼 수 있습니다.
Server Component와 Client Component는 어떻게 함께 볼까?
Atomic Design은 컴포넌트의 역할과 크기를 설명하지만, Next.js App Router의 Server/Client 구분은 렌더링 위치를 설명합니다.
즉, 둘은 기준이 다릅니다.
예를 들어:
- atom이라고 해서 무조건 Client Component는 아님
- organism이라고 해서 무조건 Server Component는 아님
- 사용자 입력과 이벤트가 있으면
use client가 필요할 수 있음
예시:
Button,Input은 atom이지만 이벤트가 있으면 Client ComponentTodoSummary는 organism이지만 단순 출력이라면 Server Component 가능TodoPageTemplate은 template이지만 상태가 없으면 Server Component 가능
중요한 것은 Atomic Design 단계와 Server/Client 구분을 같은 축으로 생각하지 않는 것입니다.
Atomic Design의 한계
실무에서 Atomic Design만으로 구조를 설명하기 어려운 이유도 분명합니다.
1. 도메인과 기능 구조를 설명하지 못한다
Atomic Design은 UI 구조 중심이라, 사용자 행동이나 비즈니스 로직 경계를 나누는 데는 약합니다.
2. 경계가 애매한 컴포넌트가 많다
실제 프로젝트에서는 atom과 molecule, molecule과 organism 경계가 쉽게 흐려집니다.
3. 상태와 데이터 흐름 기준이 부족하다
컴포넌트 계층은 설명할 수 있지만, API, 상태, 도메인 로직을 어떻게 나눌지는 별도로 생각해야 합니다.
FSD와는 어떻게 다를까?
둘은 서로 대체 관계라기보다, 초점이 다릅니다.
Atomic Design
- UI 계층 구조에 집중
- 컴포넌트 크기와 조합 관계를 설명
- 디자인 시스템과 연결하기 좋음
FSD
- 도메인과 기능 구조에 집중
- 사용자 액션과 비즈니스 경계를 설명
- 프로젝트 전체 구조를 설명하기 좋음
즉, Atomic Design은 컴포넌트 관점, FSD는 기능/도메인 관점이라고 보면 이해가 쉽습니다.
언제 잘 맞을까?
다음과 같은 경우에 잘 맞습니다.
- 디자인 시스템을 운영하는 팀
- 재사용 가능한 UI 컴포넌트가 많은 프로젝트
- 화면 조합 구조를 명확하게 관리하고 싶은 경우
반대로 기능과 도메인 구조가 더 중요하고 복잡한 서비스에서는 Atomic Design만으로는 부족할 수 있습니다.
시리즈 다시 보기
마무리
Atomic Design을 React와 Next.js에 적용할 때 핵심은 단순합니다.
- 작은 UI 조각부터 큰 화면 구조까지 단계를 나눠 생각하고
- 프레임워크 엔트리 포인트와 실제 UI 구조를 구분하며
- 필요할 때만 기준으로 사용하고, 억지로 모든 컴포넌트를 끼워 맞추지 않는 것
이 기준만 있어도 컴포넌트 구조를 훨씬 더 일관되게 정리할 수 있습니다.
