REST API에서 JSON 사용: 모범 사례
REST API에서의 JSON
JSON과 REST API는 천생연분입니다. JSON의 가벼운 구문, 네이티브 배열 지원 및 보편적인 언어 지원은 JSON을 현대 웹 API의 기본 형식으로 만들었습니다. 하지만 API에서 단순히 JSON을 사용하는 것만으로는 충분하지 않습니다 -- 확립된 규칙과 모범 사례를 따르면 API가 일관되고 직관적이며 통합하기 쉬워집니다.
요청 및 응답 형식
일관된 엔벨로프 구조
모든 API 응답에 일관된 JSON 엔벨로프를 채택하세요. 이는 클라이언트 측 처리를 예측 가능하게 만들고 오류 처리를 단순화합니다.
{
"status": "success",
"data": {
"user": {
"id": 123,
"name": "Alice",
"email": "alice@example.com"
}
},
"meta": {
"requestId": "req-a1b2c3d4",
"timestamp": "2026-07-19T10:30:00Z"
}
}
스네이크 케이스 vs 카멜 케이스
하나의 네이밍 규칙을 선택하고 전체 API에서 일관되게 유지하세요:
- 카멜 케이스 (
createdAt,firstName): JavaScript/TypeScript 생태계에서 일반적 - 스네이크 케이스 (
created_at,first_name): Python, Ruby, PHP 생태계에서 일반적
어느 것을 선택하든 명확하게 문서화하고, 백엔드 언어가 다른 규칙을 사용하는 경우 변환 계층을 사용하는 것을 고려하세요.
JSON과 함께 사용하는 HTTP 상태 코드
적절한 HTTP 상태 코드는 JSON 응답을 보완합니다. 일관되게 사용하세요:
| 상태 코드 | 의미 | 사용 시기 |
|-------------|---------|-------------|
| 200 OK | 성공 | GET, PUT, PATCH 성공 |
| 201 Created | 리소스 생성됨 | POST 성공 |
| 204 No Content | 삭제 성공 | DELETE 성공 (JSON 본문 없음) |
| 400 Bad Request | 잘못된 JSON 구문 | 잘못된 형식의 요청 본문 |
| 401 Unauthorized | 인증 필요 | 토큰 누락 또는 유효하지 않음 |
| 403 Forbidden | 권한 부족 | 유효한 인증이지만 허용되지 않음 |
| 404 Not Found | 리소스가 존재하지 않음 | 유효하지 않은 ID 또는 경로 |
| 422 Unprocessable Entity | 유효성 검사 실패 | 유효한 JSON의 의미적 오류 |
| 429 Too Many Requests | 속도 제한 초과 | 클라이언트가 제한 초과 |
| 500 Internal Server Error | 서버 측 실패 | 예기치 않은 오류 |
표준 오류 응답 형식
{
"status": "error",
"error": {
"code": "VALIDATION_ERROR",
"message": "요청 본문에 유효하지 않은 필드가 포함되어 있습니다",
"details": [
{
"field": "email",
"message": "유효한 이메일 주소여야 합니다",
"code": "INVALID_FORMAT"
},
{
"field": "age",
"message": "양의 정수여야 합니다",
"code": "OUT_OF_RANGE"
}
]
}
}
중첩 리소스
관계 표현하기
REST API는 종종 관련 리소스를 표현해야 합니다. 다음은 일반적인 패턴입니다:
임베디드 (즉시 로딩):
{
"order": {
"id": 5001,
"total": 29.99,
"customer": {
"id": 123,
"name": "Alice",
"email": "alice@example.com"
},
"items": [
{
"productId": 42,
"name": "Widget",
"quantity": 2,
"price": 14.99
}
]
}
}
참조 (지연 로딩) -- ID를 사용하고 별도의 엔드포인트 제공:
{
"order": {
"id": 5001,
"total": 29.99,
"customerId": 123,
"itemIds": [101, 102]
}
}
경험 법칙: 항상 함께 필요한 관련 데이터는 임베드하세요. 조건부로 또는 다른 시점에 조회되는 데이터는 참조하세요.
페이지네이션 패턴
리소스 목록을 반환할 때 페이지네이션은 필수적입니다. 일관된 페이지네이션 형식을 사용하세요:
오프셋 기반 페이지네이션
{
"status": "success",
"data": [
{ "id": 1, "name": "User 1" },
{ "id": 2, "name": "User 2" }
],
"pagination": {
"page": 1,
"perPage": 20,
"totalItems": 156,
"totalPages": 8,
"links": {
"first": "/api/users?page=1&perPage=20",
"prev": null,
"next": "/api/users?page=2&perPage=20",
"last": "/api/users?page=8&perPage=20"
}
}
}
커서 기반 페이지네이션 (대규모 데이터셋에 권장)
{
"status": "success",
"data": [
{ "id": 100, "name": "User 100" },
{ "id": 101, "name": "User 101" }
],
"pagination": {
"nextCursor": "eyJpZCI6MTAxfQ==",
"hasMore": true
}
}
커서 기반 페이지네이션은 새 레코드가 페이지 경계를 이동시킬 수 있는 실시간 데이터에 더 안정적입니다.
API 요청에서의 JSON
POST / PUT 요청 본문
Content-Type: application/json 헤더와 함께 JSON을 수락하세요:
{
"title": "새 블로그 게시물",
"content": "이것은 내용입니다...",
"tags": ["json", "rest-api"],
"published": false
}
PATCH를 사용한 부분 업데이트
부분 업데이트에는 PATCH를 사용하세요. 변경해야 할 필드만 수락하세요:
// PATCH /api/users/123
{
"email": "newemail@example.com"
}
필터링, 정렬 및 검색
데이터 조작에는 쿼리 매개변수를 사용하여 JSON 본문을 깔끔하게 유지하세요:
GET /api/users?filter[role]=admin&sort=-createdAt&search=alice
{
"status": "success",
"data": [ /* 필터링되고 정렬된 결과 */ ]
}
속도 제한
응답 헤더와 선택적으로 JSON 본문에 속도 제한 정보를 포함하세요:
{
"status": "error",
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "요청이 너무 많습니다. 나중에 다시 시도해 주세요."
},
"meta": {
"rateLimit": {
"limit": 100,
"remaining": 0,
"resetAt": "2026-07-19T11:00:00Z"
}
}
}
JSON 모범 사례 체크리스트
- [ ] 전체적으로 일관된 키 네이밍 사용 (camelCase 또는 snake_case)
- [ ] 모든 응답에 적절한 HTTP 상태 코드 반환
- [ ] 기계가 읽을 수 있는 오류 코드와 함께 일관된 오류 형식 포함
- [ ] 표준화된 페이지네이션 객체로 목록 엔드포인트 페이지네이션
- [ ] JSON Schema를 사용하여 요청/응답 구조 문서화 및 유효성 검사
- [ ] 모든 JSON 엔드포인트에
Content-Type: application/json설정 - [ ] 프로덕션 환경에서 gzip 또는 brotli로 JSON 응답 압축
- [ ] 최대 페이로드 크기 제한 적용 (예: 기본 1MB)
- [ ] HTTPS를 사용하여 전송 중인 JSON 데이터 암호화
- [ ] 내부 정보를 노출하지 않으면서 클라이언트 디버깅에 도움이 되도록 오류 세부 정보 구조화
API JSON 유효성 검사하기
API 응답을 JSON 유효성 검사기에 실행하여 클라이언트에 도달하기 전에 포맷 오류를 잡아내세요. 일관되고 유효한 JSON 응답은 API를 신뢰할 수 있고 개발자 친화적으로 만듭니다. 개발 중에 페이로드를 테스트하려면 저희 JSON 포맷터 & 유효성 검사기 도구를 사용하세요.