사라마라 프로젝트를 진행하면서 Container-Presentational과 비슷한(?) 패턴을 사용했습니다. "비슷한"이라는 의미는 컴포넌트의 설계와 정의가 명확하지 않다는 의미였습니다. 이는 프로젝트를 진행하면서도 새로운 팀원이 들어왔을 때, 프로젝트와 설계방법에 대해 전달하기도 힘들었으며, 새로운 컴포넌트를 제작할 때 기존의 설계방식을 따르기 어렵게 만들었습니다.
사라마라 프로젝트의 문제점
낮은 컴포넌트 재사용성
비슷해 보이는 컴포넌트더라도 사용하는 기능이 달랐기 때문에 재사용하기 힘들었습니다. 재사용성을 고려하며 컴포넌트를 설계하려고 노력했지만, 기능과 디자인이 결합된 컴포넌트를 재사용하기에는 쉽지 않았습니다. 특히, 사라마라 프로젝트에서 버튼의 label은 로고로 대체한 경우가 많았는데 이때, 각각의 로고를 모두 포함한 버튼 컴포넌트를 만들어야 했으며 이는 낮은 재사용성으로 이어졌습니다.
컴포넌트 설계 기준 미비
사라마라 프로젝트를 진행할 때, 많이 고민했던 것 중 하나는 프로젝트 폴더구조였습니다. 그 결과로 기능별(도메인별) 폴더구조로 공통컴포넌트와 기능컴포넌트를 구분하고 깔끔한 폴더구조를 계획했습니다. 또한, Container를 Layout으로, Presentational을 Components로 나누어 프로젝트를 진행했습니다. 지금 생각해 보면 네이밍에서도 흔히 사용하는 Layout과 전혀 다른 방법으로 Container를 명명해서 적절하지 않은 것 같지만, 당시에는 폴더 구조에 만족을 했습니다.
/src
|
+-- assets # 전체 프로젝트에서 사용해야할 이미지 (로고, 테스트 등)
|
+-- components # 모든 기능에서 사용하는 컴포넌트
|
+-- features # 각각의 기능 / 도메인 별로 분리
|
+-- hooks # 커스텀 훅
|
+-- lib # 라이브러리 수정 및 관리
|
+-- stores # 전역 state 관리
/src/feature/SomeDomain
|
+-- api # 특정 도메인에서 사용하는 api
|
+-- assets # 도메인에서만 활용하는 asset
|
+-- components # 도메인에서 사용되는 컴포넌트
|
+-- layouts # components 를 가지는 집합 components에 사용될 state는 layout에서 props로 전달
|
+-- hooks # 훅
|
+-- routes # 중첩 라우팅시 사용
|
+-- stores # 전역 state
|
+-- index.ts # 페이지
하지만 한 도메인의 기능과 컴포넌트가 늘어나면서 문제가 발생했습니다. 한 도메인에서 컴포넌트와 레이아웃의 파일이 많아지며, 가독성은 떨어졌습니다. 또한, 명확한 기준이 없었기 때문에 새로운 컴포넌트를 개발할 때마다 컴포넌트 설계에 대한 고민이 필요했고 결과적으로 성격이 다른 컴포넌트들 끼리 묶여있게 되었습니다.
저는 이러한 문제를 해결 하기 위해 디자인 시스템을 도입하기로 결정했습니다. 그 과정에서 컴포넌트의 기준을 명확히 구분하고, 각 컴포넌트의 의존성을 줄여 재사용을 줄일 필요가 있었습니다. 또한 Container와 Presentational의 구분은 유지하여 기존의 이용하던 Storybook을 꾸준히 사용해야 했습니다. 그리고, 이러한 이유로 Atomic Design Pattern을 도입을 시도하게 됐습니다.
아토믹 디자인 패턴이란 세상에 존재하는 모든 물체들을 쪼갠다면 결국 한정된 원자로 나누어 진다는 진리가 사실은 모든 컴포넌트를 나눈다면 HTML태그로 쪼개지는 웹 인터페이스와 일치한다는 데에서 나온 방법론입니다.
아래는 아토믹 디자인 패턴에 대해 소개한 bradfrost의 아토믹 디자인을 읽고 정리한 내용입니다.
Atomic Design Pattern 이란?
아토믹 디자인 패턴은 이러한 작동원리를 활용하여 5개의 단계로 구분했습니다. 하지만, 주의해야 할 점은 선형적인 프로세스보다 사용자 인터페이스를 각각의 집합이나, 그 하나의 전체로 봐야 한다는 점입니다.
Atoms
- Atoms은 가장 기초적인 인터페이스로 버튼, 라벨 등 더 이상 분해될 수 없는 요소들을 의미
- Atom의 가장 큰 특징으로는 하나의 유니크한 특성을 가진다는 점입니다.
Molecules
- 화학으로 치면, 수소와 산소가 만나서 물이 되는 것처럼 여러 개의 Atom들이 뭉쳐 새로운 특성을 가지는 것
라벨과, 인풋, 버튼이 합쳐져서 만들어진 폼이 있습니다. 각각의 역할을 하던 atoms들이 합쳐져서 새로운 기능을 하는 from을 만들 수 있습니다. 이러한 특성은 단일 책임원칙과 일맥상통한다고 볼 수 있습니다.
Organisms
- 상대적으로 복잡한 UI를 의미합니다.
- 헤더, 푸터를 예시로 들 수 있으며, 하나의 섹션에서 독립적으로 실행되는 컴포넌트를 의미합니다.
사실 아토믹 디자인 패턴을 도입하는 글을 보면, Molecules와 Organisms의 차이가 모호하다는 글이 많았습니다. 저는 이 글을 보며 Organisms는 페이지에서 하나의 부분을 담당하는 (Section)으로 이해했습니다.
Templates
- 컴포넌트를 다루는 Page급의 구조
- 템플릿의 중요한 점은 page에서 콘텐츠를 다룬다면, 템플릿에서는 그 아래의 구조를 다룬다는 점입니다.
Page
- 아토믹 디자인 패턴의 마지막 부분이며 유저가 볼 수 있는 실제 콘텐츠를 담고 있습니다
- 즉 페이지에서는 다양한 템플릿의 변형이 일어날 수 있습니다
- 의도치 않은 많은 글자수
- 장바구니의 상품 개수 등
Atomic Design의 장점
부분과 전체
각각의 부분이 전체를 이룬다는 점에서 추상화와 구체화를 빠르게 할 수 있다는 점입니다. 각각의 요소들이 어떻게 결합하여 페이지가 되는지 눈에 보이기 때문에 유지보수의 장점을 줄 수 있습니다.
뷰와 콘텐츠의 분리
template와 page를 통해 구조와 콘텐츠를 분리하고, 이를 통해 UI와 콘텐츠에 대한 이점을 줄 수 있습니다.
이러한 아토믹 디자인 패턴을 도입한다면, 뷰와 콘텐츠의 분리라는 이점을 가져가면서 조금 더 구조화된 컴포넌트 설계를 가질 수 있을 거라 생각했습니다.
Atomic Design Pattern에 대한 고민
하지만, 컴포넌트를 5가지로 나누어야 한다는 점. Page에서 콘텐츠를 다룬다면 필연적으로 Props Drilling이 발생한다는 점은 Atomic Design Pattern을 도입하는데 고민하게 했습니다.
이에, 프로젝트에 도입하기 전 다양한 테크 기업에서 Atomic Design 패턴을 도입한 글을 찾아보았습니다.
Teo님의 블로그
Teo님의 글을 읽으면서 Atomic Design Pattern에 대해 배울 수 있었습니다. Teo님은 moecules와 organisms의 모호성과 데이터 바인딩에 대해 고민한 내용을 볼 수 있었습니다. 프로젝트의 폴더구조부터 시작하여, 비즈니스로직과 뷰 로직의 분리로 해당 내용들을 해결하였습니다.
카카오 엔터 FE블로그
카카오엔터에서도 Molecule와 Organism을 나누는 기준에 대해 고민했으며, Organism의 하나의 특성이 추가될 때의 Props의 증가에 대해 고민했습니다. 아래와 같은 부분은 React의 Compound 컴포넌트로 해결하는 모습이 인상 깊었습니다.
kciter님의 블로그
Kciter님의 블로그에서는 대략 7가지로 아토믹 디자인 패턴을 도입하며 고민했던 내용을 정리해 놓으셨다.
인상 깊었던 내용을 정리하자면,
- Organism과 Molecule의 구분
- Organism은 하나의 역할, Molecule은 사용자에게 의미를 가지는 기능적 요소로 나누었다.
- 기능적인 관점에서 두 컴포넌트를 분리했다는 내용이 인상 깊었습니다
- Wrapper 컴포넌트를 활용한 Props Drilling관리
- Page에서 모든 데이터를 관리할 경우 책임이 커지고, Props Drilling도 발생할 수 있습니다.
- Kciter님의 블로그에서는 이러한 문제를 해결하기 위해 Wrapped 컴포넌트를 두어 데이터를 관리하였습니다
'개발' 카테고리의 다른 글
CORS (0) | 2023.12.06 |
---|---|
[SaraMara] 아토믹 디자인 도입하기 (2) (0) | 2023.11.29 |
Github Action + NCP + Nginx로 간단 CI / CD 구성하기 (0) | 2023.07.11 |
[Nginx] 비-www URL을 www URL로 redirect (0) | 2023.07.08 |
React 성능 개선 (LazyLoading, 이미지 최적화) (0) | 2023.07.06 |