지금까지 팀 프로젝트에서 프론트엔드 리드로 작업을 하였고 최근에는 혼자 프론트엔드 쪽 프로젝트를 작업하였습니다. 프로젝트를 진행하기 전에 작업을 효율적으로 가져가기 위해 어떻게 코드를 작성하고 폴더를 구성하는 지는 전적으로 저의 의견을 가지고 디자인 패턴을 구현하였습니다. 그러던 와중 시간적으로 여유가 생기게 되어 여러 프론트엔드 atomic 패턴 reference를 보게 되었고 이에 대해 이야기 해보고자 합니다.
atomic패턴에 대해 알아보기 전에 지금까지 프론트엔드 아키텍쳐의 발전과정을 알아보겠습니다.
- MVC 패턴 : 초창기 MVC패턴은 데이터 영역인
Model
, ui를 보여주는View
영역, Model과 View사이에 컨트롤하는Controller
로 구성되어 있었습니다. Model은DB
, View는html,css,Javascript
, Controller는백엔드 영역
으로 나누어졌습니다.
하지만 이후 JQuery가 등장한 이후 프론트엔드에서는 Model은Ajax
부터 받는 데이터, View는html,css
, Controller는Javascript
로 인식됩니다.
- MVVM패턴 : Model, View, ViewModel로 구성된 패턴입니다. 기존의 JQuery는 Model이 바뀌면 View를 , View가 바뀌면 Model을 직접 바꾸는 번거로운 작업을 하였습니다. 이에 템플릿 바인딩을 통한 데이터 렌더링을 통해 View에게 전달할 Model만 잘 구성하면 된다는
ViewModel(어떻게 보면 Controller역할)
이 생기게 되었습니다. 이는 지금 많이 사용되는 javascript 라이브러리인 Angular,Vue,React에서 드러납니다.
- MVP패턴 : MVVM패턴에서의 비즈니스 로직(Modal을 다루는 부분)과 뷰를 나누고자 하는 방향에서 생긴 패턴입니다. 우리가 흔히 알고있는 컴포넌트가 여기서 생기게 됩니다.
- FLUX패턴 : 컴포넌트 구조로 잘게잘게 잘라버리게 되어 propsdrilling문제에 대한 의문이 제기되면서 생긴 패턴입니다. 많이 사용되고 있는
Redux
가 대표적입니다.단방향적인 데이터 흐름
을 강조하고 있습니다.
- 더 간편한 방법들 : Flux패턴은 많은 곳에서 사용되고 있지만 학습곡선이 높고 코드량이 상대적으로 많습니다. 이에 대해
Mobx,recoil
그리고 서버 데이터를 다루기 위한SWR, React-Query
가 등장하여 외부 데이터에 대한 관리를 더 엄격하게 할 수 있게 되었습니다.
프론트엔드 개발을 하면서 대부분 MVP패턴에 맞춰 한 페이지 내에서 컴포넌트 설계를 해왔습니다. 하지만 이는 기준이 불분명 하게 다가올 수 있습니다.
이에 대해 아토믹 패턴은 솔루션을 제공합니다.
atomic패턴은 제일 작은 원자단위의 atom에서부터 가장 큰 단위인 pages까지를 구분하여 컴포넌트 구성에 있어서 솔루션을 제공합니다.
컴포넌트 및 폴더 설계를 위해 위의 atomic패턴을 적용한 레포지토리 코드를 참고 했습니다.
atoms , molecules, organimsms, pages, templates로 폴더를 구성하였습니다. (가독성을 위해 pages폴더는 따로 빼주기도 합니다.)
Atoms폴더
Button폴더
하나의 Button.tsx컴포넌트를 사용하였고 props에 프로퍼티 값들을 넘겨주며 변경에 유연하게 하고 있습니다. (보통 styled-component사용하여 스타일링을 많이 하는 것 같습니다.)
그리하여 폴더 구조를 이와 같이 변경하였습니다. 조금 더 직관적이며 Button컴포넌트 하나로 구성할 수 있게 되었습니다. 하지만 Button 컴포넌트 하나로 프로젝트의 모든 Button을 다뤄야하기 때문에 변경에 유연
해야 합니다.
/**atoms/button/buttonAtoms*/
"use client";
import React from "react";
import { Button, ButtonProps } from "@chakra-ui/react";
const ButtonAtom = ({
type,
w,
h,
bg,
color,
colorScheme,
onClick,
children,
disabled,
border,
borderRadius,
className,
fontSize,
size,
}: ButtonProps) => {
return (
<Button
className={className}
fontSize={fontSize}
type={type}
w={w}
h={h}
border={border}
borderRadius={borderRadius}
bg={bg}
size={size}
color={color}
colorScheme={colorScheme}
_hover={{ bg: { bg } }}
onClick={onClick}
isDisabled={disabled}
>
{children}
</Button>
);
};
export default ButtonAtom;
(불가피하게 Chakra UI를 사용했기에 Button이름을 naming하지 못했음..)
button props로 받아 button을 유연하게 변경하도록 설정하였습니다.
아직 atomic 패턴에 대해 공부중이며 적용해 나가는 과정입니다. 현재 atomic패턴를 많이 도입하고 사용해나가는 느낌을 받고 있습니다. 하지만 프론트엔드 기술은 빠르게 진화하고 있습니다. 불과 몇년 만에 여러 패턴들이 나왔으니... 또한 atomic은 최선의 방식이 아닙니다. props drilling
, 애매모한 분리기준
, 5단계나 되는 계층구조
등등의 단점들이 존재합니다. 추후 atomic 패턴을 적용해 나가면서 발생하는 문제들에 대해 기술할 예정입니다.
Reference
https://fe-developers.kakaoent.com/2022/220505-how-page-part-use-atomic-design-system/
https://velog.io/@teo/Atomic-Design-Pattern
좋은 글 감사합니다.