[개발 일지] 매직 포스 - 유저 form 컴포넌트 모듈화 & 코드 리팩토링

yesung·2024년 1월 9일
1

Today

  • Auth input, form 컴포넌트 모듈화 & 코드 리팩토링

유저 기능 코드 리팩토링

기존 Form 양식에 중복되는 input이 많다 보니 Form 전용 input을 재사용 하기 위해 별도의 컴포넌트로 분리하면 어떨까라는 생각을 했었다.

기존 코드

<input className="..." type="text" name="email" onChange={...} placeholder="이메일" />
<input className="..." type="password" name="password" onChange={...} placeholder="비밀번호" />

// 그 외에 input들...

개선 코드

const emailInput = {
    id: 1,
    name: 'email',
    type: 'text',
    placeholder: '이메일',
  };

const passwordInput = {
  id: 2,
  name: 'password',
  type: 'password',
  placeholder: '비밀번호: 최소 8자리 이상 25자리 이하 (알파벳, 특수문자 포함)',
};

const passwordConfirmInput = {
  id: 3,
  name: 'passwordConfirm',
  type: 'password',
  placeholder: '비밀번호 확인',
};
const businessNumberInput = {
  id: 4,
  name: 'businessNumber',
  type: 'text',
  placeholder: '사업자등록번호 (11자리)',
  minLength: 11,
  maxLength: 11,
  onKeyDown: onKeyDownHandler,
};

const inputOptions: Record<string, InputType[]> = {
  '/auth/login': [emailInput, passwordInput],
  '/auth/signup': [emailInput, passwordInput, passwordConfirmInput, businessNumberInput],
  '/auth/findPassword': [emailInput],
  '/auth/reset': [passwordInput, passwordConfirmInput],
};

const inputs = inputOptions[path];

return (
  <>
    {inputs.map((input: InputType) => {
      const key = input.name as keyof typeof value;
      if (input) {
        return (
          <input
            key={input.id}
            className={styles['input']}
            name={input.name}
            value={value[key]}
            onChange={onChangeHandler}
            type={input.type}
            placeholder={input.placeholder}
            minLength={input.minLength}
            maxLength={input.maxLength}
            onKeyDown={input.onKeyDown}
            required
            />
        );
      }
    })}
    </>
);

각 input 속성으로 들어 갈 내용들을 객체로 정리 하고 path 기준으로 배열로 분리했다. 훨씬 보기 간결하고 이해하기 쉬워졌으나 길어지는 건 마찬가지였다.

하지만, 해당 배열의 각 들어간 요소들을 map으로 출력해주니 input 요소는 한 개만 작성해도 되다 보니 마음이 편해졌다 😀

결론은 Form 컴포넌트 안에는 아래 한 줄만 추가하면 Form이 있는 경로 마다 input이 동적으로 변경된다.

<Input ... />

회원가입 & 로그인 Form 리팩토링

결국엔 Form도 계속 재사용을 해야 하기 때문에 각각의 불러올 데이터로 세분화 해서 Form으로 데이터로 보내줬다.

보낼 데이터들

import { useRouter } from 'next/router';
import AuthForm from './AuthForm';

type AuthObjectType = Record<string, string>;

const User = () => {
  const path = useRouter().pathname;

  const LOGIN_DATA = {
    url: '/auth/signup',
    subUrl: '/auth/findPassword',
    title: '편리함의 시작',
    subTitle: 'Magic Pos',
    subName: '비밀번호를 잊으셨나요?',
    caption: '아직 회원이 아니신가요? 회원가입하러 가기',
    buttonName: '로그인',
  };
  const SIGNUP_DATA = {
    url: '/auth/login',
    title: '편리함의 시작',
    subTitle: 'Magic Pos',
    caption: '이미 가입을 하셨나요? 로그인하러 가기',
    buttonName: '회원가입',
    subButtonName: '사업자등록번호 인증',
  };
  const FIND_PASSWORD_DATA = {
    title: '편리함의 시작',
    subTitle: 'Magic Pos',
    description: '가입하신 이메일을 입력해 주세요.',
    buttonName: '링크 전송',
  };
  const UPDATE_PASSWORD_DATA = {
    title: '편리함의 시작',
    subTitle: 'Magic Pos',
    buttonName: '비밀번호 변경',
    description: '새로운 비밀번호를 입력해 주세요.',
  };

  const AuthData: Record<string, AuthObjectType> = {
    '/auth/login': LOGIN_DATA,
    '/auth/signup': SIGNUP_DATA,
    '/auth/findPassword': FIND_PASSWORD_DATA,
    '/auth/reset': UPDATE_PASSWORD_DATA,
  };

  return <AuthForm data={AuthData[path]} />;
};

export default User;

Form으로 보낼 데이터들 또한, 객체 형태로 만들어서 집합 객체로 감싸주었고 Key를 path로 지정한 다음에 path가 들어오면 AuthData[path] 로 path의 key를 매칭해서 데이터를 보내준 형태로 작성했다.

만약 보여줘야할 Form이 늘어난다면 한 객체씩 추가를 해줘야하는 수고가 들긴 한다..

profile
Frontend Developer

0개의 댓글