아토믹디자인 for React

리액트에서의 아토믹 디자인 도입기

yongholee
8 min readDec 22, 2019

이 글은 부스트캠프 2019 팀프로젝트에서 재사용 가능한 컴포넌트에 대한 고민을 하면서 도입하게 된 Atomic Design에 대해서 소개 및 회고를 하는 글입니다.
직접 Atomic Pattern을 적용해 본 프로젝트는 아래에서 참고하실 수 있습니다.
https://github.com/connect-foundation/2019-12

리액트 개발을 시작하면서, 재사용 가능한 컴포넌트는 많은 사람이 고민하는 것이었고 저희 팀 역시도 어떻게 다룰 것인가에 대해서 고민을 했습니다.
일반적으로, 개발을 진행하면서 중복이 되는 컴포넌트를 따로 분리하는 개발 방법이 있었는데 저희 팀에서는

처음부터 재사용 가능한 컴포넌트를 만들어보자!

라는 의견이 나왔고, 묻고 처음부터 재사용 가능성을 고려하면서 컴포넌트를 개발하는 전략을 세웠습니다. 그래서 재사용 가능한 방법에 대해 많이 고민하고 검색을 했고 Atomic Design이라는 개념을 학습하게 되었습니다. 이는 디자이너와 개발자간의 협업의 용이성을 위해서 고안되었다고 하나 저희는 충분히 개발자간의 협업에서도 조그마한 디자인 시스템을 갖춘다는 것은 협업할 때, 엄청난 장점으로 다가오리라 생각했습니다. 무엇보다도 컴포넌트 중심의 사고가 필요한 리액트와 잘 맞을 거라는 느낌이 들었습니다.

또한 아무런 디자인 시스템이 갖추어지지 않는다면 비슷해 보이는 컴포넌트이어도 각자 서로 다른 코드와 다른 스타일로 개발이 될 가능성이 농후해 추후 유지보수하는 게 비용이 많이 들 거라고 생각했습니다. 그래서 어느 정도의 시스템을 갖추기까지는 시간이 오래 걸리겠지만, 추후 가속도가 붙고 서로의 코드가 일관성을 갖출 수 있다는 기대감에 저희는 Atomic Design을 도입하여 우리만의 작은 디자인 시스템을 구축하기로 했습니다.

Atomic Design?

아토믹 디자인은 디자인 시스템을 만드는 데 여러 가지 방법론 중 하나입니다. 이름에서 유추할 수 있듯이 Atom(원자) 단위로 디자인 및 개발을 합니다. 저는 디자이너가 아닌 개발자이기 때문에 디자이너가 아니라 개발자의 관점에서 풀어나가겠습니다.

간단하게(?) 말해서, 원자가 결합하여 분자가 되고, 분자가 결합하여 유기체가 되는 것처럼, UI 컴포넌트 또한 가장 작은 단위로 쪼개고 합치며 UI를 마치 레고 블럭 쌓듯이 만들어나가는 방법입니다.

Atom -> Molecule -> Organism -> Template -> Page

Atomic Design in React

그렇다면 컴포넌트를 어떻게 나누고, 어떻게 결합하여 개발한다는 걸까요?
먼저, 컴포넌트 구조를 위의 그림의 순서대로 Atom -> Molecule -> Organism -> Template -> Page로 단위를 정합니다.

Atoms

가장 작은 단위의 컴포넌트를 의미합니다. 리액트에서는 Label, Input, CheckBox, Select 같은 HTML의 태그같이 기능적으로/의미론적으로 가장 작은 단위의 컴포넌트라고 할 수 있습니다.
앞으로 계속해서 재사용해나갈 컴포넌트이기 때문에 특정 기능을 수행하는 것이 아니라, 일반적으로 사용할 수 있도록 구현합니다. 예를 들어, input 태그의 onChange와 값이 어딘가에 종속되지 않도록 props로 전달받아 사용할 수 있도록 구현합니다.

Label Atom, Input Atom

Molecules

Atom을 여러 개 조합한 컴포넌트입니다. 예를 들어, Label + (Input | CheckBox | Select) 조합하여 FormItem이라는 컴포넌트를 만들어서 Atom 컴포넌트를 재사용할 수 있습니다.

FormInput (Label + Input)

Oraganisms

