[React] Atomic Pattern (2)

yongkini ·2023년 2월 16일
2

React

목록 보기
10/19

아토믹 패턴 정리

경과 보고(?)

: 지난번 아토믹 패턴 관련 포스팅을 하고 나서 어언,, 3개월 정도가 지나서 이 포스팅 시리즈를 마무리하려고 한다. 이렇게 시간이 지난건 그 시간동안 실제로 아토믹 패턴을 팀원분들과 설계하고, 실제 적용하고 개발하느라 이다(핑계인가?!). 이에 더하여 지난번 포스팅에서도 아토믹 패턴은 하나의 방법론이기 때문에 팀마다 적절한 정의를 써야한다고 했는데, 실제로 지난번 포스팅에서 정의한 원자, 분자의 의미가 완전히 바껴서 적용됐기에 새로 포스팅하고자 한다.

아토믹 패턴 적용 후기

: 관련 포스팅을 하기 전에 실제로 적용해본 후기를 말해보면, '확실히 쓸만하다' 생각이다. 리액트라는 프레임워크 자체가 유연함이 장점이지만 그 장점 때문에 정석이 없어서 다 다른 패턴의 개발을 하게된다는 것 같은데, 그런 부분에 있어서 아토믹 패턴이라는 일종의 '팀원들 간의 절대규칙'을 만듦으로써 그러한 단점이 많이 보완된다고 느꼈다. 사실 프론트엔드라는 분야 자체가 기획, 디자인, 백엔드 팀의 스타일 등 여러 직군과의 협업에 따라 컨벤션이 영향받기 쉬운 구조라고 생각하는데, 그런 부분에 있어서 아토믹 패턴과 디자인 시스템 구축은 그런 영향권 속에서 우리만의 룰을 정하는 방법중에 하나라고 생각된다.

: 추가로 확실히 아토믹 패턴을 사용해서 컴포넌트를 명확히 정의하니까 '재사용성'이 향상됐다. 처음에는 '이걸 따로 만들어놓는 시간에 새로운걸 하나 만드는게 훨씬 빠르지 않을까' 라는 생각이었지만 막상 시작하니 어떤 기획과 디자인을 봤을 때 특정 단위의 컴포넌트가 떠오르면서 개발 효율이 높아졌다. 약간 규모의 경제학(?)과 같다고 생각된다. 처음에는 뭔가를 따로 만들기 위해 비용이 많이 필요하지만 그 비용이 점점 쌓이다보면 후에는 초기에 투자한 비용에 의해 거의 비용이 들어가지 않는 구조 같다.

어떤 식으로 아토믹 패턴을 '재정의' 했는가?

ATOM

: 사실 이걸 정하는데도 몇일의 시간이 걸렸던 것 같다. 애초에 수학의 정석처럼 정답이 있는 부분이 아니었어서 다른 관점일 수 밖에 없음을 인정하고 이걸 정하는데 꽤나 많은 논의와 토론을 했다. 결론적으로 아톰은 다음과 같은 특징을 갖는다.

  • 상태(react or redux state)와 비즈니스 로직을 갖지 않는다.
  • 무조건 semantic tag로만 구성한다.
  • props 으로는 해당 semantic tag의 기본 attribute만을 허용한다(img라면 alt, src 등)
  • 이 때, props에 useRef의 ref는 허용한다.

사실 처음에 이렇게 정의를 했을 때 atom이 의미가 있을까? 싶었다. 하지만, atom은 개발을 하면서 버튼을 만들일이 있으면 가장 먼저 떠올릴 단위가 됐고, 디자인 시스템 상으로 유사한 버튼이 만들어질 것이 약속이 됐기에 해당 버튼의 디자인이 사전에 구현된 적이 있다면 atom 을 사용할 때 해당 디자인과 맞는 className만 적용해주면 된다.

예시
import "./style.scss";

export interface Props
  extends React.DetailedHTMLProps<
    React.ImgHTMLAttributes<HTMLImageElement>,
    HTMLImageElement
  > {
  src: string;
}

export const Image = ({ src, alt, width, height, ...props }: Props) => {
  return <img src={src} alt={alt} width={width} height={height} {...props} />;
};

위에는 직접 만든 Image Atom 인데 위의 특징을 모두 갖고 있다. state가 없고, 비즈니스 로직이 없으며, props에는 img 태그의 기본 속성들만 들어가있다(width, height도 이미지의 기본 속성이기에).

MOLECULE

