| name | api-design |
| description | 리소스 네이밍, 상태 코드, 페이지네이션, 필터링, 에러 응답, 버저닝, rate limiting을 포함한 프로덕션 REST API 설계 패턴입니다. |
| origin | ECC |
API Design Patterns
일관되고 개발자 친화적인 REST API를 설계하기 위한 규칙과 모범 사례입니다.
활성화 시점
- 새 API 엔드포인트를 설계할 때
- 기존 API 계약을 리뷰할 때
- 페이지네이션, 필터링, 정렬을 추가할 때
- API 에러 처리를 구현할 때
- API 버저닝 전략을 계획할 때
- 공개 API나 파트너용 API를 만들 때
리소스 설계
URL 구조
GET /api/v1/users
GET /api/v1/users/:id
POST /api/v1/users
PUT /api/v1/users/:id
PATCH /api/v1/users/:id
DELETE /api/v1/users/:id
리소스는 명사, 복수형, 소문자, kebab-case를 사용합니다.
네이밍 규칙
좋은 예:
/api/v1/team-members
/api/v1/orders?status=active
/api/v1/users/123/orders
나쁜 예:
/api/v1/getUsers
/api/v1/user
/api/v1/team_members
/api/v1/users/123/getOrders
HTTP 메서드와 상태 코드
메서드 의미
| Method | Idempotent | Safe | Use For |
|---|
| GET | Yes | Yes | 조회 |
| POST | No | No | 생성, 액션 트리거 |
| PUT | Yes | No | 전체 교체 |
| PATCH | 보통 No | No | 부분 수정 |
| DELETE | Yes | No | 삭제 |
상태 코드 참조
200 OK
201 Created
204 No Content
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
409 Conflict
422 Unprocessable Entity
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
흔한 실수
- 모든 응답을 200으로 보내는 것
- validation 오류를 500으로 보내는 것
- 생성 후 201과 Location 헤더를 주지 않는 것
응답 형식
성공 응답
{
"data": {
"id": "abc-123",
"email": "alice@example.com",
"name": "Alice"
}
}
목록 응답
{
"data": [
{ "id": "abc-123", "name": "Alice" },
{ "id": "def-456", "name": "Bob" }
],
"meta": {
"total": 142,
"page": 1,
"per_page": 20,
"total_pages": 8
}
}
에러 응답
{
"error": {
"code": "validation_error",
"message": "Request validation failed",
"details": [
{ "field": "email", "message": "Must be a valid email address" }
]
}
}
페이지네이션
Offset 기반
GET /api/v1/users?page=2&per_page=20
장점:
단점:
- 큰 offset에서 느림
- 동시 삽입이 있으면 불안정
Cursor 기반
GET /api/v1/users?cursor=...&limit=20
장점:
- 큰 데이터셋에서도 일관된 성능
- 동시 삽입에 더 안정적
단점:
필터링, 정렬, 검색
- 단순 equality는 query params
- 비교 연산자는 bracket notation
- 다중값은 comma-separated 또는 반복 파라미터
- 정렬은 명시적 필드 allowlist 기반으로 제한
설계 원칙
- API는 URL에서 동사를 최소화합니다
- 에러는 구조화하고 사람/기계 모두 읽을 수 있게 만듭니다
- public API는 envelope 패턴을 선호합니다
- 내부 API는 더 단순한 flat response도 가능하지만 일관성은 유지합니다
- rate limit, auth, versioning은 나중에 붙이는 기능이 아니라 초기에 고려합니다