Representational State Transfer
HTTP 프로토콜을 사용하여 REST API 를 요청해야 한다.
경로: 서버상의 리소스를 식별할 수 있는 주소
HTTP 메서드: 이 리소스를 가지고 무슨 행위를 하고 싶은 지 표시해주는 역할
HTTP 상태 코드: 접수된 요청의 처리가 어떻게 되어가는지를 의미
Response body: 요청의 경로로 식별된 리소스의 콘텐츠를 포함
JSON 데이터 포맷
JSON은 초기엔 Javascript 프로그래밍에서 데이터를 표현하기 위해 등장했던 텍스트 데이터 포맷이지만 그 이름과 달리 지금은 언어와 상관없이 사용할 수 있다.
JSON은 어떤 프로그래밍 언어에서든 처리하기가 용이하고 읽고 쓰기가 쉽다. 이러한 장점 덕에 JSON은 데이터베이스와 설정 파일 등에서 사용되며 당연히 API 에서도 쓰기고 있다.
HTTP는 WWW(World Wide Web)의 기초다.
프로그래밍 언어에 구애받지 않는 프로토콜로 애플리케이션 간 문서(리소스)를 인터넷을 통해 주고받을 목적으로 디자인 되었다.
HTTP는 광범위한 애플리케이션에서 사용되고 있지만 가장 유명한 것은 웹 브라우저이다.
웹 브라우저는 HTTP를 이용하여 웹 서버가 호스팅하는 웹 사이트와 의사소통한다.
http://abc.com/about 이라고 주소창에 입력하면
abc.com 을 호스팅하는 서버로 GET /about HTTP request
response로 위 URL에 해당하는 HTML 페이지를 보내준다.
목적이 무엇이든 기본 HTTP 요청에는 HTTP 메서드와 리소스 경로가 꼭 포함된다. HTTP 메서드는 경로로 식별된 자원으로 수행할 작업을 나타낸다.
REST API는 HTTP 프로토콜을 이용해서 목표를 표현한다.
GET (가져오다), POST (보내다)
리소스는 경로로 식별되며 액션은 HTTP 메서드를 의미한다.
리소스를 프로그래밍적 표현으로 옮기기 전에 우선 기능적 요구사항을 분석해야 한다.
우선 리소스와 리소스 사이의 관계를 식별해야 하고, 리소스별로 가능한 액션과 파라미넡, 무엇이 리턴되는지 식별해야 한다.
리소스들은 다른 리소스들과 관계가 있을 수도, 없을 수도 있다. 또한 일정한 타입의 리소스 여러 개를 포함하는 리소스도 있다.
이런 리소스를 콜렉션 이라 부른다.
REST 리소스의 경로는 반드시 유일해야 한다. 이 점을 제외하면 REST의 공식적인 규칙은 없다.
ex. /c, /{productId}
{productId} 같은 경로에서 쓰이는 변수들은 경로 파라미터 path parameter라고 부른다.
하지만 c 보다는 명시적으로 경로를 구성하는 편이 더 좋다. c 대신 catalog로 사용하는 게더 좋다.
사또한 리소스를 폴더 같은 계층적 구조로 표현할 수 있다. 즉 상품의 경우 /products/{productId}로 표현할 수 있다.
리소스의 경로는 반드시 사용자 친화적이어야 한다. API는 사용자들이 경로를 해석하기 쉬어야 하기 때문에 경로에서 많은 정보를 제공할수록 더 좋다.
파라미터는 일반적인 경로 뒤 ? 다음에 있게 된다. name=value 형태.
만약 여러개라먼 &(앰퍼샌드) 로 연결해준다.
Method | Meaning | Req parameters | Return |
---|---|---|---|
POST | 리소스의 생성하기 | 리소스 정보 | 새로 생성된 리소스의 컨텐츠 |
GET | 리소스 가져오기 | X | 리소스에 해당하는 콘텐츠 |
DELETE | 리소스 삭제하기 | X | X |
PATCH | 리소스 일부 수정하기 | 수정하고 싶은 정보 | X |
PUT | 리소스 교체, 없는 경우 생성할 수 있음 | 교체(또는 생성)하고 싶은 정보 | X (생성된 경우는 생성된 리소스) |
HTTP 메서드의 기본적인 CRUD(Create, Read, Update, Delete) 기능과 매핑 시킬 수 있다.
이 액션들은 컨슈머 관점에서 만들어진 것이기 때문에 DELETE로 요청했다고 해서 실제 데이터베이스에서 해당 리소스를 정말 삭제해야한다는 의미는 아니다.
단순히 상태를 inactive로 변경할 수도 있다.
API 의 디자인은 데이터베이스, 구조체, 오브젝트와 같은 여타 프로그래밍적인 표현과 똑같이 시작한다. 단순히 속성 property를 나열하고 컨슈머 관점을 고수하는 것이다.
컨슈머가 반드시 데이터를 이해하도록 만드는 동시에 내부 동작 원리를 노출하지 않는 디자인을 만들어야 한다.
속성이 필수인지 아닌지 나타내는 것은 컨슈머와 프로바이더 모두에게 매우 중요하다. 컨텍스트에 따라 필수 여부가 다를 수 있기 때문이다.
상품이 생성될 때 상품의 식별자인 참조 정보는 백엔드에서 생성된다. 그래서 컨슈머가 상품을 추가할 때 리퀘스트에 참조 정보를 포함해서 전달할 필요가 없다. createdAt과 같이 백엔드에서 시점을 알아서 생성할 수 있는 속성은 파라미터에 포함할 필요가 없다.
컨슈머는 반드시 파라미터로 필요한 데이터를 모두 제공할 수 있어야 한다. 만약 데이터가 제공되지 않았다면 목표를 놓쳤거나 프로바이더 관점이 남아있을 가능성이 크다.
REST 리소스의 액션을 HTTP 메서드와 연결짓는 것을 실패할 때, 가장 먼저 해볼 수 있는 선택지는 액션 그 자체를 의미하는 리소스를 만드는 것.
액션 리소스는 명사로 표현되지 않고 동사로 표현된다.
ex. POST cart/check-out, POST /check-out-cart
HTTP 메서드 POST는 유즈케이스에 적합한 다른 메서드가 없을 때 기본으로 택하는 메서드다.
사용자 편의성과 규칙 준수 사이에서 균형을 잘 잡아야 한다!
Xerox Courier RPC -> SOAT -> REST -> gRPC, GraphQL
예로부터 지금까지 소프트웨어를 원격에서 커뮤니케이션할 수 있게 해주는 프로그래밍 인터페이스는 늘 존재했으며, 각 각의 명세와 장단점을 가지고 있다.
하지만 그게 무엇이든 간에 API 를 디자인하는 행위는 같은 목표를 가지고 있다.
REST 아키텍처 스타일의 목표는 효율적이고 확장 가능하며 안정적인 분산시스템을 구축하는 것이다. 분산 시스템은 함께 작동하고 네트워크를 통해 커뮤니케이션하는 서로 다른 컴퓨터에 있는 소프트웨어 조각으로 구성된다.
장점
위 모든 것들을 충족하기 위해서는 소프트웨어 아키텍처가 아래의 제약사항을 충족해야한다.
클라이언트/서버 분리
스테이트리스 stateless : request를 처리하는데 필요한 모든 정보는 해당 request에 포함되어 있어야 한다. 클라이언트는 요청을 처리하는데 필요한 그 어떤 컨텍스트도 서버의 세션에 담지 않는다.
캐시 가능성 Cacheability : request에 대한 response는 저장 가능 여부(재요청을 하지 않고 재사용할 수 있는) 및 기간을 표시해야 한다.
레이어드 시스템 Layered system : 클라이언트가 서버와 상호작용 할 때, 오직 서버만을 알고 있어야 한다. 인프라는 뒷단에 숨겨져 있어야 하며 하나의 레이어만 볼 수 있어야 한다.
코드 온 디멘드 Code on demand : 서버는 필요하다면 클라이언트에 실행간으한 코드를 전송할 수 있어야 한다. (ex. javascript)
유니폼 인터페이스 Uniform interface : 모든 상호작용은 식별된 리소스의 개념에 따라 이루어져야 한다. 또한 상호작용은 리소스의 표현이 무엇을 의미하는 지와 이 리소스들로 무엇을 할 수 있는지 알려줄 수 있는 모든 메타데이터를 제공해야 한다.
REST 인터페이스를 사용하는 것은 리소스 상태의 표현을 전송하는 것으로 구성된다.