추상화된 다이얼로그 구축기 + location

ddoachi·2025년 4월 15일

TekaPicker

목록 보기
4/30

Dialog 구현

1. 최초 다이얼로그 구현

  • 각 다이얼로그를 페이지 컴포넌트처럼 route에 등록함
  • ex) /login<LoginDialog /> 렌더링
  • URL을 직접 /login으로 이동하여 다이얼로그처럼 보이게 처리함
  • useLocation()에서 statesearch 등을 통해 데이터 넘겨줌
navigate('/login', {
  state: { someData },
  search: '?mode=fast'
});

2. DialogRenderer 도입

  • 다이얼로그 전용 라우팅을 추상화하기 위해 DialogRenderer 컴포넌트를 만듦
  • pathname에 따라 dialogMap에서 컴포넌트를 가져와 동적으로 렌더링함
const dialogMap = {
  '/login': {
    component: LoginDialog
  }
}

3. dialogMap 확장

  • 다이얼로그별로 onConfirm 핸들러를 설정할 수 있도록 구조 확장함
  • ex) 로그인 다이얼로그에선 로그인 처리 핸들러를 별도로 등록 가능
'/login': {
  component: LoginDialog,
  onConfirm: (data) => { ... }
}

4. DialogProps<T> 제네릭 정의

  • 다이얼로그마다 입력값 구조가 다르므로 제네릭 도입함
  • 공통 Props 타입에 onConfirm: (data: T) => void 형태로 선언함
export interface DialogProps<T> {
  open: boolean;
  onClose: () => void;
  onConfirm: (data: T) => void;
  state?: any;
  query?: URLSearchParams;
}

5. ConfirmHandlers / DialogDataMap 분리

  • 다이얼로그마다 입력값 구조를 명확히 정의하기 위해 매핑 구조 도입함
type DialogDataMap = {
  '/login': { email: string; password: string };
  '/invite': { userId: string; step: number };
}

type ConfirmHandlers = {
  [P in keyof DialogDataMap]: (data: DialogDataMap[P]) => void;
}

6. onConfirm 핸들러 추론 자동화

  • 다이얼로그에서 사용할 handleConfirm을 타입 추론 기반으로 작성함
  • typeof path를 기반으로 현재 다이얼로그의 인자 타입 추출
type confirmArg = DialogDataMap[typeof path];
  • 이렇게 추론된 data를 그대로 confirmHandler?.(data)로 전달함

7. 최종 구조 정리

  • DialogRenderer는 다음을 처리함:

    • useLocation()으로부터 state/query 분리
    • pathname 기반 다이얼로그 컴포넌트 동적 결정
    • onConfirm 핸들러 타입 안전하게 추론
    • 다이얼로그 닫기 처리 후 navigate(-1)
  • 다이얼로그 추가 시에는 dialogMap에만 등록하면 됨

  • 다이얼로그 내부에서는 props.onConfirm?.({ ... }) 호출하면 됨

✅ 장점

  • 다이얼로그 별 입력 구조 자동 추론 가능
  • onConfirm 타입 미스 방지
  • 새로운 다이얼로그 추가 시 타입 자동 추론
  • query/state 같이 전달하여 유연한 다이얼로그 구현 가능

🔚 마무리

  • 이 구조는 MSA UI 구조나 페이지 내 다중 다이얼로그 구성에도 확장 가능함
  • 타입 기반 UI 설계에 적합함

📦 useLocation()을 통한 다이얼로그 데이터 전달 방식

다이얼로그에 외부 데이터를 넘길 때 navigate()statesearch를 활용함

1. navigate로 이동 시 데이터 포함

navigate('/login', {
  state: { from: 'homepage' },
  search: '?redirect=dashboard'
});

2. DialogRenderer 내부에서 데이터 추출

const { pathname, search, state } = useLocation();
const query = new URLSearchParams(search);
  • statenavigate로 넘긴 임의의 객체
  • queryURLSearchParams를 이용해 문자열 파싱된 쿼리 객체

3. 다이얼로그 컴포넌트로 전달

<DialogComponent
  open={open}
  onClose={handleClose}
  onConfirm={handleConfirm}
  state={state}         // 전달된 state 그대로 넘김
  query={query}         // URLSearchParams로 파싱된 쿼리 객체
profile
내일도 풀스택

0개의 댓글