tailwind css의 특성 상 코드가 끝없이 길어지는 건 자주 일어나는 일이다
또한 display : flex를 사용하다보면 div가 많이 사용되어 전체 코드를 봤을 때,
각 영역을 한눈에 구분하기가 어렵다
이로인해 전체 코드의 가독성이 떨어지게 된다!
그래서 오늘은
React + TypeScript + Tailwind를 사용할 때
재사용 가능한, 가독성 높이는 UI 컴포넌트 만드는 방법에 대해 이야기해보려한다!
저도 배우고 공부하고 있는 학생입니다
무조건 제 코드가 정답은 아닙니다 :)
전후 코드 비교해보기
개선하기 전 코드인 왼쪽을 봤을 때, 일단 가로로 무척 길어서 코드를 한 화면에 보기 어렵다
또한 div와 section이 얽혀있어 각각의 div와 section 이 어떤 영역인지 한 눈에 알아보기 어렵다
하지만 개선한 뒤 코드인 오른쪽을 보면 Wrapper,TextSection, Form으로
각 영역이 구분되어있어 어떤 영역인지 한 눈에 볼 수 있다
또한 반복되는 tailwind css 코드도 컴포넌트에 포함되어있기 때문에 className의 길이가 더 짧다
기존 코드
import InputForm from "@/components/common/InputForm";
import Button from "@/components/common/Button";
function FindId() {
return (
<div className="font-suite flex flex-col items-center justify-center w-full h-full px-[20px] gap-[30px]">
<div className="flex flex-col font-suite font-bold justify-start gap-[60px] w-full">
<section className="text-2xl ">
<div>기존에 가입한 계정의</div>
<div>이름과 이메일을 입력해 주세요.</div>
</section>
<section className="flex flex-col gap-[30px]">
<div className="flex flex-col gap-3">
<div className="text-xl">이름</div>
<InputForm holder={"이름"} />
</div>
<div className="flex flex-col gap-3">
<div className="text-xl">이메일</div>
<InputForm holder={"이메일"} />
</div>
</section>
<Button text={"아이디 찾기"} type={"GREEN"} />
</div>
</div>
);
}
export default FindId;
inputForm 도 입력 영역만 지정해뒀기 때문에 따로 input title div를 생성해야 했다
현재 내가 하고 있는 프로젝트의 input은 모두 title과 함께 사용되고 있기 때문에(반복되는 요소)
inputForm 컴포넌트 안에 title도 함께 묶어서 컴포넌트를 만들어야겠다고 생각했다(재사용 가능한 컴포넌트 생성)
Common.tsx
import React from "react";
// 가독성을 위해 만든 컴포넌트
// div가 너무 많아 영역 구분이 어려워서 만듦
interface FrameProps {
children: React.ReactNode;
className?: string;
}
// 전체 코드 감싸기(가운데정렬, 폰트, 높이 자동)
export const Wrapper = ({ children, className = "" }: FrameProps) => {
return (
<div className={`flex flex-col items-center justify-center h-screen w-full font-suite ${className}`}>
{children}
</div>
);
};
// 입력을 받는 부분
export const Form = ({ children, className = "" }: FrameProps) => {
return <div className={`flex flex-col ${className}`}>{children}</div>;
};
// 글씨가 써있는 영역(왼쪽정렬)
export const TextSection = ({ children, className = "" }: FrameProps) => {
return <div className={`flex flex-col justify-start ${className}`}>{children}</div>;
};
InputForm.tsx
interface InputBoxProps {
title: string;
holder: string;
titleClassName?: string;
className?: string;
type?: string;
}
const InputForm = ({ title, holder, titleClassName = "", className = "", type = "text" }: InputBoxProps) => {
return (
<div className="flex flex-col gap-3">
<div className={`${titleClassName}`}>{title}</div>
<input
type={type}
className={`grow shrink basis-0 font-suite rounded-xl py-3 px-4 text-cardLongContent bg-White text-lg justify-start items-center font-bold whitespace-nowrap w-full outline-none border-2 focus:border-yellow100 focus:border-yellow100 focus:ring-0.5 focus:ring-yellow100 ${className}`}
placeholder={holder}
></input>
</div>
);
};
export default InputForm;
개선한 코드
import InputForm from "@/components/common/InputForm";
import Button from "@/components/common/Button";
import { Wrapper, Form, TextSection } from "@/components/common/Common";
function FindId() {
return (
<Wrapper className="px-[20px] gap-[30px]">
<div className="flex flex-col font-bold gap-[60px] w-full">
<TextSection className="text-2xl">
<div>기존에 가입한 계정의</div>
<div>이름과 이메일을 입력해 주세요.</div>
</TextSection>
<Form className="gap-[30px]">
<InputForm title={"이름"} titleClassName="text-xl" holder={"이름"} />
<InputForm title={"이메일"} titleClassName="text-xl" holder={"이메일"} />
</Form>
<Button text={"아이디 찾기"} type={"GREEN"} />
</div>
</Wrapper>
);
}
export default FindId;
결과적으로, 전보다 훨씬 가독성 좋아진 코드를 만들었다!
'개발새발개발 > React' 카테고리의 다른 글
[React] 최적화하기 (Optimization) - useMemo, memo, useCallback (0) | 2025.02.19 |
---|---|
[React] Context 사용해서 props 없이 편하게 데이터 전달하기 (0) | 2025.02.18 |
[React] VSCode Prettier 적용 안됨 5가지 해결 방법 (2) | 2025.02.13 |
[React+Typescript] Todos 앱 만들기 (0) | 2025.02.11 |
[React+Typescript] Todos 앱만들기 화살표함수 주의 (0) | 2025.02.10 |
댓글