[포스코x코딩온] KDT-Web-8 12주차 회고1 atomic design

Yunes·2023년 9월 20일
0

[포스코x코딩온]

목록 보기
31/47
post-thumbnail

서론

팀 프로젝트가 끝나고 이제 react 수업이 시작되었다. 그런데 진도상 이슈가 있는지 2주밖에 react 수업을 하지 않는다고 한다... 이게 대체 무슨일일까 한 3달은 react 를 하게 되지 않을까 생각하면서 지난 한달간 react 스터디를 진행했던건데 지금와서 생각해보면 미리 스터디를 시작해서 참 다행이다. 2주안에 react 를 다 배울수 있을지 모르겠지만 원리를 충분히 이해하기에는 빠듯할 수 있을것 같다는 생각이 떠나질 않는다. 스터디때 알아봤던 내용들중 머릿속에서 빠져나온게 있다면 다시 집어넣으며 이 포스트를 작성하게 되었다.

수업 요약

React 의 컴포넌트, props, JSX 와 함수형, 클래스형 컴포넌트의 기본구조, default props, PropsType 에 대한 내용이었다. 클래스형 컴포넌트는 react.dev 에서도

w3school react component 에서도 차라리 함수형 컴포넌트를 사용하라고 권장하고 있다.

수업시간동안 class component 와 functional component 의 차이에 대해 정말 간단하게 언급하고 구조의 차이 등에 대해 알수 있었다.

그저 render() 가 있는지, props 를 사용시 this 의 유무.. 이정도

확실히 자세한 원리를 파악하는데엔 공식문서만한게 없다. 과거 class 형 컴포넌트를 사용하다 functional component 로 넘어갈 수 있던 데엔 class 형 컴포넌트에서만 state 를 관리할 수 있었는데 React 16.8 부터 새로 추가된 Hook 에 의해 기존 class 컴포넌트를 더이상 사용할 필요없이 functional component 를 사용해도 아무 문제가 없게 된 것이다.

그래도 lifecycle와 useEffect hook 에 대해 이해하기 위해서는 class 컴포넌트에 대해 알아야 한다고 생각한다.

아토믹 디자인

마찬가지로 수업시간동안 마틴리더님이 카카오 FE 기술블로그의 아토믹 디자인을 활용한 디자인 시스템 도입기 글에 대해 소개해주셨다. 이 포스트에선 그에 대해 읽고 알게된 내용들을 정리하려 한다.


이미지 출처 : https://fe-developers.kakaoent.com/2022/220505-how-page-part-use-atomic-design-system/

나 역시 웹사이트를 React 로 만들때 해봤던 고민이라 이 아토믹 디자인이라는 개념을 알게 되면서 굉장히 흥미로웠다. 웹사이트를 만들때 Component 를 활용한다면 미리 Header, Button, Typography 등을 만들어두고 이 구성요소 Component 들을 가져다가 조합해서 사이트를 만들어본 경험이 있다. 그런데 문제가 있었다.

모바일의 경우 반응형이 그렇게 큰 범위로 발생하지 않을 수 있는데 웹사이트를 기준으로 반응형을 만든다면 같은 버튼이라도 크기가 달라질때 어떻게 처리해야 할지, 같은 버튼이라도 입력버튼, 라벨버튼, 로고와 텍스트가 들어간 버튼등 다른 버튼은 어떻게 컴포넌트를 만들어야 할지 ( 그당시엔 고민하다가 styled-component 를 활용해서 해결했다. ) 등의 고민이 있었다.

역시 개발자들은 비슷비슷한 고민을 하는것 같다. 이 아토믹 디자인을 어느정도 depth 로 설정하는지에 따라 깔끔하고 일관된 규칙으로 React 코드를 짤 수 있을것 같다는 생각이 들었다.

아토믹 디자인 도입 이유

React 로 UI 를 만들때 관리되지 않는 부분이 있을때 같은 버튼이더라도 페이지에 따라 margin, padding, color 등이 제각각일 수 있다. 또한 디자이너와 협업시 서로 어떤 것에 대해 말하는 것인지 이해의 차이가 발생할 수 있다.

또한 컴포넌트 구조 설계시 명확한 기준이 없다. 각각의 멤버가 생각하는 의미있는 기준에 따라 컴포넌트를 생성하다보면 일관성이 없고 제각각 컴포넌트를 만들어 재사용하거나 확장하기 어려운 비슷비슷한데 다른 컴포넌트들이 넘쳐나게 될 수 있다.

이런 문제는 공모전에서 React 로 웹페이지를 만들때 나 역시 겪었던 문제다. 최소한의 단위와 Compond Component 를 만들어 재사용하기 쉬운 컴포넌트를 만들고자 했다.

