🚨 만능 Input은 죄악이다.

‘준비물 챙겼어’에서 Input 컴포넌트 자체에 여러 가지 기능이 다 담긴 만능 Input 컴포넌트를 만들려고 했었다.

그러나 점점 기능들이 다양하고, 엮어있는 컴포넌트들이 다양해지면서 코드가 점점 스파게티가 되어가고 나중가서는 또 필요에 의해 변형해야 할 때 만능 Input이라면서, 해당 Input을 사용하지 않는 다른 Input을 써야 하는 케이스가 발생하기도 했다.

import {
  hasErrorMessage,
  hasLabelTextInProps,
  isShowErrorMessage,
  isShowValidationIcon,
} from "../policies/input";
import { StInput } from "../styles/input";
import { InputPropType } from "../types/input";
import CorrectIcon from "../../assets/icons/svg-input-correct-icon.svg?react";
import IncorrectIcon from "../../assets/icons/svg-input-incorrect-icon.svg?react";

export default function Input(props: InputPropType) {
  const {
    id,
    title,
    errorMessage,
    firstInputCheck,
    errorCondition,
    colorTheme,
    isViewMark,
  } = props;

  return (
    <StInput.Wrapper>
      {hasLabelTextInProps(title) && (
        <StInput.Label htmlFor={id} $colorTheme={colorTheme}>
          {title}
        </StInput.Label>
      )}
      <StInput.TextInputBox>
        <StInput.TextInput
          id={id}
          $colorTheme={colorTheme}
          $checkErrorMessage={hasErrorMessage(errorMessage)}
          {...props}
        />
        {isShowValidationIcon({
          firstInputCheck,
          errorMessage,
          isViewMark,
        }) && (
          <StInput.ValidIcon>
            {isShowErrorMessage({ firstInputCheck, errorCondition }) ? (
              <IncorrectIcon />
            ) : (
              <CorrectIcon />
            )}
          </StInput.ValidIcon>
        )}
      </StInput.TextInputBox>
      {isShowErrorMessage({ firstInputCheck, errorCondition }) && (
        <StInput.ErrorMessage>{errorMessage}</StInput.ErrorMessage>
      )}
    </StInput.Wrapper>
  );
}

결국 내 만능 Input은 실패작이었고, 언젠가 이 Input에 대한 리팩토링을 하자며 벼르고 있었다. 그리고 최근 Next.js로의 마이그레이션을 진행하게 되면서 그 벼르고 있던 숙원을 해결했다.

우선 위의 Input 코드를 모두 지웠다.

그리고 나무가 아닌 숲을 보는 전략으로 합성 컴포넌트 패턴을 이용해 Form 컴포넌트를 만들고 Input에 쓰인 요소들을 모두 담도록 변경했다.

이번 글은 그 ‘합성 컴포넌트 패턴’에 대한 이야기와 실제 프로젝트에서 어떤 식으로 리팩토링을 했는지, 그리고 그 적용한 예시 코드들을 보여주고자 한다.

❓ 그래서 우선 합성 컴포넌트 패턴이 뭔데?

여러가지 디자인 패턴에 대해서 정리된 Pattern.dev 글에 따르면 합성 컴포넌트 패턴을 ‘여러 컴포넌트들이 모여 하나의 동작을 할 수 있게 해 준다.’고 말하고 있다.

Compound 패턴

또, 카카오 엔터테인먼트의 FE 기술 블로그에서는 합성 컴포넌트를 다음과 같이 이야기한다.

합성 컴포넌트 패턴은 하나의 컴포넌트를 여러 가지 집합체로 분리한 뒤, 분리된 각 컴포넌트를 사용하는 쪽에서 조합해 사용하는 컴포넌트 패턴을 의미합니다.

합성 컴포넌트로 재사용성 극대화하기 | 카카오엔터테인먼트 FE 기술블로그