[FE-41] 3단계 라우트 골격 · 매칭/운영 하위 진입점

작업 내용 (설계 의도)

근거: 지원 관리 확장 FE 웹 설계 라우팅 · 내비게이션 (탭 구조 · 3단계 라우팅 흐름 · 라우트 등록) · 컴포넌트 트리 · Single Writer per File 검증 > 공통 파일 와이어업 배치.

변경 사항

  • web/src/routes.tsx각 단계의 wave 1 골격 티켓만 수정한다는 Single Writer 장치를 3단계에도 적용합니다. 이 티켓이 3단계 라우트를 전부 선언하고, 화면 티켓(FE-42·FE-43·FE-45)은 자기 페이지 파일만 대체합니다. 화면 티켓 6개가 각자 라우터를 건드리면 wave 2에서 머지 충돌이 확정입니다.
  • 3단계 라우트 3개를 lazy로 선언합니다 — /contact-events(연락 검토 목록 S-26), /contact-events/:contactEventId(연락 검토 상세 S-27), /settings/recommendation(추천도 가중치 S-28). 파라미터 이름은 계약의 contactEventId를 그대로 씁니다.
  • 각 라우트가 가리키는 “준비 중” 스텁 페이지를 함께 만듭니다. FE-42·FE-43·FE-45가 다음 wave에서 같은 파일을 구현으로 대체하므로 wave가 달라 충돌하지 않습니다(1·2단계의 AuthGate·서류 화면과 같은 기법).
  • 지원 탭의 활성 판정에 /contact-events*를 추가합니다. 연락 검토는 지원 도메인의 하위 화면이라 별도 탭을 만들지 않습니다.
  • 매칭 탭의 활성 판정은 이미 /settings*이므로 수정하지 않습니다/settings/recommendation이 자동으로 매칭 탭 하위로 들어옵니다.
  • 탭은 5개를 유지합니다. components/layout/NavTabs.tsx·AppShell.tsx는 이 티켓에서 수정하지 않습니다(단계 1 FE-22 소유). 3단계는 탭을 늘리지 않고 기존 탭의 하위 경로만 늘립니다.
  • 3개 라우트를 전부 AuthGate 안쪽에 둡니다. 디스코드 검토 요청 알림의 딥링크(/contact-events/:contactEventId)로 미인증 진입하면 로그인 화면을 거쳐 원래 경로로 복귀해야 하며, 이는 1단계 게이트 규약(state.from)을 그대로 승계합니다.
  • 등록되지 않은 하위 경로는 기존 NotFoundPage로 떨어집니다 — 3단계 때문에 404 처리를 바꾸지 않습니다.

의존

  • 선행 FE 티켓 없음 (단계 3 wave 1). FE-40과 서로 다른 파일을 건드리고 서로를 참조하지 않으므로 같은 wave에서 병렬 진행합니다.
  • BE 의존 없음 — 라우트 선언과 스텁은 API 계약과 무관합니다.

다이어그램

처리 흐름

sequenceDiagram
    participant User as 사용자
    participant Router as routes.tsx
    participant Gate as AuthGate
    participant Stub as 3단계 스텁 페이지
    User->>Router: /contact-events/:contactEventId 딥링크 진입
    Router->>Gate: 보호 라우트 매칭
    Gate-->>User: 미인증이면 /login (state.from 보존)
    User->>Gate: 로그인 성공
    Gate->>Stub: 원래 경로로 복귀
    Stub-->>User: 준비 중 (후행 wave가 대체)

컴포넌트 의존

flowchart LR
    Routes[routes.tsx] --> Gate[AuthGate]
    Gate --> Shell[AppShell · NavTabs 미수정]
    Routes --> ListStub[ContactEventListPage 스텁]
    Routes --> DetailStub[ContactEventDetailPage 스텁]
    Routes --> WeightStub[RecommendationWeightPage 스텁]
    ListStub --> FE42[FE-42가 대체]
    DetailStub --> FE43[FE-43이 대체]
    WeightStub --> FE45[FE-45가 대체]

테스트 케이스

  • /contact-events로 이동하면 연락 검토 목록 스텁이 렌더되고 앱 셸(탭)이 함께 보인다.
  • /contact-events/42로 이동하면 상세 스텁이 렌더되고 contactEventId 파라미터가 42로 파싱된다.
  • /settings/recommendation으로 이동하면 가중치 스텁이 렌더되고 매칭 탭이 활성으로 표시된다.
  • /contact-events에 있을 때 지원 탭이 활성으로 표시되고 매칭·운영 탭은 활성이 아니다.
  • 탭 개수가 5개로 유지되고 3단계 진입점 때문에 탭이 추가되지 않는다.
  • 미인증 상태에서 /contact-events/42로 진입하면 로그인 화면이 보이고, 로그인 성공 후 /contact-events/42로 복귀한다.
  • 등록되지 않은 /contact-events/42/unknown 경로는 기존 NotFoundPage로 떨어진다.
  • 3단계 스텁 페이지를 다크 모드로 렌더하면 시맨틱 토큰 class만 사용하고 하드코딩 색이 0건이다.