송민준의 개발노트

RESTfull API 설계 고려사항들... 본문

네트워크

RESTfull API 설계 고려사항들...

송민준 2020. 9. 7. 22:38

● Rest란?

Representational State Transfer이라는 용어의 약자이다.

로이 필딩이란 사람에게서 나온 개념이다.

 

● Rest의 구성은?

1. 자원(RESOURCE) - URI

2. 행위 - HTTP METHOD

3. 표현(Representations)

 

● Rest의 특징은?

1. Uniform interface

- URI로 지정한 리소스에 대한 조작을 통일되고 한정적 인터페이스로 수행하는 아키텍처임

2. Stateless

- 상태가 없는 특징을 가진다. 즉 상태정보를 따로 저장하고 관리하지 않는다.

3. Cacheable(캐시 가능)

- HTTP가 가진 캐시 기능을 적용 가능함

4. Self-Descriptiveness

- 자체 표현 구조를 통해 쉽게 이해할 수 있다.

5. Client-Server

- 각각 구분이 명확해서 서로간 의존성이 줄어들고 개발내용이 명확해짐

6. 계층형

- 다중 계층으로 구성 가능, 보안, LB, 암호화 등 계층을 추가해 구조상 유연상을 둘 수 있음

● URL Rules

1. 마지막에 ' / ' 를 포함하지 않는다.

//Bad
http://test.com/test/

//Good
http://test.com/test

 

2. _ 대신 - 를 사용한다.

//Bad
http://test.com/test/case_one

//Good
http://test.com/test/case-one

3. 소문자를 사용한다.

//Bad
http://test.com/test/caseOne

//Good
http://test.com/test/case-one

4. 동사(행위)는 URL에 포함하지 않는다.

//Bad
POST : http://test.com/test/1/delete-case/1

//Good
DELETE http://test.com/test/1/case/1

5. 컨트롤 자원을 의미하는 URL 예외적으로 동사를 허용한다.

//Bad
http://test.com/test/duplicating

//Good
http://test.com/test/duplicate

6. 컬렉션, 스토어 이름으로 복수 명사를 사용해야 한다.

//Bad
http://test.com/test/1

//Good
http://test.com/tests/1

7. URI에 행위에 대한 동사 표현이 들어가면 안된다.

//Bad
Delete http://test.com/test/delete/1

//Good
Delete http://test.com/test/1

8. 확장자가 들어가지 않는다.(ex. jpg) - URI 는 고유한 리소스를 나타내야함

 

//Bad
Delete http://test.com/test/dog.jpg

//Good
Delete http://test.com/test/dog

 

● HTTP Headers

1.Content-Location

- POST 요청의 대부분은 반환되는 응답 리소스의 결과가 항상 동일하지 않는다.

POST /users
{
	"name": "hak"
}

위와 같은 요청은 매번 다른 리소스를 반환함.

/users/1
/users/2
/users/3
...

따라서 응답 헤더에 새로 생성된 리소스를 식별할 수 있는 Content-Location 속성을 이용

HTTP/1.1 200 OK
Content-Location: /users/1

- 반면 GET, PUT 등의 요청은 반환되는 응답 리소스가 동일하다.

- HATEOAS로 Content-Location을 대체할 수 있다.

 

2. Content-Type

- application/json을 우선으로 제공함.

- 응답 포맷을 여러개로 나누지 말자(ex. xml 같은...)

 

3. Retry-After

- 비정상적인 방법(디도스 공격 등)으로 API 서버를 이용하려는 경우 429 Too Many Requests  오류 응답과 함께 일정 시간 뒤 요청할 것을 나타냄

HTTP/1.1 429 Too Many Requests
Retry-After: 3600

 1) 인증

/auth   OAuth, JWT 같은 인증 관련 리소스를 요청하는 작업
/login  Id, Password를 이용한 로그인 작업

    ㉮ 비정상적인 요청(401) 일 때 두 가지 응답 방안

        ① n 시간 동안 n회만 요청 가능 : 429 응답과 함께 Retry-After b

        ② n 회만 요청 가능 : 더 이상 인증 관련 API 사용할 수 없다는 응답

 

 2) 자원 요청

/posts 특정 사용자가 의도적으로 서버 과부화를 목적으로 반복 요청하는 경우
- n시간 동안 n회 이상 요청한 경우

 

4. Link

- 페이징 처리를 위해 사용

developer.github.com/v3/#pagination

 

GitHub API v3

Get started with one of our guides, or jump straight into the API documentation.

developer.github.com

● Use HTTP methods

1. GET, POST, PUT, DELETE 4가지는 반드시 제공한다.

methods POST GET PUT DELETE
/users 사용자 추가 사용자 전체 조회 사용자 추가, 수정 사용자 전체 삭제
/users/1 405 ERROR 1번 사용자 조회 1번 사용자 수정 사용자 1번 삭제

 

2. OPTIONS, HEAD, PATCH를 사용하여 완성도 높은 API를 만든다.

 1) OPTION : 현재 ENDPOINT가 제공 가능한 API method를 응답함.

OPTIONS /users/1
------------------------
HTTP/1.1 200 OK
Allow: GET,PUT,DELETE,OPTIONS,HEAD

developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS

 

OPTIONS

The HTTP OPTIONS method requests permitted communication options for a given URL or server. A client can specify a URL with this method, or an asterisk (*) to refer to the entire server.

developer.mozilla.org

 2) HEAD : 요청에 대한 Header 정보만 응답한다. BODY가 없음

HEAD /users
--------------------
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 120

developer.mozilla.org/ko/docs/Web/HTTP/Methods/HEAD

 

HEAD

HTTP HEAD 메서드는 특정 리소스를 GET 메서드로 요청했을 때 돌아올 헤더를 요청합니다.

