너무 많은 State를 관리해야될때는 어떻게 하는게 좋을까?

robin Han·2025년 2월 9일
2

우선 여러가지의 전역으로 관리를 해주기 위해서는 여러방법 중

  • 라이브러리
  • Context API

정도가 있는것 같다.

문제는 Context Api는 부모로 부터 끝이없이 내려주면서 사용되야하기때문에 어느순간부터 더 복잡해지기도 하고 또한 상태값이 복잡하면 복잡할수록 처리해줘야되는 널/ undefine 처리가 필수로 요구될수있다 ...
우선적으로 도입하기 쉽고 전역상태관리자인 zustand를 사용하기로 했는데 우리 프로젝트의 상황이 맞는지 판단하고 싶어서 글을 작성하게 되었다.

현재 상황을 간단히 풀어보자면:

  • 모바일 청첩장을 만들때 필요한 엄창나게 많은 입력값들을 각각의 컴포넌포트내부의 상태값으로 사용되고
  • 저장을 할때 -> Post API 로 청첩장 생성을 할때, 한번의 모든 값을 보내줘야된다
  • 청첩장을 만들때는 3가지의 단계로 이루어져있고
  • 모바일 에서는 아니지만 웹에서는 미리보기가 옆에 나란히 표시되어 바로바로 수정된 입력들을 확인할수있다.
  • 만들어둔 청첩장을 수정을 할때는 해당 조회를해서 받은 응답을 다시 store에 저장해주는걸 보여주는 준다.

직접 격은 문제점과 생각되는 문제점으로 나누자면

직접격은 문제들

1) 너무너무너무 많은 값들을 한번에 처리해야되는 문제가 있다.

  //웨딩 정보
  const {
    address,
    jibunAddress,
    zonecode,
    weddingHallName,
    weddingHallDetail,
    coords,
  } = useAddressStore();
  const { optionalItems } = useAccordionStore();
  const findOrder = (feature: string) => {
    if (!feature) return undefined; // feature가 없으면 undefined 반환
    const result = optionalItems.find((value) => value.feature === feature);
    return result?.order;
  };

  const { selectedOptionalFeatures } = useOptionalFeatureStore();
  const { weddingTime, formattedDate } = useWeddingStore();
  const { greetingTitle, greetingContent } = useGreetingStore();
  const { contacts } = useContactStore();
  const { brideGroom } = useBrideGroomStore();
  const { invitationtitle } = useInvitationStore();
  const { rsvpTitle, rsvpDescription, rsvpIncludeMeal, rsvpIncludePopulation } =
    useRSVPStore();
  const { accounts } = useAccountStore();
  const accountList: AccountDetail[] = accounts.flatMap((item) => [
    {
      order: findOrder('account'),
      isActive: selectedOptionalFeatures.account,
      ...item.accountInfo,
    },
    {
      order: findOrder('account'),
      isActive: selectedOptionalFeatures.account,
      ...item.fatherAccountInfo,
    },
    {
      order: findOrder('account'),
      isActive: selectedOptionalFeatures.account,
      ...item.motherAccountInfo,
    },
  ]);
  const { selectedMusic } = useMusicFeatureStore();
  const { font } = useThemeStore();
  const { subCalendarFeatures } = useCalendarFeatureStore();
  const { subFeatures: transportData, transportationInputs } =
    useLocationFeatureStore();

우선 생성하는 일부분만 확인 하더라도 코드가 너무길어지는 문제가있었다, 수정하는 기능을 넣은 상태값들 까지 포함 시킨다면 너무길어서 값들을 하나씩 확인하면서 일일이 검사하는 과정을 거쳐야되며 오류가 발생했을 또한 어디서 에러가 생기는지 값들을 다 확인해야되는 경우가 빈번히 일어났다.

그래서 생각했던 방법이 react hook form으로 한번에 관리 하는 방법이 있지 않을까 고민하게 되었다. 하지만 안되는 이유가 2가지 정도있었는데

  1. 일단 저장 버튼 즉 form을 submit하는 버튼이 헤더에있는 저장버튼 하나뿐이라서 지금 하고있는 방식보다 더 좋은 방법이 될수없다고 판단이 되었다.

  2. 미리보기를 처리할때 유저가 바로바로 입력(수정)된 정보를 볼수있어야하는데, 이또한 form으로는 제한적이였다.

    1번의 문제점은 버튼을 여러단계로 거칠수있는 버튼을 추가적으로 만들어서 할수있다

    만들기 버튼 클릭 -> 이름 입력 모달 -> API 생성 호출 -> 1단계 입력 -> 다음버튼 누를시 API 수정 호출 -> 2단계 동일-> 3단계 동일.
    이렇게 되면 3단계를 거쳐 나누어서 API를 보낼수있고, 또한 값들도 나누어서 사용할수있게 되니 부담이 덜하다

조금 걱정되는 부분은 API 호출이다, 위에 방식처럼 진행을 하다보면 단계를 변경할때 마다 조회호출을 요청해야되면 요청수 자체는 늘어나게 되기때문에 해당 부분은 백엔드에 부담을 줄것인지 프론트에 부담을 줄것인지에 따라 달라질것 같다.

단계별로 처리를 하게되면 입력된 값들에 대한 일관성과 무결성이 가장 중요하게 생각되야되는분 같다.

결론

개인적으로 단계별로 나누어서 백에 전달해주는 방법이 가장 좋은 방법이라고는 생각되지만 그렇게 된다면 구조적으로 백엔드와 프론트 둘다 코드가 많이 변경되야되는건 달라지지않는다. 폼으로 구현보다는 우선 단계를 거쳐서 나누어서 입력과 호출을 나누고, 하나의 기능이라고 오히려 한번에 처리할려고하는게 더 복잡하고 에러트래킹 데이터 확인에 너무 어려운부분이 많기때문에 문제를 오히려 나누어서 해결해야되는걸 배우는 계기가 되었다.

추가적인 잡생각

  • 입려에 대해 랜더링이 너무 많이 된다고 생각해 줄일수있는 방법중 디바운싱을 고민하게 되었는데. 이또한 한번에 여러값들을 디바운싱하게 된다면 오히려 랜더링을 줄일려다가 값들이 일치하지않을 수있다는생각이 들었다.그래서 단계별로 나누어 디부운싱을 온체인지에 넣어서 다음단계를 눌렀을때 저장하게 하면 해결할수있다고 생각된다.

2개의 댓글

comment-user-thumbnail
2025년 2월 14일

겪은 문제에 대한 고민이 잘 보이네요! 어떤게 좋은 방향일지 저도 한번 생각해볼 수 있는 글이었습니다 👍

답글 달기
comment-user-thumbnail
2025년 2월 14일

좋은 정보 감사합니다!

답글 달기