그래서 Typography, Color 등을 만들고 Button 도 여러 종류에 따라 props 로 input / icon / submit / disabled 등을 넘기면 그에 따라 styled-component 로 같은 Button 컴포넌트를 재사용하되 각각 다른 style 을 적용하는 식이었다.

그런데 문제는 Button 자체는 재사용하기는 하는데 props 로 어떤 string 을 전달하는지에 따라 구조가 달라지고 반응형을 적용하려하니 웹부터 만들어서 깨지는 문제가 발생한 것이다. ( 물론 이건 다른 문제다.. )

아무튼 그런 경험이 있어서 이 아토믹 디자인이 더 와닿았던 것 같다.

아토믹 디자인이란?

이미지 출처 : https://atomicdesign.bradfrost.com/chapter-2/#the-part-and-the-whole

아토믹 디자인이란 컴포넌트를 atoms / molecules / organicsm / templates / pages 로 나누는 방식으로 디자인 시스템을 만드는 방법론을 말한다.

이때의 디자인 시스템이란 UI 컴포넌트, variants, Typography, color palette, layout, grid 등의 하위 시스템을 말한다.

이름에서 유추할 수 있듯이 아토믹 디자인이라는 이름은 화학적 관점에서 영감을 얻은 디자인으로 더이상 쪼갤수 없는 원자 / 원자들이 결합한 분자 / 분자들이 모여 복잡한 유기체 를 생성하고 이러한 유기체들로 templatespages 를 만드는 방식을 의미한다.


이미지 출처 : https://atomicdesign.bradfrost.com/chapter-2/#the-part-and-the-whole

Atom

더이상 쪼갤수 없는 기본적인 컴포넌트를 말한다.

  • label
  • input
  • button
  • typography
  • color palette
  • layout ...

이미지 출처 : https://atomicdesign.bradfrost.com/chapter-2/

Molecule

분자는 여러 원자를 결합하여 자신의 고유한 특성을 갖는다. 마치 2개의 수소와 1개의 산소 원자가 결합하여 물이라는 특성을 나타내는 것처럼 말이다.

인터페이스에서 분자는 하나의 단위로 함께 작동하는 상대적으로 단순한 UI 요소 그룹이다. 예를 들어 양식 레이블, 검색 입력 및 버튼을 함께 결합하여 검색 양식 분자를 만들 수 있다.

이런 간단한 구성요소를 만들면 SRP 단일책임원칙을 지켜 단일 패턴에서 너무 많은 복잡성을 피할 수 있고 재사용성이 향상되며 인터페이스 전체의 일관성을 향상시킬 수 있다.


이미지 출처 : https://atomicdesign.bradfrost.com/chapter-2/

Organism

유기체는 분자들이 모여 하나의 유기체를 이룰 수 있는데 해당 글에서는 서비스에서 표현될 수 있는 명확한 영역과 특정 컨텍스트를 갖는 경우를 의미했다.

유기체는 분자, 원자, 및 기타 유기체 그룹으로 구성된 보다 복잡한 UI 구성요소이다. 아래의 예시 header 는 logo (atom) , navigation (molecule), search form(molecule) 등을 포함하며 organism 은 atom, molecule 에 비해 재사용성이 낮다.


이미지 출처 : https://atomicdesign.bradfrost.com/chapter-2/

Template

템플릿은 page 를 만들기 위해 여러 organism, molecule 로 구성할 수 있다. 이러한 template 는 실제 컴포넌트를 레이아웃에 배치하고 구조를 잡는 프레임으로 실제 콘텐츠가 없는 page 스켈레톤이다.

하단의 출처에서는 template 을 구성요소를 레이아웃에 배치하고 디자인의 기본 콘텐츠 구조를 명확하게 표현하는 페이지 수준의 개체라고 말한다.


이미지 출처 : https://atomicdesign.bradfrost.com/chapter-2/


이미지 출처 : https://atomicdesign.bradfrost.com/chapter-2/

Page

페이지는 유저가 실제로 볼수있는 화면 페이지이며 template 의 인스턴스라고 볼 수 있다. 또한 페이지는 실제 대표적인 콘텐츠가 포함딘 UI 의 모습을 보여주는 템플릿의 특정 인스턴스이다.


이미지 출처 : https://atomicdesign.bradfrost.com/chapter-2/

발생한 문제

  • Molecule 과 Organism 을 어떻게 구분하는가?

해당 글에서는 컴포넌트에 컨텍스트가 있을 때는 organism 으로, 그렇지 않고 컨텍스트 없이 UI 요소로 SRP 를 지킬수 있을때 재사용하기 쉬운 molecule 로 작성한다. 그래서 molecule 의 컴포넌트 이름에는 컨텍스트가 포함되어 있지 않고 organism 의 컴포넌트 이름에는 컨텍스트가 포함된다.

  • Organism 을 나누는 기준

