1. CRUD & API & REST
CRUD
REST에 대한 개념을 살펴보기 앞서, CRUD(Create, Read, Update, Delete)에 대한 개념을 먼저 살펴볼 필요가 있습니다. 위 개념은 HTTP 통신이나 Database 개념을 공부할 때에도 접하는 개념입니다.
각각의 개념을 정리하면 다음과 같습니다.
•
Create : 데이터베이스에 특정 자원을 생성(Create)
•
Read : 데이터베이스에 있는 특정 자원을 조회(Read)
•
Update : 데이터베이스에 있는 특정 자원을 갱신(Update)
•
Delete : 데이터베이스에 있는 특정 자원을 삭제(Delete)
데이터베이스 개념으로 접근하게 되면 CRUD는 다음과 같이 매핑될 수 있겠습니다.
Name | Function | SQL |
Create | 생성 | INSERT |
Read(Retrieve) | 읽기(인출) | SELECT |
Update | 갱신 | UPDATE |
Delete(Destroy) | 삭제(파괴) | DELETE |
API
위와 같이 CRUD 개념을 웹 상에서 기능으로 제공하고자 할 때 사용할 수 있는 방법이 API(Application Programming Interface)입니다. 이를 간단히 그림으로 표현하면 다음과 같이 표현할 수 있겠습니다.
Client(이용자)가 서버의 Database와 상호작용하여 CRUD 기능을 수행하고자 할 때 이를 위한 기능을 제공해주어야 합니다. 이를 위해 API와 같은 인터페이스가 제공될 수 있으며, 이용자가 제공된 API를 인가된 방법으로 사용하였을 경우 HTTP 프로토콜을 통해 서버의 Database와 상호작용이 가능합니다.
REST
REST란 REpresentational State Transrfer 의 약자입니다. REST는 API를 표현하는 방법이라고도 말할 수 있습니다. 먼저, 개념에 대해 간단하게 요약하게 되면 다음과 같이 표현할 수 있을 것입니다.
Representational(표현된) Status(자원의 상태) Transfer(전송)
표현된 자원의 상태를 전송하는 주체는 Client입니다. Client는 서버 내의 Database와 상호작용(Interaction)을 위해 API를 호출할 것입니다. 이때 API가 규약이 없이 작성된다면 다음과 같이 무분별할지라도 선언은 가능합니다.
•
GET /api/give-me-all-accounts
•
GET /api/give-me-my-account
•
POST /api/create-account
•
PUT /api/update-account-information
•
PATCH /api/partial-update-my-account-information
위와 같이 선언할지라도 API 통신에서는 아무런 문제가 되지 않습니다. 그러나 Client와 Server간의 원활한 커뮤니케이션을 위해 규약을 잡는 것이 서비스의 품질 향상과 유지보수 차원에서 좋아 보입니다. 이럴 때 REST라는 표현 방식을 도입하면 URI와 HTTP Method만으로도 API의 기능을 쉽게 유추할 수 있습니다.
REST의 표현 방법을 CRUD와 매핑하여 정의하면 다음과 같습니다.
HTTP Method | CRUD | SQL |
GET | Read(Retrieve or List) | SELECT |
POST | Create | INSERT |
PUT | Update | UPDATE |
PATCH | Partial update | UPDATE (some field) |
DELETE | Delete | DELETE |
또한 API의 URI를 선언하는 방법도 있습니다. 이는 따로 포스팅 하여 다루도록 하겠습니다.
위와 같은 REST 개념을 이용하여 API를 선언하는 방법을 통해 새로이 URI를 선언해보면 다음과 같이 수정해볼 수 있겠습니다.
•
GET /api/accounts
•
GET /api/accounts/{account-id}
•
POST /api/accounts
•
PUT /api/accounts/{account-id}
•
PATCH /api/accounts/{account-id}
REST는 API를 정의하는 일종의 아키텍쳐와 같다, 라고 이해하시면 좀 더 쉽게 와닿으실 거라고 생각합니다.
2. REST API
This chapter introduces and elaborates the Representational State Transfer (REST) architectural style for distributed hypermedia systems, describing the software engineering principles guiding REST and the interaction constraints chosen to retain those principles, while contrasting them to the constraints of other architectural styles. REST is a hybrid style derived from several of the network-based architectural styles described in Chapter 3 and combined with additional constraints that define a uniform connector interface. The software architecture framework of Chapter 1 is used to define the architectural elements of REST and examine sample process, connector, and data views of prototypical architectures.
REST라는 개념은 Roy Thomas Fielding 이라는 분의 박사학위 논문에서 비롯된 개념입니다. 이 박사학위 논문의 Chapter 5에서는 위와 같이 REST에 대한 개념을 정의하고 있습니다. 요약 및 정리해보면 REST API란, REST 아키텍처 스타일에 부합하는 API라고 말할 수 있겠습니다.
Client-Server
•
클라이언트와 서버를 분리하고 인터페이스로만 소통할 수 있게 해서 유저는 멀티플랫폼의 이동이 가능해지고 서버의 컴포넌트 를 단순화해 확장성을 향상. 각 컴포넌트들은 독립적으로 진화할 수 있다.
•
가령 클라이언트 환경은 단순히 브라우저의 문제뿐 아니라 모바일, 데스크탑, 랩탑 등의 다양한 환경으로 발산했는데 서버와 클라이언트단은 분리되어 서버는 이런 클라이언트의 문제를 고려할 필요가 없어졌다.
Stateless
•
클라이언트와 서버를 분리하고 인터페이스로만 소통할 수 있게 해서 유저는 멀티플랫폼의 이동이 가능해지고 서버의 컴포넌트 를 단순화해 확장성을 향상. 각 컴포넌트들은 독립적으로 진화할 수 있다.
•
가령 클라이언트 환경은 단순히 브라우저의 문제뿐 아니라 모바일, 데스크탑, 랩탑 등의 다양한 환경으로 발산했는데 서버와 클라이언트단은 분리되어 서버는 이런 클라이언트의 문제를 고려할 필요가 없어졌다.
Cache
•
클라이언트와 서버를 분리하고 인터페이스로만 소통할 수 있게 해서 유저는 멀티플랫폼의 이동이 가능해지고 서버의 컴포넌트 를 단순화해 확장성을 향상. 각 컴포넌트들은 독립적으로 진화할 수 있다.
•
가령 클라이언트 환경은 단순히 브라우저의 문제뿐 아니라 모바일, 데스크탑, 랩탑 등의 다양한 환경으로 발산했는데 서버와 클라이언트단은 분리되어 서버는 이런 클라이언트의 문제를 고려할 필요가 없어졌다.
Uniform Interface
Identification of resources
이 개념을 한글로 표현해보면 자원의 식별(Identification of resources)이라고 해석할 수 있겠습니다. 여기서 살펴봐야 할 중요한 것은 자원입니다. 자원은 시간이 지나면서 생성, 갱신, 삭제 등으로 상태가 계속해서 변화할 것이라는 가정을 둡니다. 그렇다면 자원을 식별(identification)하기 위해서는 자원에 대한 적절한 식별자(identifier)를 부여하는 것이 적절하겠습니다.
Manipulation of resources through representations
자원에 대한 식별이 가능하다면, 이 개념은 다양한 방식으로 조작이 가능해야 한다는 개념입니다. 클라이언트에서 특정한 표현으로 자원에 대해 요청을 하게 되면, 서버 또한 특정한 표현으로 응답을 하게 됩니다.
위와 같이 특정 server에서 특정 자원(something 중 1번)을 지정하여 요청하게 되면, Server는 HTTP Entity를 이용하여 자원에 대한 상태(status)를 표현(represent)할 수 있습니다.
self-descriptive messages
자기 서술적 메시지(self-descriptive messages)는 스스로 메시지인 자신을 표현할 수 있어야 한다는 개념입니다. 클라이언트가 서버에게 요청을 날릴 때, 그리고 서버가 클라이언트에게 응답할 때 메시지의 내용을 참고하여 적절한 작업이 가능하도록 스스로 어떤 메시지인지 표현하는 것이라고 할 수 있겠습니다. 이 말을 예시로 풀어서 설명해보도록 하겠습니다.
아래의 그림에서, HTTP의 형태로 API를 호출할 때 Header에서 Host를 예로 들어보겠습니다. Host에서는 내가 어디로 요청을 보낸 것인지 스스로 자신의 메시지를 설명할 수 있어야 한다는 뜻으로 해석이 가능합니다. Response에서도 마찬가지로 이러한 헤더 정보를 통해 자신의 메시지가 어디서 어떤 목적으로 전송되는지 확인이 가능할 수 있어야 한다는 제약조건입니다.
HATEOAS(hypermedia as the engine of application state)
HATEOAS란 하이퍼미디어를 통해 앱(클라이언트)의 상태를 변경시킬 수 있다는 개념입니다. 예로 <a href=""> 태그를 이용하여 특정 URI에 접근하고, 앱 상태를 변경할 수 있습니다. 그러나 만약 특정 URI를 통해 접근할 수 있는 하이퍼미디어 이외에 숨겨진 URI가 있다면 제공되지 않은 하이퍼미디어를 통해 앱 상태가 변경이 가능합니다. 이는 HATEOAS에 위배되는 사례라고 할 수 있습니다.
그렇다면 Backend의 입장에서는 특정 endpoint에 요청을 날리고 앱의 상태가 변경된다는 건 익히 이해하고 있을 것입니다. 그렇다면, 이에 대한 응답을 줄 때 link 정보를 함께 넘겨주게되면 HATEOAS에 위배되지 않는다고 주장할 수 있다는 의견이 많습니다만, 이러한 이슈를 모두 해결하면서 백엔드 서버에서 응답값을 고려하여 개발하기란 쉽지 않을 것 같습니다.
Layered System
• 인터넷 단위의 요구사항을 위한 행동을 향상하기 위해 이 제약을 도입. 이 제약은 OSI 7계층 모델처럼 컴포넌트가 인접한 컴포넌트 의외의 영역을 “볼 수 없는 것처럼”한다. 이를 통해 전체 시스템 복잡도에 한계를 주고 독립성을 증진한다. 레이어는 레거시 서비스를 감싸서 새 서비스를 레거시 클라이언트로부터 보호할 수 있다.
Code-On-Demand
• REST는 애플렛(Applet)이나 스크립트의 형태의 코드를 다운로드하고 실행해서 클라이언트 기능성이 확장되는 것을 허용한다.