이번 글에서는 REST API 를 구현하는데 도움이 되었던 내용을 공유하려고 한다. 앞으로 언급되는 내용들은 정답이 아니고, 하나의 약속임을 먼저 밝힌다.
우리가 약속할 내용을 다음과 같다.
- URL을 작성할 때 주의할 점
- SSR
- 버전관리
- 자원을 필터링해야 한다면 Query Parameter 를 이용하자.
- 데이터를 묶어서 전달해라.
- 약속된 상태코드를 사용해라.
- Stateless 하게 작성해라.
1. URL을 작성할 때 주의할 점
1.1 명사를 사용해라
URL은 우리가 제공 할 자원을 중심으로 구성되며, 자원은 반드시! 명사 로 써야하며 절대로 동사를 사용하면 안된다. 아래 예시를 보자
- GET /lectures - 강의 리스트를 조회한다.
- GET /lectures/12 - #12 라는 특정 강의을 조회한다.
- POST /lectures - 새로운 강의을 생성한다.
- PUT /lectures/12 - #12 라는 특정 강의을 수정한다.
- PATCH /lectures/12 - #12 라는 특정 강의을 부분적으로 수정한다.
- DELETE /lectures/12 - #12 라는 특정 강의을 제거한다.
1.2 복수형을 사용해라
반드시 따라야하는 네이밍 규칙은 없지만 URL은 반드시 깔끔하고 명확 해야 한다. 당신의 URL을 표현할 때, 문법적으로 복수형을 사용해야 할 때가 아니라도, 항상 복수형을 써야 한다.
person / people, goose / geese 와 같은 난해한 복수형들을 사용한다면 API를 사용하는 사람들의 짜증을 유발할 것이며, URL을 이해하는 어려울 것이다.
1.3 관계를 표현해라
자원들 간에 관계를 가질 수 있다면, RESTful 원칙은 아주 유용한 가이드를 제공해준다. 아래 몇가지 예시를 보자.
강의는 여러개의 평가를 가질 수 있다. 이 평가들은 /lectures endpoint 에 아래와 같이 맵핑되어 진다.
- GET /lectures/12/comments - #12 라는 강의의 평가 리스트를 조회한다.
- GET /lectures/12/comments/15 - #12 라는 강의의 평가 중 #5의 평가를 조회한다.
- POST /lectures/12/comments - #12 라는 강의에 새로운 평가를 생성한다.
- PUT /lectures/12/comments/5 - #12 라는 강의에 #5의 평가를 수정한다.
- PATCH /lectures/12/comments/5 - #12 라는 강의에 #5의 평가를 부분적으로 수정한다.
- DELETE /lectures/12/comments/5 - #12 라는 강의에 #5의 평가를 삭제한다.
2. SSR
항상 SSL을 사용해라. 이것은 API를 디자인하는데 있어 가장 기본적인 원칙이다. 당신이 만든 API의 endpoint 들이 SSL을 통해 노출 될 수 있도록 해라.
3. 버전관리
API는 항상 버전관리가 되어야 한다. 버전관리는 API endpoint들을 개발/수정하는데 있어 좀 더 빠르고, 유효하지 않는 요청들로 부터 도움을 준다. 또한, 오래된 API를 끊키지 않고 제공하면서 동시에 새로운 API도 제공 할 수 있도록 한다.
아래와 같이 버전을 사용해라!
/api/v1/lectures/
4. 자원을 필터링해야 한다면 Query Parameter 를 이용하자.
쿼리 파라미터를 이용하는 경우는 크게 아래 3가지로 나눌 수 있다.
- Filtering : 강의 리스트를 조회하는 endpoint
/lectures
가 있을 때, 당신은 열려 있는 강의만 조회할 수 있도록 제한하고 싶을 수도 있다. 그럴 때에는 다음과 같이 필터링을 하자. GET/lectures?state=open
. state 는 필터를 구현 할 수 있는 쿼리 파라미터다. - Sorting : 필터링과 유사하게, sort 는 Sotring 규칙을 표현할 수 있는 파라미터다. Sotring 할 필드들을 콤마로 구분하고, 내림차순으로 Sorting 하고 싶은 경우에는 앞에 - 를 붙이는 것이 일반적이다. 예를 들어, GET
/lectures?sort=priority, -created_at
은 강의의 우선 순위를 오름차순으로, 생성된 시간을 내림차순으로 정졀하여 조회한다. - Searching : 필터링과 정렬이 우리가 조회하려는 정보를 충분히 나타내는데 부족할 수 있다. 이 때, q 파라미터로 full-text search 를 지원하면, 좀 더 정확한 정보를 조회할 수 있다.
위 3가지를 조합한 예시를 보자.
- GET /lectures?sort=-updated_at - 최근에 업데이트 된 강의를 조회한다.
- GET /lectures?state=open&sort=-updated_at - 최근에 업데이트된 강의 중 열려있는 강의를 조회한다.
- GET /lectures?q=tutorial&state=open&sort=-priority,created_at - 우선순위가 높고, 생성된지 오래된 강의 순으로 검색하는데 검색어는 'tutorial' 이다.
5. 데이터를 묶어서 전달해라.
// Good 🙆
{
"success": true
"error": null
"data": {
{
"name": 'foo',
"rating": 4,
"guides": [
{
"name": "a",
"role": "A"
}.
]
}
}
}
// Bad 🙅
{
"name": 'foo',
"rating": 4,
"guides": [
{
"name": "a",
"role": "A"
}.
],
"success": true,
"error": null
}
데이터를 묶어서 전달하게 되면, 프론트엔드 개발자와 친해질 수 있다.
프론트엔는 아래와 같이 처리하면 된다.
const { data, error } = payload
if (error) { throw ...}
6. 약속된 상태코드를 사용해라
6.1. 요청한 데이터에 문제가 있을 경우
400
- 요청한 정보가 완전히 구성되어 있지 않은 경우422
- 요청한 정보가 구성은 맞지만, 값이 유효하지 않은 경우404
- 요청한 정보도 맞고, 값도 유효하지만, 데이터가 없을 경우409
- 이미 데이터가 있는 경우
6.2. 인증 오류
401
- access token이 만료되어 권한이 없는 경우403
- access token은 유효하지만, 접근 권한이 없는 경우
6.3. 일반적인 경우
200
- 성공204
- 정상적으로 처리되었지만, 반환되는 정보가 없는 경우500
- 서버쪽에 문제가 있는 경우
7. Stateless하게 작성해라
모든 상태는 Client Side 에서 처리 되어야 한다. 이 말은 요청 처리하는데 있어 모든 정보들이 요청 안에 포함되어 있어야 한다. 서버는 이전 요청에 대한 정보를 알고 있지 않으며 알고 싶어 하지도 않는다.
'잡지의 다음 페이지 내용이 궁굼해요' 라는 API를 만들 수 있을까?
/magazines/nextPage
와 같이 구성을 한다면, 서버는 아래와 같은 서비스 로직이 필요하다
nextPage = currentPage + 1
send(nextPage)
위 서비스 로직은 _Client Side_에 있어야 한다. 따라서 API는 아래와 같이 구성되면 클라이언트에서 모든 정보들을 넘겨줘야 한다.
GET/magazines/page/7
또는 GET /magazines?page=7
위 내용들이 당신의 멋진 API를 만드는데 조금이나마 도움이 되었으면 좋겠다.
'Web' 카테고리의 다른 글
OAuth 완벽하게 알고가기 (0) | 2020.04.09 |
---|