Pagination#
대용량 콘텐츠를 페이지 단위로 나누어 탐색할 수 있는 컴포넌트입니다. 현재 페이지 표시, 이전/다음 이동, 첫/마지막 페이지 이동을 지원합니다.
Live Preview#
class PaginationDefaultExample extends StatefulComponent {
const PaginationDefaultExample({super.key});
@override
State<PaginationDefaultExample> createState() =>
_PaginationDefaultExampleState();
}
class _PaginationDefaultExampleState extends State<PaginationDefaultExample> {
int _page = 3;
@override
Component build(BuildContext context) {
return Pagination(
page: _page,
totalPages: 10,
onPageChanged: (value) => setState(() => _page = value),
);
}
}
class PaginationDefaultExample extends StatefulWidget {
const PaginationDefaultExample({super.key});
@override
State<PaginationDefaultExample> createState() =>
_PaginationDefaultExampleState();
}
class _PaginationDefaultExampleState extends State<PaginationDefaultExample> {
int _page = 3;
@override
Widget build(BuildContext context) {
return Pagination(
page: _page,
totalPages: 10,
onPageChanged: (p) => setState(() => _page = p),
);
}
}
사용 시기 (When to Use)#
이 컴포넌트를 사용하세요:
- 테이블, 검색 결과, 상품 목록처럼 많은 데이터를 페이지 단위로 나눠 표시할 때
- 사용자가 특정 페이지로 직접 이동할 수 있어야 할 때
- 전체 데이터 양이 많지 않아 페이지 번호로 탐색이 유용한 경우
대신 다른 컴포넌트를 사용하세요:
RefreshTrigger: 무한 스크롤 방식으로 데이터를 로드할 때Select: 페이지 크기 선택 등 드롭다운 옵션이 필요할 때
기본 사용법 (Basic Usage)#
Flutter / Web 모두 동일한 Pagination API 를 사용합니다.
// 기본 페이지네이션
Pagination(
page: _currentPage,
totalPages: 10,
onPageChanged: handlePageChanged,
)
// 더 넓은 페이지 범위 + prev/next 라벨
Pagination(
page: _currentPage,
totalPages: 20,
onPageChanged: handlePageChanged,
maxPages: 7,
showLabel: true,
)
// 첫 페이지에서 이전 버튼 숨김
Pagination(
page: _currentPage,
totalPages: 5,
onPageChanged: handlePageChanged,
hidePreviousOnFirstPage: true,
)
// 기본 페이지네이션 (이전/다음 버튼 포함)
Pagination(
page: currentPage,
totalPages: 10,
onPageChanged: handlePageChanged,
)
// 더 넓은 페이지 범위 + prev/next 라벨
Pagination(
page: currentPage,
totalPages: 20,
onPageChanged: handlePageChanged,
maxPages: 7,
showLabel: true,
)
Props / Parameters#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
page | int | 필수 | 현재 페이지 (1-based) |
totalPages | int | 필수 | 전체 페이지 수 |
onPageChanged |
void Function(int)? |
null |
페이지 변경 핸들러 (1-based) |
maxPages |
int |
3 |
표시할 최대 페이지 버튼 수 |
showSkipToFirstPage |
bool |
true |
선행 생략 시 첫 페이지 이동 버튼 표시 |
showSkipToLastPage |
bool |
true |
후행 생략 시 마지막 페이지 이동 버튼 표시 |
hidePreviousOnFirstPage |
bool |
false |
첫 페이지에서 이전 버튼 숨김 |
hideNextOnLastPage |
bool |
false |
마지막 페이지에서 다음 버튼 숨김 |
showLabel |
bool |
false |
이전/다음 버튼에 텍스트 라벨 표시 |
variant |
CorePaginationVariant |
standard |
시각 변형 |
paginationStyle |
CorePaginationStyle? |
null |
인스턴스 스타일 (Style 시스템 참조) |
스타일 시스템 (Style System)#
Pagination 의 모든 chrome / dimensional 오버라이드는 CorePaginationStyle 단일 슬롯으로 흐릅니다. behaviour 필드 (page
/ totalPages / onPageChanged / maxPages / showSkipToFirstPage
/ showSkipToLastPage / hidePreviousOnFirstPage / hideNextOnLastPage
/ showLabel) 는 위젯/컴포넌트 파라미터로 직접 전달합니다.
시맨틱 vs 스타일#
-
시맨틱 / behaviour: 위젯/컴포넌트 파라미터로 직접 (
page,totalPages,onPageChanged,maxPages,showSkipToFirstPage,showSkipToLastPage,hidePreviousOnFirstPage,hideNextOnLastPage,showLabel) - chrome / dimensional:
CorePaginationStyle한 곳으로
Resolve chain#
CorePaginationStyle.defaultX // design system default
→ CorePaginationTheme.style // 프로젝트 공통
→ widget.paginationStyle // 인스턴스별
필드 매핑 (CorePaginationStyle)#
| 필드 | 타입 | 적용 영역 |
|---|---|---|
itemSpacing |
double? |
페이지네이션 버튼 간격 (logical px) — Row.spacing / CSS flex gap 으로 적용 |
buttonSize | double? | 정사각형 버튼의 너비/높이 (logical px) |
buttonRadius | CoreBorderRadius? | 버튼 모서리 반경 |
activeBackgroundColor | CoreColor? | 활성(현재) 페이지 버튼 배경 |
activeForegroundColor | CoreColor? | 활성(현재) 페이지 버튼 전경 |
hoverBackgroundColor | CoreColor? | 호버 시 배경 |
hoverForegroundColor | CoreColor? | 호버 시 전경 |
foregroundColor | CoreColor? | 비활성/이전/다음 버튼 전경 |
ellipsisStyle |
CoreTextStyle? |
생략 표시 (…) 텍스트 스타일 |
변형 (Variants)#
Pagination 은 현재 단일 시각 변형(standard) 을 가집니다. 표시되는 페이지 범위와
prev/next 라벨은 behaviour 파라미터로 조정합니다.
// 더 넓은 페이지 범위 + 라벨
Pagination(
page: 5,
totalPages: 20,
onPageChanged: handlePageChanged,
maxPages: 7,
showLabel: true,
)
동작 스펙 (Behavior)#
인터랙션#
- 페이지 버튼 클릭: 해당 페이지로 이동 (
onPageChanged(page)호출) - 이전/다음 버튼: 현재 페이지에서 1씩 감소/증가
- 첫/마지막 버튼: 1페이지 또는 totalPages로 이동
- 현재 페이지 버튼: 클릭해도 이벤트 없음 (비활성 강조)
- 경계 버튼: 첫 페이지에서 이전 버튼, 마지막 페이지에서 다음 버튼은 비활성
상태 전환#
- 현재 페이지 버튼: 강조 색상 + 비활성 클릭
- 경계 도달 시 이전/다음 버튼 disabled 처리
- 페이지 수가 많으면 현재 페이지 기준으로 중간 항목
...으로 생략
애니메이션#
- 페이지 전환 시 별도 애니메이션 없음 (콘텐츠 영역 전환은 부모가 처리)
- 버튼 호버 시 배경색 200ms 전환
사용 가이드라인 (Usage Guidelines)#
✅ Do#
많은 데이터에는 skip-to-first / skip-to-last 버튼 활용
Pagination(
page: _currentPage,
totalPages: 50,
onPageChanged: handlePageChanged,
showSkipToFirstPage: true,
showSkipToLastPage: true,
)
50페이지 이상의 데이터에서 첫/마지막 페이지 버튼은 멀리 있는 페이지로의 빠른 이동을 지원한다.
❌ Don't#
페이지가 1개일 때 Pagination 표시
// ❌ 페이지가 1개뿐인데 Pagination 표시
Pagination(
page: 1,
totalPages: 1,
onPageChanged: handlePageChanged,
)
페이지가 1개뿐이면 Pagination이 의미 없고 오히려 혼란을 준다. totalPages > 1인 경우에만 표시한다.
✅ Do#
좁은 화면에서는 maxPages 를 작게 유지
Pagination(
page: _currentPage,
totalPages: 20,
onPageChanged: handlePageChanged,
maxPages: 3,
)
maxPages 가 크면 버튼이 너무 많아 모바일 화면에서 줄바꿈이 발생한다. 3~5가 적당하다.
❌ Don't#
데이터가 적을 때 불필요하게 페이지네이션을 표시하지 마세요.
// ❌ 한 페이지에 다 들어오는데도 표시
Pagination(
page: 1,
totalPages: 1,
onPageChanged: handlePageChanged,
)
단일 페이지라면 페이지네이션은 불필요한 UI 요소입니다. 총 항목 수가 페이지당 개수보다 적으면 숨기세요.
접근성 (Accessibility)#
키보드 인터랙션#
| 키 | 동작 |
|---|---|
Tab | 다음 페이지 버튼으로 포커스 |
Enter / Space | 포커스된 페이지 버튼 활성화 |
Arrow Left/Right | 이전/다음 페이지 버튼으로 포커스 이동 |
스크린 리더#
- Flutter:
Semantics(label: '페이지 3, 전체 10페이지')형태로 현재/전체 페이지 전달 -
Web:
role="navigation"+aria-label="페이지 탐색"+ 현재 페이지에aria-current="page"적용
터치 타겟#
- 각 페이지 버튼 최소 크기: 44x44dp
크로스 플랫폼 차이점 (Platform Differences)#
| 항목 | Flutter | Web |
|---|---|---|
| 클래스명 | Pagination | Pagination (동일) |
| 페이지 기준 | 1-based | 1-based |
| 버튼 | div 기반 정사각 버튼 | <div role="button"> 정사각 버튼 |
| 생략 표시 | … 텍스트 (클릭 시 범위 점프) | … 텍스트 (클릭 시 범위 점프) |
| 호버 | MouseRegion + 색 전환 | CSS :hover 토큰 클래스 |