컴포넌트를 만드는 조금 다른 방법 1 - object

전에 내가 작성한 리액트 코드를 보면 수 많은 조건문이 많이 있다. 읽기도 어렵고 해당 페이지에 조건식이 많아져 화면에 대한 문맥 파악 자체가 힘들었다. 더 나은 코드 작성 방법을 찾다가 찾은 방법이다. 물론 이 방법이 정답은 아니다. 단지 동일한 관심사를 갖는 컴포넌트를 한 곳에서 담당하게 하는 방법중 하나일 뿐이다.

실제 프로덕션 환경에서 컴포넌트를 만들다 보면, 여러 경우에 따라 다른 컴포넌트를 보여줘야 하는 경우가 많다.

예를 들어 파일 다운로드 관련하여 준비, 진행, 완료라는 세 가지 타입을 가진 데이터를 내려준다고 해보자.

export enum DownLoadStatus {
  "ready" = "ready",
  "progress" = "progress",
  "complete" = "complete"
}

그리고 프론트에서는 이 상태에 따라 다른 컴포넌트를 보여줘야 한다.

그럼 아래와 같이 코드를 작성할 수 있을 것이다.

import React from 'react';

export function DownLoad({ status }) {
    ...logic
    
  if (DownLoadStatus.ready === status) {
    return <Loading />;
  }

  if (DownLoadStatus.progress === status) {
    return <Progress />;
  }

  return <Complete />;
}

아니면 이렇게도 작성할 수 있을 거 같다.

import React from 'react';

export function DownLoad({ status }) {
    ...logic

  return (
    <>
      {DownLoadStatus.ready === status && <Loading />}
      {DownLoadStatus.progress === status && <Progress />}
      {DownLoadStatus.complete === status && <Complete />}
    </>
  );
}

물론 이렇게 작성하여도 타입에 따라 알맞은 컴포넌트가 잘 동작한다.동작 화면. 전체 예제 코드는 안 궁금할거 같지만, 맨 아래 첨부해 본다.

하지만 아무리 봐도 우아하지 못한 방법인거 같다. 내가 만약 위처럼 코드를 작성해 놨다면 다른 동료 개발자는 또 저기에 수많은 조건식과 컴포넌트를 추가하며, 나중에는 저 컴포넌트는 더 길고 복잡하게 될 것이다.status만 넘겨주면 알아서 컴포넌트가 생성되면 안되나?!!

사실 이건 실제로 내가 객관식 보기 컴포넌트를 만들면서 했던 고민이다. 객관식 보기 컴포넌트는 초기 기획에는 3개의 상태가 존재했다. 예를 들어 숫자만 있는 보기, 테이블형 보기, 리스트형 보기이다. 하지만 추후 서비스가 고도화됨에 따라 더 많은 리스트 컴포넌트가 생길 예정이었다. 그리고 서버에서도 보기에 따라 다른 타입의 데이터를 내려주고 있었다.

나는 위 사진의 After 부분처럼 컴포넌트를 만들기 위해 많은 것을 찾아봤고 훨씬 깔끔하게 동적으로 컴포넌트를 만드는 구조를 찾아냈다.

const StatusLookUpTable = {
  [DownLoadStatus.ready]: Loading,
  [DownLoadStatus.progress]: Progress,
  [DownLoadStatus.complete]: Complete
};

interface StatusProps {
  status?: DownLoadStatus;
}

export const Status: FC<StatusProps> = ({ status = DownLoadStatus.ready }) => {
  return React.createElement(StatusLookUpTable[status]);
};

물론 타입스크립트를 사용하긴 하지만, 실제 프로덕션 환경에서 개발하였다면, 한 번 더 위 코드에 타입 가드를 주는 것을 추천한다(프런트는 서버를 신뢰하는 동시에 적절한 방어 코드도 짜 놔야 한다고 생각한다).

export const Status: FC<StatusProps> = ({ status = DownLoadStatus.ready }) => {
  if (typeof StatusLookUpTable[status] !== "undefined") {
    return React.createElement(StatusLookUpTable[status]);
  }
  return <div>오류가 발생했습니다. 고객센터로 문의 바랍니다.</div>;
};

오랜만에 글을 쓰면서 두서없이 쓴 거 같긴 한데, 도움이 되었으면 좋겠다.

예제 코드)

https://codesandbox.io/s/how-to-create-react-dynamic-component-rig9z

Last updated