REST (Representational State Transfer)

An API that provides network-based access to resources via a uniform interface of self-descriptive messages containing hypertext to indicate potential state transitions might be part of an overall system that is a RESTful application(link) - Roy T. Fielding
  • self-descriptive message?
    • 메시지 자체가 자기 자신을 설명하는 메시지. "어디로 가는가? 어떤 동작을 하는가?" 등이 메시지에 나타나야 함
    • 메시지를 제공하는 서버, 해석하는 클라이언트에 대한 의존이나 종속 없이 메시지가 자기 자신을 설명하게 되면, 서버나 클라이언트가 변경되더라도 메시지를 해석할 수 있다. (메시지를 변경해야 하는 경우가 없어진다)
  • potential state transition?
    • (HATEOAS, Hypermedia as the Engine of Application State)

 

  • 자원(Resource), 행위(Verb), 표현(Representation) 세 가지로 구성되는 웹(HTTP)에서 사용되는 아키텍쳐
    • 아키텍처 스타일(architectural style)이란, 그 스타일을 따르는 아키텍처가 지켜야 하는 제약조건들의 집합이다. 그냥 컨벤션 정도라고 생각해도 좋다.
  • 자원 ?
    • 실제 데이터와 URI. "DB에 들어가 있는 특정 레코드"같은 구체적 데이터를 의미할 수도 있고, "메인 페이지"와 같은 추상적인 데이터를 의미할 수도 있음.
    • 이러한 데이터들과 그에 접근하기 위한 URI를 자원이라 함.
  • 행위 ?
    • 자원에 대한 액션이라고 생각하면 되며 HTTP Method로 행위를 나타냄
  • 표현 ?
    • 리퀘스트에 대한 응답으로 반환되는 자원의 표현을 의미
    • 예를 들어 똑같은 `` asdf``라는 문자열을 응답으로 주더라도 content-type에 따라 다른 형태의 표현이 가능하다는 것

 

설계 시 생각해야 할 점?

Stateless
  • 어떤 작업을 위한 상태 정보를 따로 저장하고 있지 않는다는걸 의미
  • 상태를 저장하게 되면 상태에 따라 같은 요청에 대한 응답이 다를 수 있는데, 이러한 상황을 피하기 위함으로 보임(함수형이 그렇듯이)
  • 예를 들어 여러 Open API들 써보면 인증에 대한 부분을 매번 쿠키에 id/pw를 넣어서 보내거나, 토큰을 따로 발급받아서 매번 토큰을 붙여서 보낸다. 각각의 리퀘스트에 대한 상태를 저장하지 않고 독립적으로 처리되기 때문.
  • 결국 이러한 것도 side-effect을 줄이기 위한 맥락으로 이해할 수 있을 듯.

 

[URI는 자원을 가리키는데만 사용된다. (자원에 대한 액션이 URI에 포함되지 않는다.)]

  • 예를 들면 `` /people``까지만.

 

[자원에 대한 액션(행위)이 곧 HTTP Method (GET, POST, PUT, DELETE, ....)]

  • 자원에 어떤 액션을 할 지는 HTTP Method로 지정.
  • 예를 들어 자원을 삭제할 때는 `` DELETE /people/umbum``

 

[자원, 행위, 표현을 분리해서 구성할 때의 장점?]

  • 이렇게 구성하면 표현력이 좋아진다. 
  • 액션과 자원이 분리되어 있기 때문에 REST api 메시지가 의도하는 작업이 잘 나타남. (이로 인해 좀 더 self-descriptive한 메시지가 된다)
  • 그 밖에 캐시라던가, 클라이언트-서버 구조라던가 하는 얘기가 있지만 직접 REST api를 써보면서 경험한 장점은 이게 제일 컸던 것 같음
  • 하지만 경우에 따라 URI에 액션을 명시해야 하는 경우가 있는 등 항상 잘 들어맞지는 않음.

 

Safety와 Idempotence

https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Summary_table

  • Safety는 resource의 상태를 변경하느냐, 아니냐를 의미. 즉 read-only 이냐. 를 의미
  • idempotent는 같은 요청을 여러 번 보낸 effect와, 한 번만 보낸 effect가 동일한가. 를 의미
    • 즉 'a' 자원 생성 요청을 한 번 보내면 'a'가 생성되고, 이후 요청에 대해서는 'a'가 이미 존재한다. 라고 내려주고 상태를 변경하지 않으면 이 api는 idempotent하다고 볼 수 있다. 여러 번 요청과 한 번 요청의 effect가 동일하므로.
    • HTTP/서블릿 환경에서 멱등이라는 말은 동일 요청을 서버에서 어떤 잘못된 결과를 야기하지 않고 두 번 이상 이루어질 수 있다는 의미이다. 동일 요청은 동일 응답을 가져야 한다는 의미가 아니고, 요청으로 어떤 side-effect도 발생하지 말아야 한다는 의미도 아니라는 것에 유의하라.
      - 헤드퍼스트 서블릿 & JSP

 

자원 생성 및 수정. POST vs PUT vs PATCH

  • RFC 2616 POST : POST to a URL creates a child resouce at a server defiend URL
    • 자원의 위치(id)를 명시하지 않았을 때의 생성
    • `` POST /pet``
      • 같은 요청이라도, 보낼 때 마다 내용은 같고 id만 다른 `` /pet/1, .. /pet/2, ...``가 생성될테니 idempotent하지 않다.
  • RFC 2616 PUT : PUT to a URL create/replaces the resource in is entirely at the client defined URL
    • 자원의 위치(id)를 클라이언트가 지정할 때의 생성 또는 "대체(replace)"
    • `` PUT /pet/1``
      • 처음 요청을 보낼 때는 생성, 이후 부터는 "전체를 대체" 로 동작하도록 할 수 있음.
        • 하지만 생성을 PUT에 포함하지 않고 POST를 별도로 제공할 수도 있음.
      • "전체를 대체"(replace) 이므로 전체 데이터를 요청에 포함하여 받아야 함.
      • 전체를 대체하는 것이므로, 요청 데이터가 같은 경우 idempotent 해야만 함. (항상 같은 값으로 대체하면 결과가 매번 동일할 것임.)
      • "일부를 변경"(update)은 부분 수정 이므로, PATCH를 사용하는 편이 좋다.
  • RFC 5789 PATCH : PATCH to a URL updates part of the resource at that client defined URL
    • partial update가 핵심.
    • PATCH는 idempotent를 보장하지 않음. 즉 unsafe, non-idempotent 할 수 있음.
      • update 이기 때문. 예를 들어 ++업데이트 한다면 호출 할 때 마다 1씩 증가하게 되므로 

 

Pagination

```

/orders?offset=50&fetch=25

fetch 또는 limit

```

 

HTTP Status Code

  • 401 Unauthorized VS 403 Forbidden
    • 어떤 자원이 해당 유저에게 인가 후 접근 가능한 자원이면 401
    • 아예 접근 불가하면 403 (다른 사람 자원이라던가)
  • 구글은 로그인 실패 시 401이 아니라 200이 내려온다.
    • 생각해보면 로그인 이라는 비즈니스가 REST를 적용하기에 적절하지 않을 수도 있다. (REST가 항상 정답이 아니다)
    • accountInfo 조회, challenge 모두 POST 쓰는 것을 보니 REST 사용하지 않는 듯.

 

참고 ) 잘 모르겠다면 참고 docs

 

 

 

 

 


 

 

'System Design > external API design' 카테고리의 다른 글

API 응답 코드 계층 구조 설계  (0) 2022.02.26