티스토리 뷰
이 글은 M-Way Solutions 회사에서 운영하는 기술 블로그 중 10-best-practices-for-better-restful-api 포스트를 사전허락을 받아 번역한 글입니다.
웹 API는 지난 해에 매우 중요한 주제가 되었습니다. M-Way Solutions는 매일 다른 백엔드 시스템과 함께 프로젝트를 진행하므로 깔끔한 API설계의 중요함을 알게 되었습니다.
일반적으로 우리는 웹 API를 RESTful 디자인으로 설계합니다. REST의 개념은 API구조를 논리적 리소스들로 분리하는 것입니다. 리소스들과 함께 HTTP 메서드인 GET, DELETE, POST 및 PUT를 사용합니다.
깔끔한 RESTful API 설계를 위한 10가지 관례를 소개하겠습니다.
1. 동사말고 명사 사용
쉽게 설명하면 아래의 구조를 모든 리소스에 적용시키면 됩니다.
Resource | GET read | POST create | PUT update | DELETE |
---|---|---|---|---|
/cars | 자동차 정보 리스트 반환 | 신규 자동차 정보 등록 | 자동차 정보 대량 업데이트 | 모든 자동차 정보 삭제 |
/cars/711 | 해당 자동차 정보 반환 | 메서드 허용 안함(405) | 해당 자동차 정보 업데이트 | 해당 자동차 정보 삭제 |
아래처럼 동사를 사용하면 안됩니다.
/getAllCars
/createNewCar
/deleteAllRedCars
2. 상태를 변경할 때 GET 메서드와 쿼리 파라미터 사용금지
상태를 변경할 때는 GET 메서드 대신 PUT, POST 그리고 DELETE 메서드를 사용합니다.
아래처럼 상태변경에 GET 메서드를 사용하면 안됩니다.
GET /users/711?activate 또는
GET /users/711/activate
3. 복수 명사 사용
단수 명사와 복수 명사를 섞어 사용하면 안됩니다. 모든 리소스에 복수 명사만을 사용하여 간결함을 유지시킵니다.
/car 대신 /cars 사용
/user 대신 /users 사용
/product 대신 /products 사용
/setting 대신 /settings 사용
4. 관계 형태는 하위 리소스를 사용
한 리소스가 또 다른 리소스와 관계가 있다면 하위 리소스 형태를 사용합니다. (역자첨언: 여기서 711, 4와 같은 숫자는 해당 리소스의 고유 값을 나타냄 - 예를들어 데이터베이스 테이블의 PK)
# 711 자동차의 전체 운전자 정보 리스트를 반환
GET /cars/711/drivers/
# 711 자동차의 4 운전자 정보 반환
GET /cars/711/drivers/4
5. 직렬화 포맷에는 HTTP 헤더 사용
클라이언트와 서버는 통신을 하려면 어떤 포맷의 데이터인지 알아야 합니다. HTTP 헤더에 데이터의 포맷을 명시하면 됩니다.
Content-Type 은 요청 포맷을 정의합니다. Accept 는 수용가능한 포맷 목록을 정의합니다.
6. HATEOAS 사용
HATEOAS는 “하이퍼텍스트 링크는 API에서 더 나은 접근성을 위해 만들어야 한다”는 원칙입니다.
(역자첨언: Hypermedia as the Engine of Application State - 어플리케이션 엔진의 상태/정보를 하이퍼미디어로 표현. 예를들어 사용자정보를 입력(POST)하는 요청 후 사용자를 조회(GET), 수정(PUT), 삭제(DELETE)할 수 있는 URI를 동적으로 알려주게 되는 것.)
{
"id": 711,
"manufacturer": "BMW",
"model": "X5",
"seats": 5,
"drivers": [{
"id": "23",
"name": "Stefan Jauker",
"links": [{
"rel": "self",
"href": "/api/v1/drivers/23"
}]
}]
}
7. 결과반환 리스트에 필터링, 정렬, 결과요소 선택, 페이징 기능을 제공하기
필터 기능 :
모든 결과 속성에 유니크한 쿼리 파라미터를 사용하거나 필터링을 위한 쿼리 언어를 사용합니다.
# 빨간색 자동차 목록을 반환
GET /cars?color=red
# 좌석이 최대 2개인 자동차 목록을 반환
GET /cars?seats<=2
정렬 기능 :
오름차순, 내림차순 정렬을 여러 결과 속성에 사용할 수 있도록 제공합니다.
GET /cars?sort=-manufactorer,+model
결과요소 선택기능 :
모바일 클라이언트의 경우 결과 리스트에 있는 모든 속성들을 이용하지 않고 몇몇 속성들만 필요할 때도 있습니다. API 이용자가 몇몇 속성만 선택하여 결과를 반환받을 수 있도록 제공해야 합니다. 이는 네트워크 트래픽 감소와 API 호출 응답속도를 증가시켜 줍니다.
GET /cars?fields=manufacturer,model,id,color
페이징 기능 : limit(한 페이지 나타낼 결과 갯수) 과 offset(시작점)을 이용합니다. 이는 사용자에게 유연성을 제공하고 데이터베이스에 흔히 사용되는 기법입니다 (역자첨언: 데이터베이스 LIMIT, OFFSET 연산자 참조). LIMIT=20, OFFSET=0 을 기본 값으로 설정하면 됩니다.
GET /cars?offset=10&limit=5
반환 결과의 총 갯수를 사용자에게 알려주고 싶으면 X-Total-Count 라는 커스텀 HTTP 헤더를 이용하면 됩니다.
HTTP Link 헤더에 이전, 다음 페이지에 대한 링크가 잘 제공되어야 합니다. 사용자가 직접 URL을 이용하는 것 보다 헤더 값에 명시된 URL을 이용하여 페이지를 이동하게 하는 것이 중요합니다.
Link: <https://blog.mwaysolutions.com/sample/api/v1/cars?offset=15&limit=5>; rel="next",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=50&limit=3>; rel="last",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=0&limit=5>; rel="first",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=5&limit=5>; rel="prev",
8. API 버전 관리
API 버전을 만들고 버전이 없는 API는 릴리즈 하지 않도록 합니다. 심플한 서수를 사용하고 2.5 같은 점 표기법은 피하도록 합니다.
mwaysolutions에서는 url에 v로 시작하는 단어로 API 버전을 관리합니다.
/blog/api/v1
9. HTTP 상태 코드로 에러 핸들링
에러 핸들링 없이 API와 상호작용은 매우 어려운 일 입니다. 에러 스택과 함께 HTTP 500을 반환하는 기본 에러 반환은 그닥 도움이 되지 않습니다.
HTTP 상태 코드 이용
HTTP 표준에서 결과 값을 표현하기 위해 70개가 넘은 상태 코드를 제공합니다.
200 – OK – Eyerything is working
201 – OK – New resource has been created
204 – OK – The resource was successfully deleted
304 – Not Modified – The client can use cached data
400 – Bad Request – The request was invalid or cannot be served. The exact error should be explained in the error payload. E.g. „The JSON is not valid“
401 – Unauthorized – The request requires an user authentication
403 – Forbidden – The server understood the request, but is refusing it or the access is not allowed.
404 – Not found – There is no resource behind the URI.
422 – Unprocessable Entity – Should be used if the server cannot process the enitity, e.g. if an image cannot be formatted or mandatory fields are missing in the payload.
500 – Internal Server Error – API developers should avoid this error. If an error occurs in the global catch blog, the stracktrace should be logged and not returned as response.
(역자첨언: HTTP 상태코드에 대한 상세한 설명은 다음을 참조하세요.)
에러 정보제공
모든 예외는 에러 페이로드에 매핑되어야 합니다. 다음은 JSON 페이로드에 대한 예시 입니다.
{
"errors": [
{
"userMessage": "Sorry, the requested resource does not exist",
"internalMessage": "No car found in the database",
"code": 34,
"more info": "http://dev.mwaysolutions.com/blog/api/v1/errors/12345"
}
]
}
10. HTTP 메서드 오버라이딩 허용
일부 프록시 서버들은 GET과 POST 메서드만 허용합니다. 이러한 제한없이 RESTful API를 제공하려면 HTTP 메서드를 오버라이드할 필요가 있습니다.
POST 메서드에 X-HTTP-Method-Override 커스텀 HTTP 헤더를 통해 오버라이드를 하면 됩니다.