와플카드 서비스 컴포넌트 구조 (feet. 아토믹 디자인 패턴, Storybook)

younoah·2022년 3월 15일
5
post-custom-banner

와플카드 서비스가 궁금하다면!
와플카드 서비스 둘러보기 : https://waffle-card.com/
와플카드 깃허브 둘러보기 : https://github.com/waffle-card


🏃🏻‍♂️ intro

프로젝트를 시작하면서 가장 고민했던 점은 컴포넌트의 구조를 직관적으로 설계하는 것이다.

프로그래머스 웹 데브코스를 진행하면서 아토믹 디자인 패턴에 대해 알게 되었다.

아토믹 디자인의 최대 장점은 바로 간단 명료하다는 것이다.

Atom, Molecule, Organism, Template, Page로 컴포넌트들을 분류하고, 이들이 합쳐져 상위 레벨의 컴포넌트를 완성하는 구조이며 직관적이라고 생각이 들었다. 또한 중복되는 컴포넌트를 줄여 재사용성을 높이고, 결과적으로 개발소요시간을 단축할 수 있다.

이러한 장점 때문에 아토믹 디자인 패턴으로 bottom-up방식의 개발을 진행하기로 마음을 먹었고 아래와 같은 순서로 개발을 진행했다.

  1. 피그마를 참고하여 재사용되는 컴포넌트와 재사용되지 않는 컴포넌트를 분리
  2. 이후 아토믹 디자인 패턴을 활용하여 bottom-up 방식으로 개발을 진행
    • atommoleculeorganismpage
  3. 스토리북을 활용하여 컴포넌트 뷰 테스트 진행 및 컴포넌트 문서화

컴포넌트 개발을 진행하다보면 "이 컴포넌트는 어디로 분류해야하지?" 싶을 때가 있다. 즉, Atom, Molecule, Organism의 분류가 모호할 때가 있다. 이 기준을 모호하게 설정하고 개발을 진행하다보면 컴포넌트의 분류가 오히려 뒤죽박죽 섞여서 직관적이지 못할 수 있다.

다양한 글들을 참고하면서 아토믹 디자인 패턴의 분류를 아래와 같이 정의하고 들어갔다.

  • atom : 하나의 기능, 더 이상 나눠지지 않는 최소 요소 (재사용 가능)
  • molecule : 하나의 역할, 데이터를 표시하고 이벤트를 받을 수 있지만 하나의 역할만 가능 (재사용 가능)
  • organism : 하나의 요구사항, 사용자에게 의미를 가지는 기능적 요구사항에 포함되는 경우 (재사용 불가)

🧸 컴포넌트 구조

이렇게 완성된 와플카드 서비스의 컴포넌트 구조는 아래와 같다.

Atom

하나의 기능 - 더 이상 나눠지지 않는 최소 요소 (재사용 가능)

  • Button : 앱에서 사용되는 버튼 컴포넌트
  • Input : 이름, 휴대폰 번호, 주민등록 번호 입력 필드에 사용되는 컴포넌트
  • Portal : 자식요소를 body태그 최상단으로 이동시키는 컴포넌트. 로딩을 표시하는 Spinner와 같은 컴포넌트에서 활용
  • Text : 앱에서 사용되는 텍스트 컴포넌트

Molecule

하나의 역할 - 데이터를 표시하고 이벤트를 받을 수 있지만 “하나의 역할”만 가능 (재사용 가능)

  • ColorPicker : 와플카드를 생성하거나 수정할 때 컬러를 지정하기 위한 컬러 팔레트 피커
  • EditBox : 자신의 와플카드나 댓글에 마우스를 호버하였을 경우 나타나는 콤보박스이며 수정, 삭제 기능을 제공
  • LikeToggle : 와플카드를 좋아요 기능을 나타내는 컴포넌트
  • LoginGuide : 로그인 안내 가이드를 나타내는 컴포넌트
  • Modal : Portal 컴포넌트를 활용하여 body태그 최상단에 렌더링되며 컨텐츠를 전달받아 표시하는 모달 컴포넌트
  • NoCardGuide : 드가 존재하지 않다는 안내를 나타내는 컴포넌트
  • ScrollGuide : 홈페이지의 카드 목록을 가로스크롤로 활용하는 것을 안내하는 컴포넌트
  • Spinner : 시간이 소요되는 비동기 로직에서 로딩상태를 UI로 표시되는 컴포넌트
  • Tab : 홈페이지에서 와플카드의 목록을 필터링하는 탭 컴포넌트 (total, my, like 3가지 탭 종류가 존재)

Organism

