본문 바로가기

개발공부/API

잘된 REST API 설계 vs 잘못된 REST API 설계

✅ 잘된 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.comhttps://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