신입 개발자에서 시니어 개발자가 되기까지

[메인 프로젝트] 메인프로젝트 회고 - 디자인 패턴(feat. atomic) 본문

코드스테이츠

[메인 프로젝트] 메인프로젝트 회고 - 디자인 패턴(feat. atomic)

Jin.K 2023. 2. 14. 21:48

디자인 패턴이란 무엇인가

react에서 디자인 패턴이라 하면 컴포넌트를 설계하는 방법론인 것 같다. 어떤 기준으로 컴포넌트를 나눌 것인지, 나눠진 컴포넌트를 어느 폴더에 넣어서 관리할 것인지, 비지니스 로직은 어떤 컴포넌트에서 구현할 것인지 등을 결정하는 것이다.
우리팀이 사용하기로 한 디자인 패턴은 아토믹 디자인 패턴이다.

왜 아토믹 디자인 패턴인가

일단 어떤 디자인 패턴이든 하나는 사용하고 싶었다. 여러 개의 솔로 프로젝트를 하면서 어려웠던 것 중 하나가 폴더 관리였다. 어떤 컴포넌트를 어떤 폴더에 둬야하는지, 또 나름 찾아보면서 폴더 관리를 했지만 이렇게 하는게 맞는건지 확신할 수 없었다. 그저 블로그 여러개를 보며 공통적으로 해당되는 부분들을 참고해서 사용했을 뿐이니까.
우리가 아토믹 디자인 패턴을 사용하기로 한 결정적인 이유는 재사용성 때문이다. 프론트엔드 팀원이 총 4명이었기 때문에 UI 컴포넌트부터 컴포넌트를 atoms, molecules, organisms로 나누어 작은 단위부터 개발을 하면 누군가가 input 엘리먼트를 만들어놓으면, 다음 사람은 거기다 필요한 props만 전달해서 사용하면 되기 때문이다.
물론 그 외에도 여러 이유가 있다. 카카오 기술 블로그에 마침 아토믹 디자인 패턴에 대한 상세한 글이 있었고, 영어로된 문서도 아토믹에 대한 장점과 단점들을 나열한 문서들이 많았다. 또한 피그마로 디자인을 할 때 만들어뒀던 컴포넌트들을 그대로 UI로 옮기면 됐기 때문에 현재의 작업방향과도 맞아 떨어졌다. (원래는 기획과 디자인 단계에서 이미 디자인 패턴이 결정됐어야 했지만, 이런 프로젝트가 처음이었기에 순서가 바뀌었다)

아토믹 디자인 패턴을 어떻게 적용했는가

우리 팀은 아토믹 디자인 패턴을 똑같이 사용하지는 않았다. atomics -> molecules -> organisms -> template -> page 순으로 컴포넌트를 만들어나가야 하는데 template은 사용하지 않았다. 팀원들과 논의한 결과 템플릿의 개념이 조금 모호한 것 같았고 organisms 까지만 아토믹 디자인패턴에 따라 구분했다. 그리고 기능구현을 하기 전까지는 별 문제가 없었지만 기능구현을 하면서 비지니스 로직을 작성하게되니까 이 로직을 어디에 둬야하는지 고민을 많이했고, 첫 번째는 page 단에 비지니스로직을 두고, 그 외에 container 폴더를 만들어 tab과 같은 컴포넌트를 해당 폴더 아래에 두고 여기서 비지니스 로직을 구현했다. (근데 이것 때문에 고생을 많이해서 이 부분은 아래에서 더 다루도록 하겠다..)

아토믹 디자인 패턴의 장점

재사용성

실제로 우리는 UI컴포넌트 개발부터 input, 버튼, header, bottom, listItem, tap, 이미지 컴포넌트 등등으로 나누어서 만들어나갔다.

이런식으로 컴포넌트를 나눠서 역할 분담을 했고, UI컴포넌트를 나눴다. 페이지를 나누고 작업한게 아니라 컴포넌트 단위로 작업을 한 후 각자 페이지를 맡아서 UI를 그렸다. 이렇게하니까 만들어둔 컴포넌트를 가져와서 내가 담당한 페이지에 올려두기만 하면 돼서 일단 편했고, 뭔가 협업하는 느낌이 강하게 들었다.

확장성

재사용성과 어찌보면 비슷할 수도 있겠다. 다만, 우리는 Material UI를 사용했었고, MUI의 TextField를 atoms로 두고서 이걸 molecules에서는 password input, textInput, dropdownInput으로도 사용했다. 단순히 만들어둔 Input 컴포넌트를 로그인에도 사용하고 회원가입에도 사용하고 이랬던 것이 아니라 이 input 컴포넌트를 다양하게 확장해서 사용했다.

1.atoms input

const Input = ({
  endAdornment,
  children,
  select,
  multiline,
  className,
  value,
  onChange,
  required,
  ...props
}: any) => {
  return (
    <TextField
      {...props}
      {...(select ? { select: true } : null)}
      {...(multiline ? { multiline: true } : null)}
      className={className}
      value={value}
      onChange={onChange}
      InputProps={{ endAdornment }}
      required={required}
    >
      {children}
    </TextField>
  );
};

2.molecules에서 DropdownInput

     <Input
        id={id}
        label={label}
        select={true}
        defaultValue={dropDownOptions[0]?.label || '기본값'}
        selectprops={{
          native: true,
        }}
        onChange={onChange}
        {...props}
      >
        {dropDownOptions?.map((option: any) => (
          <MenuItem value={option.value} key={option.value}>
            {option.label}
          </MenuItem>
        ))}
      </Input>

폴더관리

