6.1 KiB
6.1 KiB
SAM API 페이지네이션 정책
작성일: 2025-12-09 적용 범위: 모든 목록 조회 API
1. 응답 구조
1.1 표준 페이지네이션 응답
{
"success": true,
"message": "조회되었습니다.",
"data": [
{ "id": 1, "name": "항목1", ... },
{ "id": 2, "name": "항목2", ... }
],
"pagination": {
"current_page": 1,
"per_page": 20,
"total": 100,
"last_page": 5,
"from": 1,
"to": 20
}
}
1.2 응답 구조 설명
| 키 | 타입 | 설명 |
|---|---|---|
success |
boolean | 요청 성공 여부 |
message |
string | 응답 메시지 (i18n 키) |
data |
array | 데이터 배열 (바로 접근 가능) |
pagination |
object | 페이지네이션 정보 |
1.3 pagination 객체 필드
| 필드 | 타입 | 설명 |
|---|---|---|
current_page |
int | 현재 페이지 번호 (1부터 시작) |
per_page |
int | 페이지당 항목 수 |
total |
int | 전체 항목 수 |
last_page |
int | 마지막 페이지 번호 |
from |
int|null | 현재 페이지 첫 번째 항목 번호 |
to |
int|null | 현재 페이지 마지막 항목 번호 |
2. 요청 파라미터
2.1 표준 파라미터
| 파라미터 | 타입 | 기본값 | 설명 |
|---|---|---|---|
page |
int | 1 | 페이지 번호 |
size |
int | 20 | 페이지당 항목 수 (max: 100) |
2.2 요청 예시
GET /api/v1/items?page=1&size=20
GET /api/v1/items?page=2&size=50&search=스크린
3. 구현 가이드
3.1 Controller 구현
public function index(Request $request)
{
$items = $this->service->getItems($request->all());
return ApiResponse::success([
'data' => $items->items(),
'pagination' => [
'current_page' => $items->currentPage(),
'per_page' => $items->perPage(),
'total' => $items->total(),
'last_page' => $items->lastPage(),
'from' => $items->firstItem(),
'to' => $items->lastItem(),
],
], __('message.fetched'));
}
3.2 Service 구현
public function getItems(array $params): LengthAwarePaginator
{
$size = min($params['size'] ?? 20, 100); // 최대 100개
return Model::query()
->when($params['search'] ?? null, fn($q, $s) => $q->where('name', 'like', "%{$s}%"))
->orderByDesc('created_at')
->paginate($size);
}
3.3 Helper 함수 (권장)
ApiResponse 클래스에 페이지네이션 헬퍼 추가:
// app/Helpers/ApiResponse.php
public static function paginated(LengthAwarePaginator $paginator, string $message = null): JsonResponse
{
return self::success([
'data' => $paginator->items(),
'pagination' => [
'current_page' => $paginator->currentPage(),
'per_page' => $paginator->perPage(),
'total' => $paginator->total(),
'last_page' => $paginator->lastPage(),
'from' => $paginator->firstItem(),
'to' => $paginator->lastItem(),
],
], $message ?? __('message.fetched'));
}
사용 예시:
public function index(Request $request)
{
$items = $this->service->getItems($request->all());
return ApiResponse::paginated($items);
}
4. 설계 원칙
4.1 data는 항상 배열
// ✅ 올바른 형식 - data가 바로 배열
{
"data": [...]
}
// ❌ 잘못된 형식 - data.data 중첩
{
"data": {
"data": [...]
}
}
4.2 pagination 분리
- 페이지네이션 정보는
pagination객체로 명확히 분리 - Laravel 기본 형식(first_page_url, links 등) 대신 필수 정보만 포함
- 응답 경량화 및 프론트엔드 접근 편의성 확보
4.3 최대 페이지 크기 제한
$size = min($params['size'] ?? 20, 100); // 최대 100개
- 기본값: 20
- 최대값: 100
- 서버 부하 방지 및 응답 시간 최적화
5. 프론트엔드 사용 가이드
5.1 TypeScript 타입 정의
interface PaginatedResponse<T> {
success: boolean;
message: string;
data: T[];
pagination: {
current_page: number;
per_page: number;
total: number;
last_page: number;
from: number | null;
to: number | null;
};
}
5.2 React 사용 예시
const fetchItems = async (page: number, size: number) => {
const response = await api.get<PaginatedResponse<Item>>('/items', {
params: { page, size }
});
// 데이터 직접 접근
const items = response.data.data;
// 페이지네이션 정보
const { current_page, total, last_page } = response.data.pagination;
return { items, pagination: response.data.pagination };
};
6. 기존 API 마이그레이션
6.1 변경 전 (Laravel 기본)
{
"success": true,
"data": {
"current_page": 1,
"data": [...],
"first_page_url": "http://...",
"from": 1,
"last_page": 5,
"links": [...],
"next_page_url": "http://...",
"path": "http://...",
"per_page": 20,
"prev_page_url": null,
"to": 20,
"total": 100
}
}
6.2 변경 후 (SAM 표준)
{
"success": true,
"message": "조회되었습니다.",
"data": [...],
"pagination": {
"current_page": 1,
"per_page": 20,
"total": 100,
"last_page": 5,
"from": 1,
"to": 20
}
}
6.3 Breaking Changes
| 항목 | 변경 전 | 변경 후 |
|---|---|---|
| 데이터 접근 | response.data.data |
response.data |
| 페이지 정보 | response.data.current_page |
response.pagination.current_page |
| URL 정보 | 포함 (first_page_url 등) | 제거 |
| links 배열 | 포함 | 제거 |
7. 적용 API 목록
| API | 상태 | 비고 |
|---|---|---|
GET /api/v1/items |
🔧 예정 | Items API 통합 작업 시 적용 |
GET /api/v1/products |
⏳ 대기 | |
GET /api/v1/materials |
⏳ 대기 | |
GET /api/v1/pricing |
⏳ 대기 | |
GET /api/v1/employees |
⏳ 대기 |