developer.mozilla.org

3) PATCH : PUT대신 PATCH method를 사용한다. 자원의 일부를 수정할 때는 PATCH가 목적에 맞는 method 다.

- 일반적으로 PUT 요청 시 일부분만 보낼 경우 나머지는 default로 되는게 원칙이지만 대부분 이렇게 개발하진 않는다.

// PUT 일부만 보낼 경우
PUT /user/1
{
	"level":11
}

-------------------------

HTTP/1.1 200 OK
{
	"name": null,
    "level": 11
}
// PUT 수정안하는 값까지 보냄
PUT /users/1
{
	"name": "1",
    "level": 11
}

----------------------------

HTTP/1.1 200 OK
{
	"name": "1",
    "level": 11
}

이상적인 방법

PATCH /users/1
{
	"level":11
}

----------------

HTTP/1.1 200 OK
{
	"name": "1",
    "level": 11
}

 

● Use HTTP status

1. 의미에 맞는 HTTP status를 리턴한다.

// Bad
HTTP/1.1 200 OK
{
	"result" : false
    "status" : 400
}

// Good
HTTP/1.1 400 Bad Request
{
	"msg" : "check your parameter"
}

 

2. HTTP status만으로 상태 에러를 나타낸다.

//Bad
HTTP/1.1 404 Not Found
{
	"code" : 404,
    "error_code" : -765
}

//Good
HTTP/1.1 404 Not Found
{
	"code" : -765,
    "more_info" : "https://test.com/users/-765
}

●  정확한 HTTP status code 사용

1. 성공 응답은 2XX로 응답

200 : OK
201 : Created 요청에 성공 및 새로운 리소스를 만든 경우에 응답
202 : Accepted 요청 받은 후 요청은 유효하나 서버가 아직 처리하지 않은 경우 응답(비동기)
      작업 완료 후 클라이언트에 push 작업을 하거나 클라이언트가 해당 작업의 상황을 알 수 있는
      조회 URL를 응답해야한다.

ex)
HTTP/1.1 202 Accepted
{
   "links": [
       {
           "rel": "self",
           "method": "GET",
           "href": "반환주소"
       }
   ]
}

204 : No Content 응답 body가 필요없는 자원 삭제 요청에 응답(DELETE)
      200 응답에 body가 null, {}, [], false 로 응답하는 것과는 다름
      204는 아예 없음

 

2 실패 응답은 4XX로 응답한다.

400 : [Bad Request] 클라이언트 요청이 미리 정의된 파라미터 요구사항을 위반한 경우
      사용자 입력 값, 에러 이유 등을 반드시 알린다.
      
      ex1)
      {
        "message" : "'name'(body) must be Number, input 'name': text123"
      }
      
      ex2)
      {
        "error": [
            {
               "location":"body",
               "param":"name",
               "value":"test123",
               "msg":"must be Number"
            }
        ]
      }
401 : [Unauthorized]
403 : [Forbidden] 해당 요청은 유효하나 서버 작업 중 접근이 허용되지 않은 자원 조회함
404 : Not Found
405 : [Method Not Allowed] 
     ex) 405와 404를 구분을 잘해야 한다.
         POST /users/1의 경우 404로 응답한다고 생각할 수 있지만 경우에 따라 405로 응답.
         /users/:id URL은 GET,PATCH,DELETE method는 허용되지만 POST는 불가함.

 

3. 5XX 에러는 사용자에게 나타내지 않는다.

 

● HATEOAS 사용

- REST API는 요청-응답 이라는 간단한 구조로 이루어져 있다. 여기서 문제는 간단한 응답만으론 사용자 리소스의 상태가 전이되기엔 정보가 부족하다는 것이다. 이 문제를 해결하기 위해 응답 객체에 해당 리소스의 상태가 전이될 수 있는  link들을 함께 제공한다. link들을 통해 리소스의 다음 상태 전이 정보를 동적으로 제공한다.

1. 구성 요소

  - 변경될 리소스의 상태 관계 rel - self :  현재 URL 자신

  - 요청 URL href

  - 요청 Method method

{
   "rel": "self",
   "href": "http://test.com/users/1",
   "method": "GET"
}

2. 응답 예제

201 Created
  {
  "id": 1,
  "name": "hak",
  "createdAt": "2018-07-04 14:00:00"
  "links": [
      {
        "rel": "self",
        "href": "http://api.test.com/users/1",
        "method": "GET"
      },
      {
      "rel": "delete",
      "href": "http://api.test.com/users/1",
      "method": "DELETE"
      },
      {
      "rel": "update",
      "href": "http://api.test.com/users/1",
      "method": "PATCH",
      "more_info": "http://api.test.com/docs/user-update"
      "body": {
              "name": "{The value to be modified}"
              }
      },
      {
      "rel": "user.posts",
      "href": "http://api.test.com/users/1/posts",
      "method": "GET"
      }
  ]
}

 

 

 

 

 

 

 

참고 블로그 및 문헌

sanghaklee.tistory.com/57

 

RESTful API 설계 가이드

1. RESTful API 설계 가이드 본 문서는 REST API를 좀 더 RESTful 하게 설계하도록 가이드할 목적으로 만들어졌다. 따라서, 기본적인 REST API 개념 설명은 아래의 링크로 대신한다. REST API 제대로 알고 사용

sanghaklee.tistory.com

 

'네트워크' 카테고리의 다른 글

윈도우 포트 킬(window port kill)  (0) 2020.07.03
HTTP/1.1 쿠키 헤더 필드  (0) 2020.01.10
HTTP/1.1 엔티티 헤더 필드  (0) 2019.12.30
HTTP/1.1 리스폰스 헤더 필드  (0) 2019.12.23
HTTP/1.1 리퀘스트 헤더 필드  (0) 2019.12.15