목록으로
Backend

REST API 설계 베스트 프랙티스

직관적이고 일관된 REST API를 설계하는 방법. 실무에서 검증된 규칙들을 공유합니다.

좋은 API는 사용하기 쉽고 일관성이 있습니다. 문서를 자세히 읽지 않아도 예측 가능해야 합니다. REST API 설계의 핵심 원칙들을 알아봅니다.

URL 설계

명사를 사용하고, 복수형으로

# 좋은 예
GET /users
GET /users/123
GET /users/123/orders

# 나쁜 예
GET /getUsers
GET /user/123
GET /getUserOrders/123

계층 구조 표현

GET /users/123/orders          # 사용자 123의 주문 목록
GET /users/123/orders/456      # 사용자 123의 주문 456
POST /users/123/orders         # 사용자 123의 새 주문 생성

필터링, 정렬, 페이지네이션

쿼리 파라미터를 사용합니다.

GET /products?category=electronics&minPrice=100&maxPrice=500
GET /products?sort=price:desc
GET /products?page=2&limit=20

HTTP 메서드 사용

GET     /users          # 목록 조회
GET     /users/123      # 단일 조회
POST    /users          # 생성
PUT     /users/123      # 전체 수정
PATCH   /users/123      # 부분 수정
DELETE  /users/123      # 삭제

PUT vs PATCH

PUT은 리소스 전체를 교체하고, PATCH는 일부만 수정합니다.

// PUT - 전체 리소스 전송 필요
PUT /users/123
{
  "name": "홍길동",
  "email": "hong@email.com",
  "age": 26,
  "address": "서울시"
}

// PATCH - 변경할 필드만
PATCH /users/123
{
  "age": 26
}

상태 코드

적절한 HTTP 상태 코드를 사용합니다.

2xx 성공
200 OK - 일반적인 성공
201 Created - 리소스 생성 성공
204 No Content - 성공했지만 반환할 내용 없음 (DELETE)

4xx 클라이언트 에러
400 Bad Request - 잘못된 요청
401 Unauthorized - 인증 필요
403 Forbidden - 권한 없음
404 Not Found - 리소스 없음
409 Conflict - 충돌 (중복 등)
422 Unprocessable Entity - 유효성 검사 실패

5xx 서버 에러
500 Internal Server Error - 서버 오류
503 Service Unavailable - 서비스 일시 중단

응답 형식

성공 응답

// 단일 리소스
{
  "data": {
    "id": 123,
    "name": "홍길동",
    "email": "hong@email.com"
  }
}

// 목록
{
  "data": [
    { "id": 1, "name": "홍길동" },
    { "id": 2, "name": "김영희" }
  ],
  "meta": {
    "total": 100,
    "page": 1,
    "limit": 20,
    "totalPages": 5
  }
}

에러 응답

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "입력값이 올바르지 않습니다.",
    "details": [
      {
        "field": "email",
        "message": "올바른 이메일 형식이 아닙니다."
      },
      {
        "field": "password",
        "message": "비밀번호는 8자 이상이어야 합니다."
      }
    ]
  }
}

에러 응답은 클라이언트가 문제를 이해하고 해결할 수 있도록 충분한 정보를 제공해야 합니다.

버전 관리

API가 변경될 때 기존 클라이언트가 깨지지 않도록 버전을 관리합니다.

# URL에 버전 포함 (가장 일반적)
GET /v1/users
GET /v2/users

# 헤더로 버전 지정
GET /users
Accept: application/vnd.myapi.v1+json

인증

Bearer 토큰 방식이 가장 일반적입니다.

GET /users
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

실전 예시

사용자 관리 API 설계 예시입니다.

# 사용자 목록 (필터, 정렬, 페이지네이션)
GET /v1/users?role=admin&sort=createdAt:desc&page=1&limit=20

# 사용자 조회
GET /v1/users/123

# 사용자 생성
POST /v1/users
Body: { "name": "홍길동", "email": "hong@email.com" }
Response: 201 Created

# 사용자 수정
PATCH /v1/users/123
Body: { "name": "홍길순" }
Response: 200 OK

# 사용자 삭제
DELETE /v1/users/123
Response: 204 No Content

# 사용자의 주문 목록
GET /v1/users/123/orders

# 사용자 비밀번호 변경 (특수 작업)
POST /v1/users/123/change-password
Body: { "oldPassword": "...", "newPassword": "..." }

마무리

일관성이 가장 중요합니다. 팀에서 규칙을 정하고, 모든 API가 같은 패턴을 따르도록 합니다.

OpenAPI(Swagger) 스펙으로 API를 문서화하면 프론트엔드 개발자와 협업이 훨씬 수월해집니다.