Files
sam-docs/standards/pagination-policy.md
kent 3ba4f87566 docs: 견적 산출 API 개발 계획 문서 추가
- 견적 산출 API 개발 계획 문서 신규 작성 (quote-calculation-api-plan.md)
- MNG FormulaEvaluatorService 핵심 로직 상세 명세 포함
- 10단계 BOM 계산 프로세스, CategoryGroup 단가 계산 방식 등
- React 견적등록 화면 연동을 위한 API 명세 정의
- 페이지네이션 정책 문서 업데이트 (Laravel 기본 응답 구조 반영)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 22:55:09 +09:00

4.8 KiB

SAM API 페이지네이션 정책

작성일: 2025-12-09 수정일: 2025-12-30 적용 범위: 모든 목록 조회 API


1. 응답 구조

1.1 표준 페이지네이션 응답 (Laravel 기본)

{
  "success": true,
  "message": "조회되었습니다.",
  "data": {
    "current_page": 1,
    "data": [
      { "id": 1, "name": "항목1" },
      { "id": 2, "name": "항목2" }
    ],
    "first_page_url": "http://sam.kr/api/v1/items?page=1",
    "from": 1,
    "last_page": 5,
    "last_page_url": "http://sam.kr/api/v1/items?page=5",
    "links": [
      { "url": null, "label": "&laquo; Previous", "active": false },
      { "url": "http://sam.kr/api/v1/items?page=1", "label": "1", "active": true },
      { "url": "http://sam.kr/api/v1/items?page=2", "label": "Next &raquo;", "active": false }
    ],
    "next_page_url": "http://sam.kr/api/v1/items?page=2",
    "path": "http://sam.kr/api/v1/items",
    "per_page": 20,
    "prev_page_url": null,
    "to": 20,
    "total": 100
  }
}

1.2 응답 구조 설명

타입 설명
success boolean 요청 성공 여부
message string 응답 메시지 (i18n 키)
data object 페이지네이션 객체 (Laravel 기본)

1.3 data 객체 필드

필드 타입 설명
current_page int 현재 페이지 번호 (1부터 시작)
data array 실제 데이터 배열
per_page int 페이지당 항목 수
total int 전체 항목 수
last_page int 마지막 페이지 번호
from int|null 현재 페이지 첫 번째 항목 번호
to int|null 현재 페이지 마지막 항목 번호
first_page_url string 첫 페이지 URL
last_page_url string 마지막 페이지 URL
next_page_url string|null 다음 페이지 URL
prev_page_url string|null 이전 페이지 URL
path string 기본 경로
links array 페이지 링크 배열

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(IndexRequest $request)
{
    $items = $this->service->getItems($request->validated());

    return ApiResponse::success($items, __('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 최대 페이지 크기 제한

$size = min($params['size'] ?? 20, 100);  // 최대 100개
  • 기본값: 20
  • 최대값: 100
  • 서버 부하 방지 및 응답 시간 최적화

4. 프론트엔드 사용 가이드

4.1 TypeScript 타입 정의

interface PaginatedResponse<T> {
  success: boolean;
  message: string;
  data: {
    current_page: number;
    data: T[];
    first_page_url: string;
    from: number | null;
    last_page: number;
    last_page_url: string;
    links: Array<{
      url: string | null;
      label: string;
      active: boolean;
    }>;
    next_page_url: string | null;
    path: string;
    per_page: number;
    prev_page_url: string | null;
    to: number | null;
    total: number;
  };
}

4.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.data;

  // 페이지네이션 정보
  const { current_page, total, last_page } = response.data.data;

  return { items, pagination: response.data.data };
};

4.3 간편 접근 패턴

// 구조 분해로 간결하게 사용
const { data: pagination } = response.data;
const items = pagination.data;
const { current_page, total, last_page, per_page } = pagination;

5. 설계 원칙

5.1 Laravel 기본 형식 유지

  • 프레임워크 기본 동작 활용
  • 추가 변환 로직 불필요
  • 생태계 호환성 유지

5.2 일관성 우선

  • 기존 API와 동일한 형식 유지
  • 프론트엔드 코드 재사용
  • 학습 비용 최소화

5.3 최대 페이지 크기 제한

  • 서버 부하 방지
  • 응답 시간 최적화
  • DoS 공격 방어

6. 관련 문서