하나의 요구사항 - 사용자에게 의미를 가지는 기능적 요구사항에 포함되는 경우에 해당되는 컴포넌트 (재사용 불가)

  • CardEditModal : 자신의 와플카드를 생성하거나 수정하는 기능을 나타내는 컴포넌트
  • ChattingCardModal : 와플카드를 클릭하면 나타나는 채팅 컴포넌트
  • Header : 앱의 헤더를 나타내는 컴포넌트
  • Modals : 렌더링할 모달들을 한번에 관리하는 용도의 컴포넌트
  • NameEditModal : 유저의 이름(닉네임)을 수정하기 위한 모달 컴포넌트
  • PasswordEditModal : 유저의 비밀번호를 수정하기 위한 모달 컴포넌트
  • WaffleCard : 홈페이제이서 렌더링되는 와플카드를 나타내는 컴포넌트
  • WaffleCardList : 와플카드들을 담고 있는 컨테이너 컴포넌트

Page

HomePage (홈페이지)

  • 탭에 따라 와플카드 목록을 렌더링합니다.
  • 로그인이 되어 있지 않다면 "오늘의 카드"(total) 목록만 렌더링이 됩니다.

SignUpPage (회원가입 페이지)

  • 회원가입을 진행합니다.
  • 각 Input에 따라 폼 검사를 진행합니다.

LoginPage (로그인 페이지)

  • 로그인을 진행합니다.
  • 각 Input에 따라 폼 검사를 진행합니다.

MyPage (마이 페이지)

  • 유저의 이메일, 이름(닉네임) 정보를 확인하고 로그아웃할 수 있으며 닉네임과 비밀번호를 변경합니다.
  • 닉네임과 비밀번호를 변경은 모달로 진행되며 폼 검사를 진행합니다.

최종적인 컴포넌트 구조는 아래 이미지 혹은 피그마를 참고


피그마 : https://www.figma.com/file/3vc8td1cihxElb6dqcpmA4/waffle-card?node-id=0%3A1


🎨 Storybook 곁들이기

컴포넌트를 아토믹 디자인 패턴으로 바텀업 개발을 하면 스토리북을 활용하여 뷰 테스트를 진행했다. 스토리북을 활용하면 테스트 뿐만아니라 각 컴포넌트에 어떤 prop이 있고 어떻게 사용하지 문서화도 할 수 있기 때문에 적극적으로 활용하였다.

결과적으로 스토리북의 구조화 된 것처럼 Atom과 Molecule을 조합해 새로운 Organism을 만들거나 혹은 Page를 구성하여 개발을 진행할 수 있어서 직관적이고 매우 편리하게 컴포넌트를 재활용 할 수 있어서 반복되는 코드를 줄일 수 있었다.

하지만

초반에 아토믹 디자인 패턴에 대해 설명할 때도 말했듯이 동료들과 개발을 하면서 Atom, Molecule, Organism의 분류가 모호하다는 단점이 더욱이 느끼게 되었다.

예를들어 아래와 같은 ColorPicker라는 컴포넌트가 있다고 가정하자.

이 컴포넌트는 어디에 속해야 할까? 개발 당시 재사용성이 가능하다고 판단하여 Molecule로 분류하였다. 하지만 해당 ColorPicker는 와플카드를 생성하는 CardEditModal에서만 사용된다. 그렇다면 재사용성이 이미 손실되었다는 반증이기도 하다. 물론 훗날 서비스를 확장하여 다른 곳에 활용이 될 수 있지만 현재의 서비스에서는 재사용을 할 곳이 없다.

비슷한 관심사나 관련있는 것들은 서로 가깝게 두는것이 더 효율적이다. 수정을 해야할 때 파일이 멀어진다면 비효율적이기 때문이다. 따라서 굳이 재사용되지 않고 어떤 컴포넌트 하나에 종속된다면 해당 컴포넌트에 귀속시키는게 더 좋은 방법이 될 수 도 있다.

이렇듯 Atom, Molecule, Organism의 분류의 기준이 개발자의 주관이 강하다는 점과 모호하다는 점이 협업에서 혼란을 야기할 수 있는 단점이 존재한다.

또한 Atom의 Button 컴포넌트를 수정한다고 생각해 보자 그렇다면 해당 Button 컴포넌트를 조합하여 만든 상위 컴포넌트들도 모두 수정해야하는 단점도 존재한다.

다양한 디자인 패턴을 찾아보면서 적용해 보고 앞으로 경험을 해봐야 할 것 같다. 그리고 현업에서는 어떤 디자인 패턴을 많이 사용할지 궁금하다.

profile
console.log(noah(🍕 , 🍺)); // true
post-custom-banner

0개의 댓글