프로젝트/RESUMER

zustand를 활용한 팝업, 토스트 메세지

문앵 2025. 5. 24. 02:23

예전에 이삼다를 할때 팝업을 열심히 만들었던 기억이 있다. 나는 나름 3중 팝업 만든다고 열심히 손수 만들었는데,

나중에 과장님께서 만든 팝업 컴포넌트를 보고 나니 내 코드는 확장성이나 재활용성을 전혀 고려하지 않은 코드였다는걸 알게 됐다.

 

팝업이나 토스트 메세지같이 모든 화면에서 사용할 수 있는 컴포넌트는 당연히 전역으로 관리하는게 좋다.

루트 레이아웃에 컴포넌트를 넣어주고

popupStore 와 toastStore 를 각각 만들어준다.

 

코드를 짤때 주요 포인트들은 다음과 같았다.

 

1. 새로고침이나 브라우저를 다시 열었을 때 유지 되어야하는 session과 달리

팝업이나 메세지등은 당연히 초기화 되는게 맞기 때문에 그냥 create 해줬다.

 

 

 

2. 인터페이스 가독성이 은근 안좋아서.

팝업 내부에 들어가는 컨텐츠 타입 따로 && extends 팝업 동작 컨트롤하는 애들 따로 만들어줬다

이러면 showPopup 에 들어가는 인자값 타입도 중복을 줄일수 있어서 좋다.

토스트 메세지도 마찬가지로 분리.

 

// Popup

interface PopupProps {
    type?: "info" | "confirm";
    title: string;
    message: string;
    onConfirm?: () => void;
    onClose?: () => void;
}

interface PopupState extends PopupProps {
    isOpen: boolean;
    showPopup: (params: PopupProps) => void;
    closePopup: () => void;
}

 

// Toast

type ToastType = 'success' | 'error' | 'info';

export interface Toast {
  id: string;
  message: string;
  type: ToastType;
}

interface ToastStore {
  toasts: Toast[];
  addToast: (message: string, type?: ToastType) => void;
  removeToast: (id: string) => void;
}

 

 

 

3. toast 상태값을 배열 형태로 만들어주고 클릭을 할때마다 배열에 토스트 객체가 추가되게 만들어줬다.

이 배열 상태값을 가지고 tsx 를 만들어주면 여러개의 토스트 메세지가 동시에 존재할 수 있다.

// Toast 컴포넌트

<div className="fixed top-40 left-1/2 -translate-x-1/2 z-[9999] flex flex-col gap-2">
      {toasts.map((toast) => (
        <div
          key={toast.id}
          className={clsx(
            'min-w-[200px] text-center px-4 py-2 rounded shadow-md text-white transition-all duration-300 ease-in-out text-sm',
            toast.type === 'info' && 'bg-green-500/75',
            toast.type === 'error' && 'bg-red-500/75',
            toast.type === 'success' && 'bg-blue-500/75'
          )}
          onClick={() => removeToast(toast.id)}
        >
          {toast.message}
        </div>
      ))}
    </div>

 

 

반응형

'프로젝트 > RESUMER' 카테고리의 다른 글

[resumer] prisma 외래키 설정  (1) 2025.05.29
[resumer] zustand persist 사용, 커링 currying  (0) 2025.05.20