백엔드 프레임워크

RESTful API 설계 원칙 및 베스트 프랙티스 (best practice)

ioh'sDeveloper 2024. 9. 20. 17:23

RESTful API는 현대 웹 애플리케이션의 핵심 요소로, 클라이언트와 서버 간의 통신을 단순하고 효율적으로 할 수 있도록 설계된 아키텍처 스타일입니다. **REST(Representational State Transfer)**는 2000년 로이 필딩(Roy Fielding)이 소개한 개념으로, 리소스를 명확히 정의하고 HTTP 프로토콜을 기반으로 데이터를 주고받는 방식입니다. 이번 포스팅에서는 RESTful API의 설계 원칙과 이를 효과적으로 구현하기 위한 베스트 프랙티스를 자세히 설명합니다.


1. REST의 6가지 주요 원칙

REST 아키텍처는 다음 6가지 원칙을 따릅니다:

  1. 클라이언트-서버 구조 (Client-Server Architecture)
    클라이언트와 서버는 서로 독립적으로 동작해야 합니다. 클라이언트는 사용자 인터페이스와 요청을 담당하며, 서버는 데이터 저장 및 처리 로직을 관리합니다. 이 구조는 역할을 명확히 분리하여 확장성과 관리 용이성을 제공합니다.
  2. 상태 없음 (Statelessness)
    각 요청은 독립적이어야 하며, 서버는 클라이언트의 상태를 저장하지 않아야 합니다. 즉, 모든 요청은 그 자체로 완전한 정보를 포함해야 하며, 클라이언트가 필요한 모든 데이터를 요청에 포함해야 합니다. 이를 통해 서버 확장이 용이해집니다.
  3. 캐시 처리 가능 (Cacheability)
    응답 데이터는 캐시가 가능해야 합니다. HTTP 프로토콜의 캐싱 메커니즘을 사용하여 클라이언트가 서버와의 트래픽을 줄이고, 성능을 향상시킬 수 있습니다. 예를 들어, 자주 변경되지 않는 리소스는 Cache-Control 헤더를 사용해 캐시할 수 있습니다.
  4. 계층화 시스템 (Layered System)
    RESTful 아키텍처는 여러 계층의 시스템으로 구성될 수 있습니다. 클라이언트는 중간에 프록시, 로드 밸런서, 캐시 등을 거쳐도 응답을 받을 수 있습니다. 이러한 계층 구조는 시스템 확장성과 보안을 강화합니다.
  5. 인터페이스 일관성 (Uniform Interface)
    RESTful API는 일관된 인터페이스를 가져야 합니다. 리소스에 접근하는 방식이 일관적이어야 하며, 리소스 표현은 URL로 접근 가능해야 합니다. 이를 통해 클라이언트와 서버가 상호작용하는 방식이 명확해집니다.
  6. 요구에 따른 코드 전송 (Code on Demand)
    선택적으로 클라이언트에 실행 가능한 코드를 전송할 수 있습니다. 예를 들어, 클라이언트가 필요한 경우 서버로부터 자바스크립트 코드를 받아 실행할 수 있습니다. 하지만, 이 원칙은 REST의 필수 요소는 아닙니다.

2. RESTful API 설계 원칙

RESTful API를 설계할 때는 몇 가지 중요한 원칙을 따르는 것이 바람직합니다. 이 원칙들은 API의 가독성을 높이고, 유지보수를 용이하게 하며, 확장성을 극대화하는 데 기여합니다.

2.1 리소스는 명사로 표현한다

RESTful API에서 리소스는 URL을 통해 표현되며, 리소스는 항상 명사로 나타나야 합니다. HTTP 메서드가 동작을 정의하므로, 리소스 경로에 동사나 행동을 포함시키지 않습니다.

예시:

  • 잘못된 URL: GET /createUser (동사를 포함하지 않음)
  • 올바른 URL: GET /users (리소스 이름만 포함)

2.2 HTTP 메서드를 올바르게 사용한다

HTTP 메서드는 각 요청의 성격을 명확하게 나타내는 데 사용됩니다. 주요 메서드와 그 역할은 다음과 같습니다:

  • GET: 서버에서 리소스를 조회할 때 사용됩니다. 데이터 변경이 일어나지 않으며, 안전한 메서드입니다.
    • 예: GET /users/123
  • POST: 새로운 리소스를 생성할 때 사용됩니다.
    • 예: POST /users (새 사용자 생성)
  • PUT: 리소스를 완전히 대체하거나 업데이트할 때 사용됩니다.
    • 예: PUT /users/123 (ID가 123인 사용자 정보 전체 업데이트)
  • PATCH: 리소스의 일부를 수정할 때 사용됩니다.
    • 예: PATCH /users/123 (ID가 123인 사용자 정보 일부 수정)
  • DELETE: 리소스를 삭제할 때 사용됩니다.
    • 예: DELETE /users/123 (ID가 123인 사용자 삭제)

