이전에 컴포넌트 UI구성에 있어서 Atomic Pattern을 도입할 것을 예고 하였습니다. Atomic패턴
을 도입함으로써 장단점등 경험했던 것들을 작성하고자 합니다. Atomic패턴에 대해 궁금한 사항이 있으시면 이전 글 Atomic Pattern을 참고해주세요.
디자인 패턴을 본격적으로 도입하기 위해서 컴포넌트 설계부터 철저하게 할 필요가 있었습니다. 저번 글에서 사용했던 Idol정보에 대한 Card입니다. 이 카드의 경우 어떠한 방식으로 컴포넌트 설계를 할 수 있을까요??
저는 이러한 구조를 이용하여 설계를 하였습니다. 그리고 Card안의 3가지 요소에 대해 molecules
로 분류를 하였습니다. 곧 세 요소를 합친 Card는 Organism
으로 보았습니다.
molecules를 구성하기 위한 atoms
들은 위와 같이 기본적인 html시멘틱 태그들과 외부 라이브러리에서 제공하는 UI
를 기본 구성요소로 구성하였습니다.
/** ../atoms/input/InputAtom.tsx*/
import { Input, InputProps } from "@chakra-ui/react";
import React from "react";
import { UseFormRegisterReturn } from "react-hook-form";
interface InputAtomProps extends InputProps {
register?: UseFormRegisterReturn;
}
const InputAtom = ({
placeholder,
size,
onChange,
fontFamily,
w,
h,
fontSize,
margin,
register,
type,
accept,
cursor,
pos,
opacity,
}: InputAtomProps) => {
return (
<Input
placeholder={placeholder}
accept={accept}
cursor={cursor}
pos={pos}
opacity={opacity}
size={size}
type={type}
onChange={onChange}
fontFamily={fontFamily}
w={w}
h={h}
fontSize={fontSize}
margin={margin}
{...register}
/>
);
};
export default InputAtom;
저 중 InputAtoms.tsx
를 살펴보겠습니다. input 프로퍼티의 타입을 지정해 놓고 그때 그때 상황에 맞게 custom하도록 하였습니다.(보통은 styled-component를 사용하는 경우가 많았음.)
위의 설계했던 3가지 요소를 합쳐 만든 Card컴포넌트가 IdolInfoCard입니다. Flex박스에 Organism들을 모아 놓습니다. soloTemplate의 경우에는 organism요소가 하나밖에 필요하지 않았습니다.
반대로 GroupMemberTemplate은 MemberSection을 추가된 구조입니다. 앞에서 IdolInfoCard의 props를 주입하여 재사용도 하는 것을 확인 할 수있었습니다.
import SoloTemplate from "@/component/template/SoloTemplate";
import { getIdolSolo, getIdolSoloAlbum } from "@/utils/API/SSGSetting";
import { SoloType, albumType } from "@/utils/interface/interface";
import React from "react";
interface SoloPageProps {
searchParams: { idol: string };
}
const SoloPage = async ({ searchParams }: SoloPageProps) => {
const idolName: string = searchParams.idol;
const soloData: SoloType = await getIdolSolo(idolName);
const albumData: albumType[] = await getIdolSoloAlbum(idolName);
return <SoloTemplate soloData={soloData} albumData={albumData} />;
};
export default SoloPage;
마지막으로 Pages
입니다. Page는 가장 큰 단위로 모든 요소들을 모아놓은 구조입니다. 결론적으로 클라이언트에게 보여지는 모습입니다. page에서는 data를 fetching해오고 그 data를 구성요소들에게 주입
하였습니다. 저의 경우 nextJs의 sever Component에서 data를 fetching을 하였습니다.
또한 Page의 경우 폴더를 따로 구성할 수 있었지만 nextJs의 폴더 기반 page routing으로 그대로 구성하였습니다.
html 태그를 좀 더 sementic
하게 세팅할 수 있었습니다.
기존의 코드에서 리팩토링 과정에서 의미없는 html 태그 등을 남발했던 것을 atomic패턴을 사용하니 이런 의미없는 태그 사용을 쉽게 발견하고 효율적으로 코드를 줄여 나갈 수 있었습니다.
atoms사용에서의 유연성
input이나 button사용에 있어서 경우에 따라 컴포넌트를 따로 구성할 필요가 없어서 유연성이 높고 재사용할 수 있었습니다.
프로퍼티에 따라 커스텀이 가능하였음.
직관적인 컴포넌트 네이밍
보다 컴포넌트 설계에 있어서 치밀해야 하는 부분이 있었기 때문에, 각각 구성되어 있는 컴포넌트의 네이밍을 직관적으로 하여 팀 협업시에 효율적인 부분이 있을 수 있겠다는 생각을 하게 되었습니다.
모호한 컴포넌트 구성 기준
다음 사진에서 IdolInfoCard와 MemberSection, 즉 Organism 컴포넌트들이 구성되어 있습니다. MemberCard를 보면 MemberSection의 Molecules로 구성되어 있습니다. 뭔가 이상한 느낌이 오신다면 눈썰미가 좋으신 것입니다. 저는 처음 Card단락을 Oragnsims으로 구분해 놓았습니다.
구분 요소가 달라 결국 MemberCard 네이밍을 변경하고 Molecules폴더로 분리하여 작업을 하였습니다. 다른 Reference에서는 Card를 더 작은 단위로도 봅니다. 결국 보는 사람마다 기준이 다르기 때문에 컴포넌트 구성에 있어서 같이 협업을 한 사람이 아니라면 기준이 다를 수 있습니다.
이렇듯 보통 직접적인 데이터 주입을 받지않는 atoms,molecules,organisms
의 분기를 결정하는 것은 어려운 일입니다. 협업 과정에서 설계에 있어서 시간적 비용
이 많이 소요가 될 것 같습니다.
데이터 주입시 Props Drilling문제
import SoloTemplate from "@/component/template/SoloTemplate";
import { getIdolSolo, getIdolSoloAlbum } from "@/utils/API/SSGSetting";
import { SoloType, albumType } from "@/utils/interface/interface";
import React from "react";
interface SoloPageProps {
searchParams: { idol: string };
}
const SoloPage = async ({ searchParams }: SoloPageProps) => {
const idolName: string = searchParams.idol;
const soloData: SoloType = await getIdolSolo(idolName);
const albumData: albumType[] = await getIdolSoloAlbum(idolName);
return <SoloTemplate soloData={soloData} albumData={albumData} />;
};
export default SoloPage;
pages에서 data fetching이후 요소들에게 data를 주입할 때 5단계의 atomic pattern구성으로 인해 props drilling
문제가 생길 수 있게 됩니다. 그렇기 때문에 상태관리 라이브러리를 이용하거나 서버데이터의 경우 react-query + custom hook을 사용하여 해결하는 것이 현명해 보입니다.
현재 계속해서 다른 페이지에도 atomic pattern
을 적용하며 컴포넌트를 구성하고 있습니다. 저 혼자하는 프론트엔드 역할을 맡아 하기 때문에 혼자 컴포넌트를 설계하고 네이밍을 하고 있지만, 팀 단위 협업을 하는 과정에서는 많은 커뮤니케이션 비용이 발생할 것으로 보입니다.
또한 현재 atomic패턴의 5단계의 구성보다 좀 더 줄여 3가지 단계를 구성한다던지 기존의 문제점을 해결하고 있습니다.
Naver Line에서 도입한 atomic패턴
세간에서도 atomic패턴이 좋다 나쁘다, 어떻게 봐야한다 의견이 엇갈리고 있고 제가 atomic패턴을 적용하기 위해 참고한 reference에서도 방식이 다양하였습니다.
사실 atomic패턴은 개발을 위해 만들어진 것이 아닌, 컴포넌트 구성에 있어서 도움을 주기 위해 화학용어를 빌려 사용한 것입니다.
마지막으로 결국 컴포넌트 설계에 대해 atomic패턴의 5단계 설계 방식에 집중하기 보다는 이를 참고하여 컴포넌트 설계, 네이밍 등 협업을 하는 것이 좋은 방식이라고 느껴집니다.
Reference
https://yozm.wishket.com/magazine/detail/1531/
https://jbee.io/react/stop-using-atomic-design/
https://www.youtube.com/watch?v=33yj-Q5v8mQ
글 재미있게 봤습니다.