Molecule과 Atom들을 조합하여 컴포넌트를 만듭니다. 예를 들어, FormItem 여러 개와 버튼을 조합하여 SignUpForm을 만들 수 있습니다. Organism 또한 특정 기능을 직접적으로 수행하진 않지만, 특정한 Component들을 조합하다 보니 재사용성이 조금 떨어지게됩니다.

SignUpForm (4 FormInputs)

Templates

앞서 만든 컴포넌트들을 결합하기 전에 모호할 수도 있다고 느껴지지만, 단순하게 ‘레이아웃’을 그리고 컴포넌트를 주입받기 위해 준비하는 Template를 만들어야 합니다. 비즈니스 로직이 아니라, 완전히 스타일링에 집중한 단위입니다. 컴포넌트를 주입만 하면 바로 사용할 수 있도록 레이아웃을 그립니다.

Template

현재 페이지 구조가 단순하여 위와 같은 레이아웃으로 구성했지만, 실제로는 보다 더 다양한 레이아웃을 짤 수 있습니다.

Pages

해당 Template에 알맞은 컴포넌트를 주입하게 된다면, template에서 미리 만들어 놓은 레이아웃에 맞게끔 사용할 수 있도록 합니다. 컴포넌트를 주입함으로써 실제로 사용자가 보는 화면과 동일하여지도록 합니다. 따라서 전체적인 로직이나 상태 등을 Page 레벨에서 컨트롤해야 합니다. (이와 관련해서는 아래에서 더 자세히 설명하겠습니다.)

Template에 Component를 주입한 Page

위에서 구현한 Template에 미리 만들어놓은 Atom, Molecule, Organism을 주입함으로써 완성시킵니다. 이렇게 함으로써, UI와 비즈니스 로직/상태를 분리할 수 있어서 Page레벨에서는 해당 부분에 집중할 수 있는 장점이 있습니다.

State…

리액트에서 가장 중요한 것 중 하나는 상태 관리인데, 온전히 재사용 가능한 컴포넌트에서는 어떻게 해야 할 지에 대한 고민이 많았습니다. UI에 대한 재사용성은 너무 뛰어나고 편리하지만, 상태를 주입한다는 것은 컴포넌트를 상태에 종속시킨다는 말이기 때문에 상충하는 느낌이었습니다.

그래서 저희는, 각각 컴포넌트의 일반적인 상태 (disabled, focused 등)은 각 컴포넌트에서의 상태를 관리하되 직접적인 사용이 필요한 데이터에 대한 상태는 Page 레벨에서 주입하여 props로 내리는 방안을 선택했습니다.

전역으로 관리할 state를 제외하곤 각 page 별로 state를 관리했고, 해당 상태를 page -> organism -> molecule -> atom으로 props를 내려주는 방법을 선택했지만, 실질적으로 low level(atom)에서부터 general 하게 구현을 했기 때문에 크게 신경을 쓸 부분은 page뿐이었습니다. 다만, 주의를 해야 할 부분은 props를 전달, 전달하다 보니 의도치 않은 props를 내려줄 실수가 발생할 수 있는데 저희 팀에서는 typescript를 도입함으로써 props의 타입을 강제함으로써 그러한 이슈를 막았습니다.

So…

보시다시피 UI 컴포넌트에 대한 재사용성을 추구하니, 상태와 컴포넌트와 1:1 매칭을 시키기 어렵습니다. 그래서 상태에 대한 전반적인 부분을 모두 Page에서 관리하고 Props로 전달을 해주는 trade off가 있는 개발 방법론이라고 생각이 들었습니다. 하지만, 계속해서 컴포넌트를 만들어나가는 것보다는 충분히 더 생산적이었고 여러 명이 협업을 하는 코드임에도 불구하고 일관성이 있다는 것은 엄청난 메리트였습니다. (+ 코드리뷰) 처음부터 디자인 시스템을 갖추기는 어렵지만, 멀리 보는 프로젝트라면 느리더라도 디자인 시스템이 필수적이겠다는 생각을 했습니다.

재사용가능한 컴포넌트, 더 나은 협업을 위해서 즐겁게 고민해준 @dobest27 @FullOfOrange @doong-jo 모두 감사합니다.

직접 Atomic Pattern을 적용해 본 프로젝트는 아래에서 참고하실 수 있습니다.

References:

진짜 너무 많이 부족합니다. 발전적인 피드백은 언제나 감사드립니다.
댓글 또는 inwalter99@gmail.com

--

--