✅ 잘된 REST API 설계 vs ❌ 잘못된 REST API 설계
REST API를 설계할 때 올바른 방식과 그렇지 않은 방식을 비교하여 이해하면 더욱 직관적으로 좋은 설계를 할 수 있습니다.
1. 자원(Resource) 설계
✅ 잘된 설계 (자원을 명확하게 표현)
GET /users → 모든 사용자 조회
GET /users/{id} → 특정 사용자 조회
POST /users → 사용자 생성
PUT /users/{id} → 사용자 전체 수정
PATCH /users/{id} → 사용자 일부 수정
DELETE /users/{id} → 사용자 삭제
❌ 잘못된 설계 (동사를 URI에 포함하거나 RESTful하지 않음)
GET /getUsers → 불필요한 동사 사용
GET /users/get/1 → RESTful하지 않음
POST /users/create → 동작을 URI에 포함
DELETE /users/delete/1 → 잘못된 URI
🔍 문제점
- REST에서는 URI는 "명사" 로 표현해야 하며, 동작(동사)은 HTTP 메서드로 구분해야 합니다.
- /getUsers, /users/delete/1처럼 API 동작을 URI에 포함하면 RESTful하지 않습니다.
2. HTTP 메서드 활용
✅ 잘된 설계 (HTTP 메서드를 올바르게 활용)
GET /products → 모든 상품 조회
POST /products → 새로운 상품 생성
PUT /products/{id} → 상품 정보 전체 수정
PATCH /products/{id} → 상품 정보 일부 수정
DELETE /products/{id} → 특정 상품 삭제
❌ 잘못된 설계 (메서드를 잘못 사용)
POST /products/getAll → GET을 사용해야 하는 요청
GET /products/create → POST를 사용해야 하는 요청
PUT /products → 리소스 ID 없이 전체 수정 요청 (잘못됨)
🔍 문제점
- GET 요청에 POST를 사용하면 RESTful하지 않음.
- PUT 요청은 특정 리소스(/products/{id})를 대상으로 해야 함.
3. 계층 구조 설계
✅ 잘된 설계 (계층적 관계를 명확하게 표현)
GET /users/{id}/orders → 특정 사용자의 주문 목록 조회
GET /users/{id}/orders/{oid} → 특정 사용자의 특정 주문 조회
POST /users/{id}/orders → 특정 사용자에게 주문 추가
❌ 잘못된 설계 (비효율적이거나 RESTful하지 않음)
GET /orders?userId={id} → 사용자 ID를 쿼리 파라미터로 전달 (비효율적)
GET /users/orders/{oid} → 사용자를 명시하지 않아 관계가 불분명
POST /orders?userId={id} → URI에서 관계를 표현하지 않음
🔍 문제점
- 계층적 관계(users → orders)가 보이지 않음.
- GET /orders?userId={id}처럼 쿼리 파라미터로 관계를 표현하면 RESTful하지 않음.
4. 응답(Response) 설계
✅ 잘된 설계 (일관된 응답 포맷)
{
"status": "success",
"data": {
"id": 1,
"name": "Alice",
"email": "alice@example.com"
}
}
❌ 잘못된 설계 (불필요한 응답 구조)
{
"responseCode": 200,
"responseMessage": "OK",
"result": {
"userInfo": {
"user_id": 1,
"user_name": "Alice",
"user_email": "alice@example.com"
}
}
}
🔍 문제점
- responseCode, responseMessage 등 불필요한 중첩 구조가 많음.
- userInfo라는 불필요한 계층을 만들지 말고 data 안에 바로 넣는 것이 좋음.
- user_id, user_name은 camelCase 또는 snake_case로 통일해야 함.
5. 에러 처리
✅ 잘된 설계 (표준 HTTP 상태 코드 사용)
400 Bad Request → 잘못된 요청 (예: 필수 필드 누락)
401 Unauthorized → 인증 실패
403 Forbidden → 권한 없음
404 Not Found → 리소스를 찾을 수 없음
500 Internal Server Error → 서버 오류
응답 예제:
{
"status": "error",
"message": "User not found",
"code": 404
}
❌ 잘못된 설계 (비표준 상태 코드 사용)
200 OK → 오류인데도 성공(200)을 반환 (잘못된 방식)
500 User Not Found → 404를 사용해야 함
{
"error_code": 1234,
"description": "User does not exist"
}
🔍 문제점
- 200 OK를 모든 응답에 사용하면 클라이언트가 오류를 인식하기 어려움.
- HTTP 상태 코드(404, 403 등)를 올바르게 사용해야 함.
6. 페이징 & 정렬
✅ 잘된 설계 (쿼리 파라미터 활용)
GET /products?limit=10&offset=20&sort=name,asc
❌ 잘못된 설계 (URI에서 직접 표현)
GET /products/page/2/size/10/sort/name/asc → URI에 직접 표현 (비효율적)
🔍 문제점
- URI에 페이징 정보를 포함하면 변경하기 어려움.
- RESTful API에서는 필터링 및 정렬을 쿼리 파라미터로 처리하는 것이 좋음.
7. API 버전 관리
✅ 잘된 설계 (버전 명시)
GET /api/v1/users
GET /api/v2/users
❌ 잘못된 설계 (버전 미관리)
GET /users?version=1
GET /v1.0/users
🔍 문제점
- 버전을 쿼리 파라미터로 관리하면 API를 사용하는 클라이언트가 헷갈릴 수 있음.
- /v1.0/처럼 소수점까지 포함하는 것은 일반적이지 않음.
8. 보안 고려
✅ 잘된 설계 (보안 적용)
- HTTPS 사용
- JWT 토큰 기반 인증 적용
- API 키 또는 OAuth2를 통한 접근 제어
- CORS 정책 설정
❌ 잘못된 설계 (보안 취약)
- HTTP 사용 (http://api.example.com → https://api.example.com이 되어야 함)
- API 키를 URL에 노출 (GET /users?apikey=12345678 → 헤더로 보내는 것이 좋음)
- 인증이 필요한 API에서 인증 미적용 (POST /users가 누구나 가능하면 위험)
🚀 정리: 잘된 설계 원칙
✅ URI는 명사로 표현
✅ HTTP 메서드를 적절히 사용
✅ 계층적 구조를 반영
✅ 일관된 응답 포맷 유지
✅ 표준 HTTP 상태 코드 활용
✅ 페이징 & 정렬은 쿼리 파라미터로 관리
✅ API 버전 관리 적용
✅ 보안 고려 (HTTPS, 인증, CORS 등)
'개발공부 > API' 카테고리의 다른 글
REST API / REST / RESTful API 란 ? (0) | 2025.02.24 |
---|---|
API 캐시 도입 (@Cacheable) (0) | 2025.02.13 |
RESTful API 이란? (0) | 2025.02.13 |
REST, REST API, RESTful 특징 (0) | 2025.02.13 |