Skip to content

대시보드 Jotai 상태 관리

Won Kim edited this page Nov 3, 2024 · 1 revision

대시보드는 Trello와 같은 Kanban 스타일 보드에서 다양한 카드와 컬럼을 생성, 편집, 삭제할 수 있는 기능을 제공합니다. Jotai는 간단한 원자(atoms)를 사용하여 상태를 추적하고 이 상태를 바탕으로 컴포넌트의 상태를 업데이트합니다. 이 상태 관리 방법을 중심으로 코드를 설명하겠습니다.

1. Atom 정의

Jotai에서 Atom은 컴포넌트가 사용할 수 있는 상태의 가장 작은 단위입니다. 이 코드는 여러 가지 Atom을 정의하여 각각의 상태를 관리하고 있습니다.

주요 Atom 정의

  • dashboardCardUpdateAtom: 카드가 업데이트되는지 여부를 나타내는 boolean 상태.
  • currentDashboardIdAtom: 현재 대시보드의 ID를 추적하기 위한 상태.
  • currentColumnListAtom: 현재 대시보드에 있는 모든 컬럼의 리스트 상태.
  • resetColumnListAtom: 특정 대시보드 ID로 현재 컬럼 리스트를 초기화하는 데 사용되는 atom입니다. 특정 대시보드를 선택하면 이 atom을 통해 해당 대시보드의 컬럼 리스트를 초기화합니다.
  • columnCardsAtom: 각 컬럼의 카드 상태를 관리하는 객체로, 컬럼별 카드 리스트 및 추가 카드 로딩 여부, 카드의 전체 수 등을 추적합니다.
export interface ColumnCards {
  [columnId: number]: {
    cards: ICard["cards"];
    hasMore: boolean; // 추가 로딩할 카드가 더 있는지 여부
    cursorId: number | null; // 카드의 마지막 아이디를 통해 다음 카드 로딩을 결정
    totalCount: number; // 카드의 전체 개수
  };
}

export const columnCardsAtom = atom<ColumnCards>({});

모달 상태 관리

  • **initiModalState**와 ModalStateAtom: 모달들의 상태를 한 곳에서 관리합니다. 예를 들어 카드 생성 모달, 카드 수정 모달, 컬럼 생성 모달 등이 있는데, 각 모달의 열림 여부를 boolean 값으로 추적합니다.
export const initiModalState = {
  createDashboard: false, // 대시보드 생성 모달
  createCard: false, // 할 일 카드 생성 모달
  detailCard: false, // 할 일 카드 상세 모달
  updateCard: false, // 할 일 카드 수정 모달
  createColumn: false, // 컬럼 생성 모달
  editColumn: false, // 컬럼 수정 모달
  invitationDashboard: false, // 대시 보드 초대 모달
  deleteModal: false, // 알람 모달
};

export const ModalStateAtom = atom(initiModalState);

이러한 atom들은 대시보드 애플리케이션에서 모달의 열림 여부를 관리하는 데 사용됩니다.

삭제 모달과 관련된 상태

  • DeleteModalStateAtom: 삭제 모달에서 어떤 제목을 보여줄지와 삭제를 확인했을 때 실행될 콜백 함수를 저장하는 데 사용됩니다.

컬럼과 카드에 관련된 상태

  • ColumnAtom: 특정 컬럼의 ID와 제목을 추적하기 위한 상태.
  • CardIdAtom: 상세 카드 모달을 열 때 특정 카드의 ID를 추적하는 상태.

2. Jotai를 사용하는 컴포넌트

DashboardDetail 컴포넌트

