목록에서 상세로
목록의 탐색 조건과 선택 맥락을 상세 화면까지 보존합니다.
목표
목록에서 대상을 찾고 상세 내용을 확인한 뒤 다시 목록으로 돌아오는 동안 검색, 필터, 정렬, 페이지, scroll과 선택 위치를 보존한다. 화면 이동을 새로운 시작으로 만들지 않고 하나의 이어진 작업으로 만든다.
선택 기준
- 여러 record 가운데 하나를 선택해 독립된 상세 route에서 검토하거나 편집할 때 사용한다.
- 비교가 핵심이면 상세 route를 반복 이동하기보다 table, split view 또는 비교 패턴을 검토한다.
- 상세 내용이 매우 짧고 현재 목록과 함께 봐야 하면 side panel을 사용할 수 있다.
- 여러 단계 편집이나 중요한 저장이 포함되면 독립 route가 더 안전하다.
기본 구조
목록
PageHeader: 화면 목적과 주 생성 행동PageToolbar: 검색·필터·정렬·새로고침- 결과 요약: 결과 개수, 적용 범위, 마지막 갱신
- record list 또는
Table - loading, empty, error가 같은 결과 frame 안에서 교체
상세
PageHeader.backAction: 돌아갈 목록의 이름- title: 선택한 record의 사람이 이해할 이름
- badge와 meta: 상태, 소유자, 저장 시각
- 제한된 주 행동
- 세부 section
이동과 맥락 보존
- 검색어, 필터, 정렬, pagination은 URL search params를 우선 사용한다.
- 목록을 떠날 때 scroll 위치와 마지막 선택 record를 보존한다.
- 상세에서 돌아오면 결과를 처음부터 다시 불러오며 빈 화면을 보여주지 말고 기존 결과를 유지한 채 갱신한다.
- 돌아온 뒤 마지막 record가 남아 있으면 해당 행으로 focus 또는 시각적 위치를 복원한다.
- record가 삭제되었다면 가장 가까운 안전한 목록 heading 또는 결과 영역으로 focus를 이동한다.
뒤로보다실행 기록으로 돌아가기처럼 목적지를 눈에 보이는 레이블로 제공한다.
행 행동
- 행 전체가 정확히 하나의 상세 목적지로 이동하면 행의 주 링크가 넓은 hit area를 가질 수 있다.
- 실제 table row에 임의
onClick만 추가하지 말고 record 이름에 semantic link를 둔다. - 행 안의 menu, checkbox, button은 상세 링크와 독립적으로 동작해야 한다.
- 행 전체 선택과 상세 이동을 같은 클릭에 묶지 않는다.
- hover에서만 필수 행동을 드러내지 않는다.
- 파괴 행동은 row menu에서 바로 완료하지 말고 대상과 결과를 확인한다.
상태와 피드백
Loading
- column 또는 row 구조를 반영한 skeleton으로 목록 frame을 유지한다.
- 검색·필터 변경 중에는 이전 결과를 유지하고 갱신 중임을 알린다.
Empty
- 최초 데이터 없음과 현재 조건의 결과 없음을 구분한다.
- 최초 없음은 생성 행동, 결과 없음은 조건 초기화를 우선한다.
Error
- 목록 전체 실패는 같은 frame에 오류와 재시도를 보여준다.
- 일부 row 실패는 나머지 결과를 유지하고 해당 항목에 상태를 표시한다.
Detail change
- 저장 성공 뒤 title, status와 목록의 해당 row가 같은 값을 보여야 한다.
- 삭제 성공 뒤 목록으로 이동하고 삭제된 대상을 다시 focus하려 하지 않는다.
- 다른 사용자가 record를 변경했다면 덮어쓰기 전에 최신 상태와 충돌을 설명한다.
좁은 화면
- table의 모든 열을 축소하지 말고 식별자, 상태, 핵심 meta, 주 행동을 record list로 재배치한다.
- 열려 있는 side panel은 독립 route 또는 full-screen layer로 전환한다.
- 필터는 sheet에 둘 수 있지만 적용된 조건과 결과 개수는 목록에서 계속 확인 가능해야 한다.
- 목록으로 돌아왔을 때 이전 scroll과 조건을 모바일에서도 보존한다.
접근성
- table 데이터는
Table의 header와 cell 관계를 유지한다. - 목록에는 고유한 heading 또는
aria-label을 제공한다. - row action의 이름에 record 대상을 포함한다. 예:
온보딩 커리큘럼 더보기. - route가 바뀌면 상세 h1에 programmatic focus를 보낸다.
- 목록으로 돌아올 때 삭제되지 않은 마지막 link로 focus를 복원한다.
- 결과 개수 변경은 짧은 live region으로 알리되 매 keystroke마다 과도하게 낭독하지 않는다.
예제
<PageScaffold>
<PageHeader
title="커리큘럼"
description="운영 중인 학습과 검토가 필요한 초안을 관리해요."
actions={<Button>새 커리큘럼 만들기</Button>}
/>
<PageToolbar
title="전체 커리큘럼"
controls={<Input aria-label="커리큘럼 검색" placeholder="이름 검색" />}
/>
<CurriculumTable />
</PageScaffold>상세 header:
<PageHeader
title={curriculum.name}
backAction={{ label: '커리큘럼 목록', onClick: returnToList }}
badge={<StatusPill tone="warning">검증 필요</StatusPill>}
/>피해야 할 사용
- 상세에서 돌아올 때 검색과 필터 초기화
- table row에
onClick만 추가하고 link semantics 생략 - row checkbox, menu와 상세 이동 영역 충돌
- 상세 title을 내부 ID만으로 표시
- 검색 갱신마다 결과 전체를 비워 깜박이게 함
- 모바일에서 중요한 상태 열을 아무 설명 없이 숨김
검토 체크
- 목록의 목적과 주 생성 행동이 첫 화면에서 보인다.
- 검색·필터·정렬·페이지가 URL 또는 복원 가능한 state에 있다.
- 상세로 이동한 record와 돌아갈 위치를 기억한다.
- row의 link, 선택, menu hit area가 충돌하지 않는다.
- loading, 최초 empty, 결과 empty, 전체 error, 부분 error가 구분된다.
- 상세 저장·삭제 결과가 목록과 즉시 일치한다.
- route 전환과 복귀 focus가 정의돼 있다.
- 좁은 화면에서도 식별자·상태·핵심 행동이 남는다.