2.3 URL은 계층 구조를 반영한다

리소스는 계층 구조를 가질 수 있습니다. API 경로는 이 계층 구조를 직관적으로 표현해야 하며, 부모-자식 관계를 나타낼 수 있습니다.

예시:

  • /users/123/orders (사용자 ID 123의 주문 목록)
  • /users/123/orders/456 (사용자 ID 123의 주문 중 ID가 456인 주문)

2.4 상태 코드를 올바르게 사용한다

API 응답 시 적절한 HTTP 상태 코드를 반환해야 합니다. 상태 코드는 클라이언트가 요청 처리 결과를 이해할 수 있도록 돕습니다.

  • 200 OK: 요청이 성공적으로 처리되었습니다.
  • 201 Created: 새로운 리소스가 생성되었습니다.
  • 204 No Content: 요청은 성공적으로 처리되었으나 응답 본문이 없습니다 (예: DELETE).
  • 400 Bad Request: 클라이언트의 요청이 잘못되었습니다.
  • 401 Unauthorized: 인증이 필요합니다.
  • 403 Forbidden: 권한이 부족합니다.
  • 404 Not Found: 요청한 리소스를 찾을 수 없습니다.
  • 500 Internal Server Error: 서버에서 오류가 발생했습니다.

3. RESTful API 베스트 프랙티스

3.1 페이징, 정렬, 필터링 적용

대용량 데이터를 처리할 때는 페이징(Paging), 정렬(Sorting), **필터링(Filtering)**을 지원하는 것이 필수적입니다. 이를 통해 API의 응답 성능을 향상시키고, 클라이언트가 필요한 데이터만 요청할 수 있도록 합니다.

예시:

  • 페이징: GET /users?page=2&limit=50 (2페이지, 50명의 사용자)
  • 정렬: GET /users?sort=created_at,desc (생성일을 기준으로 내림차순 정렬)
  • 필터링: GET /users?role=admin (관리자만 조회)

3.2 HATEOAS 적용

**HATEOAS(Hypermedia as the Engine of Application State)**는 RESTful API에서 클라이언트가 리소스 상태를 쉽게 탐색할 수 있도록 하이퍼미디어 링크를 제공하는 개념입니다. 응답에 관련 리소스의 링크를 포함하여 클라이언트가 다음 동작을 쉽게 결정할 수 있도록 도와줍니다.

{
  "id": 123,
  "name": "John Doe",
  "links": [
    {
      "rel": "self",
      "href": "/users/123"
    },
    {
      "rel": "orders",
      "href": "/users/123/orders"
    }
  ]
}

 

3.3 버전 관리

API는 시간이 지남에 따라 변화하기 때문에 버전 관리가 필수적입니다. 버전 관리를 통해 기존 클라이언트와의 호환성을 유지하면서 새로운 기능을 추가할 수 있습니다.

베스트 프랙티스:

  • URI에 버전 추가: GET /v1/users
  • 헤더에 버전 추가: GET /users (헤더: Accept: application/vnd.myapp.v1+json)

3.4 적절한 에러 메시지 반환

API 응답에서 에러가 발생했을 때는 명확한 에러 메시지를 제공해야 합니다. 클라이언트가 문제를 파악하고 해결할 수 있도록 구체적인 에러 정보를 포함하는 것이 좋습니다.

{
  "error": "Bad Request",
  "message": "The field 'email' is required.",
  "status": 400
}

 

3.5 보안 강화

API는 항상 보안을 고려하여 설계해야 합니다. 이를 위해서는 다음과 같은 보안 베스트 프랙티스를 따릅니다:

  • HTTPS 사용: 데이터를 안전하게 전송하기 위해 HTTPS를 사용해야 합니다.
  • API 키 또는 OAuth: 클라이언트 인증을 위해 API 키나 OAuth 2.0을 사용해 접근 제어를 구현해야 합니다.
  • 입력 값 검증: 클라이언트가 보내는 모든 입력 값을 철저히 검증

하여 SQL Injection이나 XSS 공격을 방지합니다.


4. 결론

RESTful API 설계는 클라이언트와 서버 간의 상호작용을 효율적이고 직관적으로 만들기 위한 중요한 요소입니다. 명확한 리소스 정의, 일관된 URL 구조, 적절한 상태 코드 사용, 보안 고려 등은 API의 성능과 사용성을 높이는 데 필수적입니다. API 설계에서 이러한 원칙과 베스트 프랙티스를 따름으로써 유지보수하기 쉬운 API를 만들 수 있으며, 이는 개발자의 생산성과 사용자 경험을 모두 향상시키는 데 기여할 것입니다.


참고 자료