본 글은 아래 링크의 포스트를 번역한 내용입니다.
https://daily.dev/blog/restful-api-design-best-practices-guide-2024
주요 권장 사항
아래 예시를 따르면 사용하기 쉽고 유지보수 및 확장에 용이한 API를 만들 수 있다.
Best Practice | 설명 |
리소스 명명 | 복수 명사 사용 (예시: /users) |
HTTP 메서드 | GET (읽기), POST (생성), PUT (갱신), DELETE (삭제) |
인증 | OAuth 2.0 또는 JWT 구현 |
버전 관리 | 시맨틱 버전 관리 사용 (예: v1.2.3) |
문서화 | OpenAPI/Swagger 문서 제공 |
보안 | HTTPS, 입력 유효성 검사, CORS 사용 |
성능 | 캐싱, 압축, 비동기 처리 구현 |
RESTful API 설계 주요 원칙
리소스 기반 아키텍처
RESTful API 는 리소스를 주요 구성 요소로 사용한다. 리소스는 수정하거나 사용할 수 있는 모든 데이터 또는 객체를 말한다.
각 리소스는 고유한 URI를 가진다. 이를 통해 사용자는 기본적인 웹 메서드를 사용해서 리소스에 접근하고 수정할 수 있다.
예시 | URI |
Products | /products |
Customers | /customers |
Orders | /orders |
Stateless Communication(무상태 통신)
RESTful API에서는 각 요청을 완료하는데 필요한 모든 정보가 포함되어 있어야 한다. 서버는 요청 간에 클라이언트 정보를 별도로 보관하지 않는다.
이로 인해 RESTful API는 확장과 변경이 쉬워지고, 전체 시스템에 영향을 주지 않고 서버를 추가하거나 제거할 수 있다.
Client - Server 분리
RESTful API는 클라이언트와 서버를 분리해 유지한다. 각각의 역할이 있다.
역할 | 작업 |
Client | 서버에 요청을 보냄 |
Server | 요청을 처리하고 응답을 보냄 |
Web Method
RESTful API는 모든 리소스에 대해 동일한 웹 메서드를 사용한다. 이로 인해 클라이언트가 API를 쉽게 사용할 수 있다.
메서드 | 용도 |
GET | 데이터 조회 |
POST | 새 데이터 생성 |
UPDATE | 기존 데이터 갱신 |
DELETE | 데이터 삭제 |
Layer System
RESTful API는 계층으로 구축된다. 각 계층은 특정 작업을 처리한다. 이로 인해 API가 유연하고 확장에 쉬워진다.
계층 | 작업 |
Presentation | 사용자에게 데이터 표시 |
Business Logic | 주요 작업 처리 |
Data Access | 데이터 관리(저장/수정/삭제) |
좋은 URI 설계 방법
리소스 네이밍
리소스 이름에 복수 명사를 사용한다. 이름에 동사나 약어를 사용하지 않는다.
Good Example | Bad Example |
/products | /getProducts |
/customers | /cust |
/orders | /order-info |
관계를 위한 URI 구조화
리소스 간의 관계를 보여준다. 이렇게 관계를 URI에서 보여주면 연결 데이터간의 관계를 이해하기 쉽다.
관계 | URI 예시 |
제품 주문 | /proudcts/{product_id}/orders |
고객 주소 | /customers/{customer_id}/addresses |
쿼리 파라미터 사용
쿼리 파라미터를 사용해 반환되는 데이터를 변경한다. 필수 정보는 쿼리 파라미터에 사용하지 말자
목적 | Example |
필터링 | /products?category=electronics |
정렬 | /products?price=desc |
결과값 개수 제한 | /orders?status=pending&limit=10 |
API 버전 관리
변경 사항을 적용할 때 사용자를 위해 이전 버전의 API를 계속 작동시켜야 한다.
Method | Example | How it works |
URI 버전 | /vi/products | URI에 버전 포함 |
쿼리 파라미터 | /products?version=1 | 쿼리로 버전 추가 |
Header | API-Version: 1 | 헤더 사용 |
HTTP 메서드 제대로 사용하기
RESTful API를 만들 때, CRUD(생성, 읽기, 수정, 삭제) 작업에 HTTP 메서드를 제대로 사용하는 것이 중요하다.
다음은 HTTP 메서드별 가이드이다.
GET: 데이터 가져오기
GET 메서드는 서버에서 데이터를 가져오는데 사용된다. 어떠한 데이터도 변경되지 않는다. Request는 비어있고, Response에는 요청한 데이터가 포함된다.
HTTP 메서드 | CRUD 작업 | Request | Response |
GET | 읽기(Read) | 없음 | 요청한 데이터 |
POST: 새 리소스 생성
POST는 서버에 새로운 데이터를 생성할 때 사용한다. 새 데이터를 request로 보내면 서버는 생성된 데이터와 ID를 response로 보낸다.
HTTP 메서드 | CRUD 작업 | Request | Response |
POST | 쓰기(Write) | 새 데이터 | 생성된 데이터 + ID |
PUT: 전체 리소스 수정
PUT 메서드는 기존 리소스의 전체 내용을 변경하는데 사용된다. Request에 수정할 전체 리소스를 담아 보내면 서버는 수정된 리소스를 Response로 보낸다.
HTTP 메서드 | CRUD 작업 | Request | Response |
PUT | 수정/교체(Update) | 수정할 전체 데이터 | 수정된 데이터 |
DELETE: 리소스 삭제
DELETE는 리소스를 제거할 때 사용된다. 별도 request를 보내지 않고, 서버에서는 성공여부를 response로 보낸다.
HTTP 메서드 | CRUD 작업 | Request | Response |
DELETE | 삭제(Delete) | 없음 | 삭제 성공 메시지 |
PATCH: 부분 수정
PATCH는 리소스의 일부를 수정할 때 사용도니다. 수정하려는 데이터만 보내면 서버는 수정된 리소스를 response로 보낸다.
HTTP 메서드 | CRUD 작업 | Request | Response |
PATCH | 수정(Update) | 변경된 데이터 일부 | 수정된 데이터 |
HEAD, OPTIONS: 메타데이터 가져오기
HEAD와 OPTIONS는 리소스 자체를 가져오지 않고 리소스에 대한 정보를 가져오는 용도로 사용된다.
HEAD는 헤더를 제공하고, OPTIONS는 사용 가능한 메서드를 알려준다.
HTTP 메서드 | CRUD 작업 | Request | Response |
HEAD | 정보 가져오기 | 없음 | 헤더 |
OPTIONS | 허용된 메서드 가져오기 | 없음 | 허용된 메서드 |
요청(Request)와 응답(Response) 관리
RESTful API를 만들 때, 클라이언트-서버 간의 좋은 커뮤니케이션을 위해서 요청과 응답을 잘처리하는 것이 중요하다.
Contents 협상 기본
컨텐츠 협상을 통해 클라이언트와 서버가 어떻게 응답을 주고받을지 합의할 수 있다.
이는 리소스가 JSON, XML, CSV등 다양한 방식으로 표현될 수 있을 때 유용하다.
클라이언트는 원하는 원하는 응답 형식을 요청하면, 서버는 형식에 맞춰 응답 데이터를 전달한다.
단계 | Action | Example |
1. 클라이언트 Request | 클라이언트가 특정 형식을 요청한다. | GET /users HTTP/1.1 Accept: application/json |
2. 서버 Response | 서버가 해당 형식으로 데이터를 전송 | HTTP/1.1 200 OK Content-Type: application/json |
올바른 HTTP Status Codes 사용
HTTP 상태 코드는 클라이언트에게 요청에 대한 결과를 알려준다. 올바른 상태 코드를 사용하면 클라이언트가 응답을 이해하고 대응하는데 도움이 된다.
Code | 의미 | 사용 시기 |
200 OK | 요청 성공 | 요청이 성공했을 때 |
400 Bad Request | 요청이 잘못됨 | 클라이언트가 잘못된 데이터를 보냈을 때 |
404 Not Found | 요청한 것을 찾을 수 없음 | 리소스가 존재하지 않을 때 |
500 Internal Server Error | 서버에 문제 발생 | 서버에 문제가 생겼을 때 |
일관된 오류 처리
좋은 오류 처리는 클라이언트가 문제를 이해하고 해결하는 데 도움이 된다.
오류를 잘 처리하는 방법은 아래와 같다.
- 표준 HTTP 상태 코드 사용
- 명확한 오류 메시지 제공
- 코드나 ID 같은 오류 상세 정보 포함
- API 전체에서 동일한 오류 형식 사용
페이지네이션과 필터링 구현
API 가 커지면 많은 양의 데이터를 반환하게 된다. 페이지네이션과 필터링은 이를 관리하는 데 도움이 된다.
- 페이지네이션: 한 번에 전송되는 데이터 양을 줄인다.
- 필터링: 많은 데이터 중 특정 정보를 더 쉽게 찾을 수 있도록 해준다.
기능 | 구현 방법 | Example |
페이징 | 쿼리 파라미터 사용 | /users?page=2&limit=10 |
필터링 | 고객이 원하는 카테고리 지정 | /products?category=electorinics |
메타데이터 | 결과에 대한 추가 정보를 제공 | 총 개수 또는 페이지 크기 포함 |
API 성능 개선
API를 성능 개선하는 것은 사용자 만족도, 더 낮은 비용, 더 쉬운 성장을 위해 중요하다.
캐싱
캐싱은 자주 사용되는 데이터를 근처에 저장해두기때문에 DB까지 멀리 가져올 필요가 없다.
이렇게 하면 API가 더 빨라지고 서버 리소스를 덜 사용하게 된다. 캐싱은 두 가지 유형이 있다.
유형 | 설명 |
클라이언트 캐싱 | 사용자의 기기에 데이터를 저장 |
서버 캐싱 | 서버에 데이터를 저장 |
Cache-Control 및 ETag와 같은 HTTP 헤더를 사용해서 캐싱 작동 방식을 제어한다.
데이터 압축
데이터를 압축하면 더 작아지기 때문에 인터넷에서 더 빨리 주고 받을 수 있다. 이는 API 응답을 더 빠르게 만든다.
Method | 작동 원리 |
Gzip | 일반적인 압축 방법 |
Brotli | Gzip 보다 최신 방법이며 때때로 더 좋은 성능을 보인다. |
Deflate | 압축을 위한 또 다른 옵션 |
비동기 처리
비동기로 처리하면 API가 여러 작업을 한 번에 처리할 수 있기 때문에 더 빠르고 반응성이 더 좋아진다.
- Node.js와 같은 비동기 방식으로 작동하는 프로그래밍 언어를 사용한다.
- RabbitMQ와 같은 메시지 큐를 사용하여 작업을 하나씩 처리한다.
일괄 작업 처리
하나의 API 호출로 여러 작업을 수행할 수 있다. 즉, 호출이 줄어들고 속도가 향상된다.
POST /product-import
[
{
"name": "Cool Gadget",
"price": "$ 12.45 USD"
},
{
"name": "Very cool Gadget",
"price": "$ 19.99 USD"
},
...
]
이점 | 설명 |
호출 횟수 감소 | 여러 호출 대신 하나의 호출로 모든 작업을 처리 |
더 빠른 속도 | 서버와의 오고가는 시간이 줄어든다. |
서버 부하 감소 | 서버는 여러 개의 작은 작업 대신 하나의 큰 작업을 수행한다. |
...내용 주기적으로 추가
'Network' 카테고리의 다른 글
HTTP - 헤더 정보 (0) | 2023.08.01 |
---|---|
HTTP - 알아두면 좋은 URI 설계 개념 (0) | 2023.08.01 |
HTTP - HTTP 메서드 (0) | 2023.07.20 |
HTTP - HTTP 기본 메시지 (0) | 2023.07.20 |
Network - TCP, UDP (0) | 2023.06.04 |