가장 먼저, 이번 먹팟 프로젝트엔 프론트엔드로 3명이 참여했기 때문에 각자 어디까지 담당할 지를 나누어야 했다.
그래서 회의를 통해 사용할 기술 스택을 선정한 이후엔 다른 프론트엔드 파트 팀원들이 셋업을 준비해주었고 나는 글로벌 스타일 파일을 만들었다.
어느 정도 프로젝트 셋업이 끝난 후에 공통 인풋 개발을 위해 역할을 분배했다.
여기서 어려웠던 점은 어디까지가 공통 컴포넌트의 영역인지 구분하는 것이었는데, 그래서 공통 컴포넌트인 Input은 가장 먼저 Figma 디자인 시스템 파일에 주어진 status별 Input 디스플레이를 구현하는 것을 목표로 했다.
Input의 요구 사항은 다음과 같았다.
디자인 시안을 보고 가장 먼저 하나의 인풋 컴포넌트에서 모든 사이즈의 인풋에 대응하려 했다.
그 목표를 달성하기 위해 3가지 사이즈로 대응하는 방법을 적용했다. 그런데 개발 도중에 vanilla-extract에 미숙한 탓에 난관에 부딪혔다.
이 두 문제는, vanilla-extract의 recipe variants를 사용해 해결할 수 있었다. variants를 설정하면, 컴포넌트의 Props로 size, color등을 넘겨주어 조건부 css를 사용할 수 있다.
하지만 이후에 Input 컴포넌트가 Calendar나 Map등 다른 컴포넌트들과 복합적으로 쓰이게 되면서 size를 결정 짓는 width는 상속으로 처리했다.
대신, Input이 사용되는 case별로 type variants를 나누어 아래처럼 코드를 작성했다.
export const inputBase = recipe({
base: {
minWidth: '100%',
height: '56px',
fontSize: fontSize.md,
padding: space['lg'],
paddingRight: space['4xl'],
backgroundColor: color.grey50,
color: color.hint,
borderRadius: borderRadius.md,
border: `1px solid ${color.grey100}`,
selectors: {
'&::-webkit-search-cancel-button': {
display: 'none',
},
'&:not(:focus)': {
color: color.primary,
},
'&:not(:disabled):focus': {
color: color.primary,
border: `1px solid ${color.primary500}`,
},
},
},
variants: {
type: {
textArea: {
alignItems: 'flex-start',
padding: '16px',
gap: '8px',
height: '299px',
},
title: {
fontSize: fontSize.xl,
fontWeight: fontWeight.semibold,
},
search: {
paddingLeft: space['5xl'],
},
password: {},
},
},
});
useFormContext
를 사용해서 onSubmit시 필드 에러를 체크해 사용자가 변화를 인지할 수 있게끔 만들었다.const InputErrorMessage = ({ name, showError = true }: errorProps) => {
const { formState } = useFormContext();
const errorMessage = showError && (formState.errors[name]?.message as string);
return (
<Typography color="red500" variant="label5" as="p">
{errorMessage}
</Typography>
);
};
며칠 동안 컴포넌트를 작성하며 이런 저런 문제들을 발견하고, 초기 설계 접근 방향이 잘못되었다 생각해 다른 방식의 인풋 컴포넌트를 만들 방법을 구상했다.
그 중, 눈에 들어온 블로그 아티클.
드롭 다운은 팀원이 직접 구현한 공통 컴포넌트를 쓰겠지만 캘린더는 외부 라이브러리 사용이 예정되어있으므로 controller를 이용한 type별 인풋 컴포넌트 분리가 적절할거라 생각했다.
그래서 위 아티클을 참고해, 한 일주일~이주일 정도는 컴포넌트를 수정했다.
결국 나중 가선, 공통 ControllerInput 컴포넌트가 아니라 각각의 캘린더, 드롭다운을 Controller에 말아서 사용하는 페이지 단일 컴포넌트로 쓰긴 했지만 위에서 삽질하며 많은 도움을 얻을 수 있었다.
다음 시리즈에 이어서, 어떻게 최종까지 Input 컴포넌트를 개선시켜나갔는지 계속 적어보려 한다.
재렌더링 비용이 적은 폼 컴포넌트 만들기 | Blog by pumpkiinbell
react-hook-form과 MUI를 사용한 재사용성 있는 Input 공통 컴포넌트 만들기(TypeScript)
🛠 기술 스택 | |
---|---|
Framework | |
Styling | |
State Management | |
Testing | |
+ |