: 어떤 회사의 아토믹 패턴에서는 분자가 가장 많다고들 하는데, 이와는 다르게 원자가 많고, 분자가 상대적으로 적어지는 방향으로 분자를 정의했다. 분자의 특징은 다음과 같다.

  • 상태(react or redux state)와 비즈니스 로직을 갖지 않는다.
  • semantic tag 이외에 tag를 자유롭게 사용할 수 있다.
  • props 는 자유롭게 사용 가능하다.
  • 복수개의 원자를 포함할 수 있다. 하지만, 분자안에 분자는 안된다.
예시
export interface Props
  extends React.DetailedHTMLProps<
    React.HTMLAttributes<HTMLDivElement>,
    HTMLDivElement
  > {
  children: React.ReactNode;
  width: number;
}

export const Nav = ({ children, width, ...props }: Props) => {
  return (
    <nav {...props} style={{ width }}>
      {children}
    </nav>
  );
};

위의 코드는 잘만든건지는 아직은 확신이 안서지만 분자에 해당하는 특징을 갖는다. 시맨틱 태그를 썼지만, props로 width를 받고 있기 때문에 기본 속성이 아닌 속성을 받음으로써 원자가 아닌 분자가 됐다. width를 받지 않았다면 원자였을 것이다.

ORGANISM

: 유기체는 위에서 정의한 원자, 분자를 가지고 실제로 우리가 흔히 보는 '하나 이상의 동작 및 기획이 들어있는 단위'가 된다. 이에 따라 유기체의 특징은 다음과 같다.

  • 상태(react or redux state)와 비즈니스 로직을 갖는다.
  • props는 자유롭게 사용 가능하다.
  • semantic tag 이외에 tag를 자유롭게 사용할 수 있다.
  • 분자와 분자 혹은 분자와 원자의 조합으로 구성된다(분자 안에 분자가 안되듯이, organism 안에 organism은 불가능함).

TEMPLATE

: 템플릿은 용어 그대로 해석하고자 했다. 레이아웃 등을 잡는 역할로 쓰고자 한다.

  • react or redux state는 사용하지 않는다.
  • 비즈니스 로직은 쓰지 않는다.
  • props 에는 자유롭게 다른 컴포넌트를 받아서 children으로 쓸 수 있고, 오른쪽에 배치하는 등 레이아웃팅에 쓸 수 있다.
  • tag 의 스펙트럼도 자유다.
예시
import React from "react";
import "./style.scss";
import { createPortal } from "react-dom";
export interface Props
  extends React.DetailedHTMLProps<
    React.HTMLAttributes<HTMLDivElement>,
    HTMLDivElement
  > {
  children: React.ReactNode;
}

export function ModalLayout({ children, ...props }: Props) {
  return (
    <div {...props}>
      <div className="dim"></div>
      <div className="content">{children}</div>
    </div>
  );
}

const parentEl = document.getElementById("root") as HTMLElement;

export function Modal({ children, ...props }: Props) {
  return createPortal(
    <ModalLayout {...props}>{children}</ModalLayout>,
    parentEl
  );
}

위에는 제가 만들어본 모달 템플릿 입니다. createPortal을 써서 한번 감싸준 modal을 실제로 사용하게 되는 방식입니다. 위에를 보시면 템플릿의 특징 답게(?) 따로 비즈니스 로직 및 state는 없고 props로 컴포넌트를 받아서 세팅해놓은 모달에 해당 컴포넌트를 레이아웃팅만 해주는 역할을 합니다.

CONTAINER

: 일반적인 아토믹 패턴과 다르게 container를 따로 둬서 재사용하지 않는 유기체와 템플릿을 컨테이너로 정의했다. 아토믹 패턴을 쓴다고 해도 TS를 쓸 때 처음부터 너무 strict 하면 어려울 것이 예상되듯이 약간의 자율성을 부여한 정의이다. 유기체와 템플릿의 특징은 가지되 재사용하지 않는 것이 여기에 들어간다고 생각했다.

결론

: 사실 팀마다 필요로 하는 아토믹 패턴이 다를 수 있기에 위에 패턴이 정답은 아니다. 누군가에겐 왜 이렇게 하지? 정도로 맞지 않는 패턴일 수 있다. 따라서 아토믹 패턴을 정의할 때는 기존에 몇페이지 안되는 아토믹 패턴에 대한 정의를 참조하면서 팀에게 적합한 아토믹 패턴을 커스텀해서 만들어 쓴다는 방향으로 접근해서 쓰는게 맞는 것 같다.

profile
완벽함 보다는 최선의 결과를 위해 끊임없이 노력하는 개발자

0개의 댓글