개발을 하다보면 처음엔 어느 컴포넌트에 뭐가 있는지 잘 기억하고 잘 찾지만 폴더관리를 잘 해놓지 않으면 프로젝트가 확장될수록 이런걸 찾는데 헤매는 시간이 늘어난다. 그런데 아토믹 컴포넌트를 사용했을 때는 비교적 더 쉽게 원하는 컴포넌트, 함수 등을 잘 찾았던 것 같다. 규모가 엄~청 큰건 아니어서 그럴 수도 있지만, 내가 작성하지 않은 코드라도 잘 찾았었다. 비지니스 로직이 여기저기 분산되어 있는게아니라 페이지 혹은 container에서 구현했기 때문이다.

아토믹 디자인 패턴의 어려움

아토믹 디자인 패턴을 사용하면서 좋았던 점만 있는 것은 아니었다.

atoms / molecules / organisms 의 구분

우리는 처음에 이 atoms와 molecule을 구분하는 것이 어려웠고, 또 molecules와 organisms를 구분하기가 어려웠다. 각자 생각이 달랐기 때문이다. input은 atome이고 label도 아톰이면 여러개의 input과 여러개의 label이 모인 회원가입 form은 molecules인지 organisms인지? 이런 것들이 팀원들마다 각자 생각이 달랐다. 그래서 이런 것들을 우리만의 기준을 세워서 구분했다.
먼저 atoms는 가장 작은 단위의 컴포넌트로 정했다. 그리고 atoms가 두 개 이상 모이면 molecules에 두기로 했다. 또 atoms + molecules의 구조와 molecules + molecules의 구조라면 organisms에 뒀다. 우리만의 기준을 세워서 폴더를 나누다보니 훨씬 수월해졌다.

디자인 패턴의 적용

위의 구분처럼 우리 나름대로 기준을 세웠긴 하지만, 처음 적용하는 것이다보니 가장 작은 단위의 컴포넌트에 대한 개념이 부족했었다. 그래서 atoms가 태그 두 개 이상인 경우가 있었다. 이 부분은 멘토님께서 보시고 조언을 해주셔서 나중에 깨달은 건데 atoms는 더이상 분해할 수 없는 컴포넌트, 태그 하나여야 한다고 말씀하셔서 리팩토링을 하곤 했다.

비지니스 로직의 분리

UI 컴포넌트를 개발하고 난 후 로그인, 회원가입, 지도 기능, 실시간 채팅 등의 기능을 구현하면서부터 또 한번 어려움에 부딪혔다. 사실 멘토님의 조언이 있었기에 비지니스 로직을 페이지단에서 구현한다는 것은 헷갈릴 게 없었다. 그런데 my page의 경우 다음과 같이 이중tab을 구현했었는데 여기서 조금 어려움이 있었다.

이런 식으로 내 정보 탭에는 내정보 수정, 주소록 등록 탭이 있고, 쉐어링 탭에서는 내가 참여한 쉐어링, 찜한 쉐어링, 내가 개설한 쉐어링 탭이 있다. 그래서 마이 페이지 단에서 비지니스 로직을 모두 구현하자니 많은 로직이 한번에 들어가야해서 너무 복잡해지는 것 같았고, 그렇다고 organisms에서 비지니스 로직을 구현하자니 아토믹 디자인 패턴에 맞지 않는 것 같았다. 그래서 tab 컴포넌트는 container 라는 폴더를 따로 만들어서 그 아래에 두고 비지니스 로직을 탭 컴포넌트에서 구현하기로 했다. 이런 문제 때문에 container 폴더가 생기게 됐고 최대한 페이지 단에서 로직을 사용하되 탭 컴포넌트처럼 애매한 부분이 있으면 container에서 비지니스 로직을 구현했다.

아토믹 디자인 패턴 사용 후기

위에서 언급한 어려움들 때문에 프론트 팀원들 간의 회의 시간이 많았다. 기준을 정해야하고, 애매한 것이 있으면 팀원들이랑 의논도 했다. 컴포넌트는 어느 폴더에 둘지 로직은 어디에 배치할지 결정해야했기 때문이다. 이런 회의 시간 때문에 개발속도가 늦어진 것은 분명하다. 하지만 초기 속도가 늦었을 뿐이지 익숙해질수록 점차 회의 시간은 줄어갔고 파일과 폴더들이 많아질수록 디자인 패턴을 적용하지 않은 프로젝트에 비해 작업이 원활했던 것 같다. 위에서 언급했듯이 내가 작성하지 않은 코드라도 잘 찾을 수 있었다고 한 이유는 실제로 문제가 되는 코드를 급하게 찾아야 했고, 내가 쓴 코드가 아니었음에도 어느 파일에 있는 로직인지 알았기 때문에 금방 찾아서 수정할 수 있었다. 분리되어 있기 때문에 컴포넌트에는 많은 로직이 들어가있지 않은 것도 코드를 쉽게 찾은 이유였다.
아무튼 팀원들과의 생각을 공유하면서 비지니스 로직은 무엇인지 한번 생각하는 계기가 됐고, 정리된 컴포넌트와 로직이 들어가있는 파일들을 보면 매우 뿌듯하다.
비록 정확한 아토믹 디자인 패턴을 적용한 것은 아닌 것 같지만 결국 디자인 패턴이란 작업을 효율적으로 하기 위한 것이고, 이러한 근본적인 목적을 생각한다면 우리만의 기준을 세워 나가며 디자인 패턴을 사용한 것이 잘못 사용했다는 생각이 들지는 않는다. 다음 프로젝트에서는 이러한 고민들이 경험이 되어 더 나은 디자인 패턴을 사용할 수 있을 것 같다는 자신감이 생겼고,