DashboardDetail 컴포넌트는 대시보드의 상세 내용을 보여주며, 여기서 컬럼 및 카드들을 렌더링합니다. 이 컴포넌트에서 Jotai를 사용하여 상태를 관리하고 있습니다.

  • 컬럼 초기화 및 설정: 대시보드를 선택할 때 **setResetColumnList**로 컬럼 리스트를 초기화합니다.

    useEffect(() => {
      if (dashboardId) {
        setResetColumnList(dashboardId);
      }
    }, [dashboardId, setResetColumnList]);
  • 컬럼 데이터 가져오기: getColumn 함수는 선택한 대시보드의 컬럼을 가져와 **setCurrentColumnList**에 설정합니다. 이를 통해 렌더링할 컬럼 리스트를 업데이트합니다.

    setCurrentColumnList(
      columns.map((column: IColumnData) => ({
        id: column.id,
        title: column.title,
      }))
    );
  • 카드 업데이트 시 실시간 반영: isCardUpdate 상태가 true일 때 **getColumn**을 호출하여 카드 리스트를 다시 가져오고, 이후 **isCardUpdate**를 false로 설정합니다.

    useEffect(() => {
      if (isCardUpdate) {
        getColumn();
        setIsCardUpdate(false);
      }
    }, [getColumn, isCardUpdate, setIsCardUpdate]);
  • 드래그 앤 드롭 처리: onDragEnd 함수는 드래그 앤 드롭 라이브러리를 사용하여 카드가 드래그되어 이동되었을 때의 로직을 처리합니다. 여기서 카드의 위치를 변경하고, 해당 상태를 Jotai의 **columnCardsAtom**과 **columnList**에 반영합니다.

    setColumnCards(updatedColumnCards);
    setColumnList(updatedColumnList);

ColumnList 컴포넌트

ColumnList 컴포넌트는 각 컬럼과 그 안의 카드들을 보여줍니다. 여기서 무한 스크롤을 사용해 카드를 더 로딩하고, 컬럼의 수정 및 카드의 세부 내용을 확인하는 기능을 제공합니다.

  • 카드 추가 로드: loadMoreCards 함수는 특정 컬럼의 카드가 더 필요할 때 호출되어 새로운 카드를 불러옵니다. 상태를 업데이트하면서 현재 로딩 여부를 isLoading 상태로 관리합니다.

    const loadMoreCards = useCallback(async () => {
      if (!currentColumn.hasMore || isLoading || !currentColumn.cursorId) return;
      setIsLoading(true);
      
      // API 요청을 통해 새로운 카드 가져오기
      // ...
      
      setIsLoading(false);
    }, [columnId, currentColumn.hasMore, currentColumn.cursorId, isLoading, setColumnCards]);
  • Intersection Observer: **useEffect**를 사용하여 Intersection Observer를 설정하고, 컬럼의 마지막 요소가 화면에 보일 때마다 새로운 카드를 불러옵니다.

    useEffect(() => {
      const observer = new IntersectionObserver(
        (entries) => {
          if (entries[0].isIntersecting && currentColumn.hasMore && !isLoading) {
            loadMoreCards();
          }
        },
        { root: null, rootMargin: "50px", threshold: 0.1 }
      );
      
      // observer 설정 및 정리 로직
      // ...
    }, [currentColumn.hasMore, isLoading, loadMoreCards]);

요약

대시보드는 Jotai를 사용하여 대시보드의 상태모달 상태, 컬럼 및 카드 상태를 관리합니다. 주요 상태들은 Atom으로 정의되어 있고, 이를 컴포넌트에서 사용하여 대시보드의 변경 사항을 반영합니다.

주요 Jotai 활용 패턴

  1. Atom을 사용한 상태 분리: 상태를 각각의 작은 단위로 분리하여 각 컴포넌트가 필요한 상태만 가져다 쓰게 합니다.
  2. useAtomuseSetAtom을 이용한 상태 변경: 컴포넌트에서 특정 상태를 읽거나 설정할 때 Jotai 훅을 사용합니다.
  3. 콜백 함수와 useEffect를 통한 비동기 데이터 로딩: 상태를 비동기적으로 업데이트하며, Intersection Observer를 사용해 필요한 경우에만 데이터를 불러옵니다.