보통 디자이너, 타 개발자들과 논의하에 애매한 경우에 대해 대처하는 방식을 채택

  • 불필요한 props 증가

redux 나 recoil 등을 사용했는지 어떤지는 알수가 없으나 이 글에서는 비슷한 디자인인데 구조가 조금씩 달라질때 불필요한 props 가 증가하는 경우에 대해 compound component 를 이용하여 해결했다고 한다. 저 compound-component 에서는 context 를 활용하여 props 를 불필요하게 전달하지 않는 방식을 사용하는 것으로 보이는데 실제로 kakao webtoon 페이지로 가서 컴포넌트를 확인해봤다.

compound-component 코드 예시

function App() {
  return (
    <Toggle onToggle={on => console.log(on)}>
      <ToggleOn>The button is on</ToggleOn>
      <ToggleOff>The button is off</ToggleOff>
      <ToggleButton />
    </Toggle>
  )
}

import * as React from 'react'
// this switch implements a checkbox input and is not relevant for this example
import {Switch} from '../switch'

const ToggleContext = React.createContext()

function useEffectAfterMount(cb, dependencies) {
  const justMounted = React.useRef(true)
  React.useEffect(() => {
    if (!justMounted.current) {
      return cb()
    }
    justMounted.current = false
  }, dependencies)
}

function Toggle(props) {
  const [on, setOn] = React.useState(false)
  const toggle = React.useCallback(() => setOn(oldOn => !oldOn), [])
  useEffectAfterMount(() => {
    props.onToggle(on)
  }, [on])
  const value = React.useMemo(() => ({on, toggle}), [on])
  return (
    <ToggleContext.Provider value={value}>
      {props.children}
    </ToggleContext.Provider>
  )
}

function useToggleContext() {
  const context = React.useContext(ToggleContext)
  if (!context) {
    throw new Error(
      `Toggle compound components cannot be rendered outside the Toggle component`,
    )
  }
  return context
}

function ToggleOn({children}) {
  const {on} = useToggleContext()
  return on ? children : null
}

function ToggleOff({children}) {
  const {on} = useToggleContext()
  return on ? null : children
}

function ToggleButton(props) {
  const {on, toggle} = useToggleContext()
  return <Switch on={on} onClick={toggle} {...props} />
}

코드출처 : https://kentcdodds.com/blog/compound-components-with-react-hooks

위의 코드에서 볼 수 있듯이 compound-component 구조에서 불필요하게 props 를 전달하는 것을 막기위해 compound 구조상 가장 부모 컴포넌트에서 children 을 createContext 로 만든 Context.Provider 로 감싸고 있는 것을 볼 수 있다.

kakao webtoon

카카오 웹툰을 보면 카카오에서 이런 compound-component 방식을 채택하여 useContext 를 써서 각각의 compound-component 가 Context 를 통해 props 를 줄였다는 것을 알 수 있었다.

피그마 컴포넌트

인상적이었던게 피그마 컴포넌트에 대한 내용도 소개가 되고 있는 부분이 있다는 것이다.
피그마에서는 Typography, Component, Color 등을 디자이너가 저장해둘 수가 있다. 그런 이름을 그대로 컴포넌트에 갖다 사용하면 디자이너와의 협업시 같은 대상에 대해 이야기하기 쉬워진다.

예를 들어 이런 Typography 를 디자이너가 미리 지정해 뒀다면 FE 개발자는 scss 작업을 할때나 React 로 컴포넌트명을 지을때나 같은 이름으로 네이밍을 작성할 수 있다.

UI 모델링

결국 아토믹 디자인도 하나의 방법이지 반드시 지켜야하는것이 아니다. 또한 적용을 하다보면 모호한 부분이 생길 것이라 이러한 경우 협업을 하는 동료 개발자, 디자이너와 어떤 이름을 부여할 것인지 논의가 필요할 것 같다.


이미지 출처 : https://fe-developers.kakaoent.com/2022/220505-how-page-part-use-atomic-design-system/

결론

여러모로 흥미로운 글이었다. 컴포넌트를 작성할때 Context 의 활용사례도 확인할 수 있었고 어떤 방식으로 컴포넌트를 쪼개서 관리할 수 있는지에 대해 새로운 관점을 알게되었다. 적어도 기존에 규칙없이 컴포넌트를 쪼개서 관리할때보다는 좀더 일관적이고 규칙있는 구조로 React 컴포넌트를 관리할 수 있을 것 같다.

레퍼런스

reference
kakao entertainment FE 기술블로그 - 아토믹 디자인을 활용한 디자인 시스템 도입기
atomic design bradfrost

profile
미래의 나를 만들어나가는 한 개발자의 블로그입니다.

0개의 댓글