[FE-32] 서류 보관함 (계열 목록)

작업 내용 (설계 의도)

근거: 지원 관리 확장 FE 웹 설계 S-20 서류 보관함 (계열 목록)·컴포넌트 트리·상태 관리·API 연동 > 2단계·Single Writer per File 검증 > 단계 2 wave 2, 지원 관리 확장 TDD 2단계 — 지원 서류 API 계약(GET /api/documents/series).

변경 사항

  • 서류 보관함(S-20)을 구현합니다. 화면의 첫 질문은 “무엇을 올릴까”가 아니라 “무엇이 있나” 이므로, 유형 세그먼트 + 계열 카드 목록을 먼저 보여 주고 업로드는 하단 고정 CTA로 둡니다.
  • 계열 카드는 documentType 칩·seriesTitle·latestVersionNumber·versionCount·updatedAt을 한 줄 요약으로 노출합니다. 카드 탭의 주 액션은 계열 상세(S-21) 이동 하나뿐입니다 — 목록에 버전별 액션을 넣으면 카드가 비대해집니다.
  • 문서 유형 세그먼트는 URL search params가 SSOT입니다(useSearchParams). 전역 스토어·지역 state로 들고 있지 않아야 뒤로가기와 링크 공유가 동작합니다. 서버 데이터는 TanStack Query 캐시가 SSOT이며 스토어에 복사하지 않습니다.
  • 빈 상태를 2종으로 구분합니다. 전체 0건은 “아직 올린 서류가 없어요 / 이력서를 올리면 공고별 지원 추천도를 계산할 수 있어요”로 다음 행동의 이유를 설명하고 CTA를 화면 중앙에도 배치합니다. 유형 필터 0건은 “이 유형의 서류가 없어요” + [전체 보기]로 필터 해제 경로를 줍니다. 두 상태를 같은 문구로 합치면 사용자가 “내 서류가 사라졌나”로 오해합니다.
  • 에러 상태에서도 하단 업로드 CTA는 유지합니다 — 목록 조회가 실패해도 업로드 자체는 가능한 동작이기 때문입니다.
  • DocumentTypeChipwave 1의 FE-30이 소유합니다 — S-20·S-21·S-25 3곳(FE-32·34·37)이 같은 wave에서 쓰므로 정의를 선행 wave로 올렸습니다. 이 티켓은 import만 하고 수정하지 않습니다.
  • 업로드 CTA는 자리(버튼과 빈 상태 배치)만 만들고 시트 배선은 하지 않습니다. DocumentUploadSheet는 같은 wave의 FE-33이 소유하므로, 같은 wave 두 티켓이 서로의 파일을 수정하는 상황을 피하기 위해 연결은 wave 3의 FE-38이 수행합니다. 이 티켓에서는 CTA 클릭 핸들러를 확장 가능한 형태로 비워 둡니다.
  • 로딩은 카드 스켈레톤 3개로 처리하되 세그먼트와 CTA는 즉시 렌더합니다 — 조작 가능한 영역이 늦게 나타나면 화면이 멈춘 것처럼 보입니다.

의존

  • FE-30 — DocumentType·DocumentSeriesResponse 타입, 계열 목록 queryKey, MSW 목.
  • FE-31 — /documents 라우트와 스텁 페이지. 이 티켓이 스텁을 대체합니다.
  • BE-61 — GET /api/documents/series 구현.
  • FE-33 — 업로드 시트 자체. 단 배선은 FE-38이 하므로 이 티켓의 착수를 막지 않습니다.

다이어그램

처리 흐름

sequenceDiagram
    participant User as 사용자
    participant Page as DocumentSeriesListPage
    participant Hook as useDocumentSeries
    participant Api as GET documents/series
    User->>Page: 지원 탭 > 서류 진입
    Page->>Hook: documentType(URL param)로 조회
    Hook->>Api: GET series
    Api-->>Hook: series[]
    Hook-->>Page: 캐시 데이터
    Page-->>User: 유형 칩 + 계열 카드 목록

컴포넌트 의존

flowchart LR
    Page[DocumentSeriesListPage] --> Segment[DocumentTypeSegment]
    Page --> Hook[useDocumentSeries]
    Hook --> Api[fetchDocumentSeries]
    Api --> Types[DocumentSeriesResponse]
    Page --> Card[DocumentSeriesCard]
    Card --> Chip[DocumentTypeChip]
    Card --> Ui[Card · Chip · Button]
    Page --> Cta[BottomActionBar 업로드 CTA]

테스트 케이스

  • 계열 3건이 내려오면 각 카드에 유형 칩·계열 제목·v{최신버전}·버전 개수·갱신일이 보인다.
  • 계열 카드를 탭하면 /documents/series/{seriesId}로 이동한다.
  • 유형 세그먼트에서 이력서를 선택하면 URL search param이 갱신되고 그 유형으로 재조회된다.
  • 유형 세그먼트 선택 후 뒤로가기를 하면 이전 유형 필터 상태로 복귀한다(URL이 SSOT).
  • 전체 0건이면 “아직 올린 서류가 없어요”와 추천도 안내 문구가 보이고, “이 유형의 서류가 없어요”는 보이지 않는다.
  • 유형 필터를 건 상태에서 0건이면 “이 유형의 서류가 없어요” + [전체 보기]가 보이고, 전체 빈 상태 문구는 보이지 않는다.
  • [전체 보기]를 누르면 유형 필터가 해제되고 전체 목록으로 재조회된다.
  • 목록 조회가 5xx로 실패하면 ErrorState[다시 시도]가 보이고 하단 업로드 CTA는 그대로 유지된다.
  • 로딩 중에는 카드 스켈레톤이 보이되 유형 세그먼트와 하단 CTA는 즉시 렌더된다.
  • DocumentTypeChip이 유형 4종에 대해 각각 한국어 라벨을 렌더한다.
  • 목록·카드·칩이 .dark 클래스 환경에서 렌더되고 하드코딩 색을 0건 사용한다.