Restful API
Restful API란?
Restful API란 REST 아키텍처의 제약 조건을 준수하는 애플리케이션 프로그래밍 인터페이스(API)를 뜻한다. REST는 Representational State Transfer의 줄임말이다. HTTP URI를 통해 자원(Resource)를 명시하고, HTTP Method(POST, GET, PUT, DELETE)를 통해 자원에 대한 CRUD operation을 적용하는 것이다. 하지만 이 정의 자체는 진짜 REST API가 아닌 가짜 REST API라고 할 수 있다. 진짜 REST API는 이후 나오는 규약들을 모두 만족시켜야 REST API라고 부를 수 있다.
API란 Applcation Program들이 소통을 하기위한 명세라고 볼 수 있다. 그리고 API통신이란 이 명세를 지키며 Applcation 끼리 통신을 하는 것이다. 일종의 소프트웨어 인터페이스이며 다른 종류의 소프트웨어에 서비스를 제공하기 위해 존재한다.
- 자원(Resource)
- 자원을 구별할 수 있는 URI를 이용한다.
- 명사로 구성된다.
- 예를 들면 /classes/3/students/12 : 3반의 12번 학생을 가리키는 URI(Unifrom Resource Identifier)
- 이처럼 자원을 잘 표현하는 방식이다.
URI와 URL(Uniform Resource Identifer)이 헷갈릴 수 있는데 URL은 URI의 서브셋으로 해당 서버의 명확히 자원의 위치를 표시하는 경우 URL이며 URI라고 할 수 있고 추가적인 Identifier가 있다면 그것은 URL이 아니며 URI라고 할 수 있다.
- 행위(Verb)
- HTTP Method를 사용한다. (GET,UPDATE,PUT,POST 등)
- PUT /classes/3/students/12
- POST : 데이터를 넣을 때
- GET : 데이터를 조회할 때
- PUT : 데이터를 수정할 때 (entity 단위)
- PATCH : entity의 일부 데이터 수정
- DELETE : 데이터를 삭제할 때
한 가지 알고 가야하는 것이 있다. 바로 PUT과 PATCH 모두 데이터를 수정할 때 사용한다. 그럼 둘의 차이는 무엇일까? PUT은 전체를 수정하는 것이며 만약 데이터가 없다면 생성을 해야하기 때문에 자원 전체를 담아서 보내야 한다. 반면 PATCH는 일부만 수정하는 것이기 때문에 일부분의 데이터만 담아서 보내도 된다. 이것 외에도 PUT은 멱등성을 보장하며 PATCH는 멱등성을 보장하지 않는다는 차이도 있다. 완전히 대체하는 것이 아닌 일부 속성을 더한다는 메소드를 보내게 되면 그것은 더이상 멱등성을 보장하지 않게된다.
- 표현(Representation of Resource)
- client가 자원에 대한 조작을 요청하면 server는 이에 대한 응답을 보낸다.
- 보통 json이나 xml와 같은 form-data를 통해 데이터를 주고받는다.
정통 Rest
분산 하이퍼미디어 시스템을 위한 아키텍쳐 스타일이다. 아키텍쳐 스타일이란 제약 조건의 집합이다. 주어진 조건을 따라야 "Rest하다"라고 말할 수 있다.
- Rest는 HTTP를 기반으로 자원을 정의하고, 자원에 접근하는 방식을 정해 놓았다.
- Rest는 프로토콜이나 표준이 아니다.
- Rest를 하기 위해선 6가지 원칙을 지켜야 한다.
- Client-Server 구조 : 서버는 API를 제공, 클라이언트는 사용자 인증이나 세션, 로그인 정보를 관리하는 구조로 각각의 역할을 분리하여 서버와 클라이언트의 책임이 명확하고 서로 간의 의존성이 줄어들도록 한다.
- stateless (무상태성) : 서버는 들어오는 요청만을 단순히 처리하고, 작업을 위한 상태 정보(클라이언트 정보)는 따로 저장하고 관리하지 않는다. 즉, 불필요한 정보를 관리하지 않음으로써 구현을 단순화한다.
- cacheable : Rest는 HTTP 웹표준을 그대로 사용하기 때문에 웹에서 사용하는 기존 인프라를 그대로 활용가능하다. 따라서 HTTP Cache를 사용할 수 있다.
- API의 경우 사용가능한 HTTP Cache는 2가지 있다. Cache Control + Expire은 max-age를 설정하여 max-age 시간동안은 서버에 요청하지 않는 방법인데, API의 경우 언제 새로운 데아터가 추가될지 모르게 때문에 적합하지 않은 방식이다.
- Cache-Control 일반 헤더 필드는 요청과 응답 내의 캐싱 메커니즘을 위한 디렉티브를 정하기 위해 사용된다. 캐싱 디렉티브는 단방향성이며, 이는 요청 내에 주어진 디렉티브가 응답 내에 주어진 디렉티브와 동일하다는 것을 뜻하지는 않는다는 것을 의미한다.
- 여기서 Expire의 max-age는 리소스가 최신 상태라고 판단할 최대 시간이다. 어쨋든 위에서 말한 max-age 시간동안 최신 상태로 판단하기 때문에 서버에 요청하지 않는다.
- Last-Modified : 최초에 API에 응답을 받을 때 해당 데이터베이스의 마지막으로 수정된 시간을 response로 받게 되고 다음에 동일한 요청을 보낼 때 이 정보를 request header에 담아 보낸다. api 핸들러에서는 이 시간을 체크하여 데이터베이스가 이후 수정된 기록이 없다면 cache 되었던 데이터를 다시 보낸다. DB에서 마지막 변경을 시작을 관리하고 있을 때 유리한 방법이다. 비교적 간단한 데이터를 가져올 때 유리하다. (JOIN으로 가져오는 데이터의 경우 각 테이블의 마지막 수정시간을 체크해야 함, 즉 단일 테이블 쿼리시에 좋다는말임)
- Etag는 Last-Modified 방식과 거의 동일하지만 Hash값을 사용한다는 것이 다르다. Last-modified 보다 더 유연하게 적용 가능하여 더 많이 사용된다. response 에 Etag를 추가하여 응답을 보내고 클라이언트는 동일한 요청을 다시 보낼 때 Etag를 request header에 추가하여 보낸다. 보통 Response 데이터(json)의 MD5 Hash를 사용한다.
- Last-Modified 혹은 Etag를 사용하여 Http Cache를 사용할 때 변경되지 않는 경우에는 304 상태코드로 리턴, 변경된 경우에는 response 데이터와 함께 200으로 리턴한다.
- Http Cache를 사용하면 DB의 부하를 줄이고 API의 속도를 올릴 수 있다.
- uniform interface는 URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행한다.
- layered system는 다중 계층 구조로 로드 밸런싱, 암호화 계층을 추가하여 구조상의 유연성을 둘 수 있고, PORXY, 게이트웨이 같은 네트워크 기반의 중간 매체를 사용할 수 있다.
- code-on-demand (optional)은 서버에서 코드를 클라이언트로 보내서 실행할 수 있어야 한다.(자바 스크립트)
- 서버가 네트워크를 통해 클라이언트에 전달한 js등과 같은 프로그램들은 그 자체로 실행이 될 수 있어야 한다. 이것은 사전 구현에 필요한 기능의 수를 줄임으로써 클라이언트를 단순화한다.
- 이 말은 우리가 평소에는 정적인 데이터를 xml 또는 json에 담아서 client로 보내고 client가 이것을 가공한다. 하지만 code on demand라는 것은 client에 보내는 데이터를 바로 실행 가능한 코드를 보내서 이것을 Client에서 실행하는 것을 말한다.
4번을 제외한 규칙들은 HTTP 규약만 지키면 쉽게 지킬 수 있는 규칙들이다. 4번 규칙이 Rest의 핵심을 나타낸다.
- identification of resource :resouce는 uri로 식별되어야 한다.
- manipulation of resource through representations : 자원에 대한 행위(동작)은 HTTP method(GET,POST,PUT,DELETE)로 표현한다.
- self-descriptive messages : 메시지는 스스로를 설명해야 한다. (메시지는 응답 코드, 응답 데이터 뿐만 아니라 응답 경로, 응답의 해석을 위한 명세서를 포함해야 온전하게 메시지가 스스로를 설명한다고 할 수 있다.) API 문서가 REST API 응답 본문에 존재해야 한다는 것이다. 전체를 넣는건 불가능하다. 적어도 API 문서가 어디 있는지 알려줘야 한다. 만약 서버가 변해서 Response Data가 변경되었다고 가정하자. 그럼 클라이언트가 해당 API 문서를 통해서 어떤 데이터가 바뀌었는지 알 수 있게 된다. 즉, 클라이언트가 resource를 가지고 어떤 일을 수행할 때 필요한 모든 데이터가 응답되어야한다. 보통 안에 porfile(docs) 링크를 명시하는식으로 구현한다.
- hypermedia as the engine of application state (HATEOAS) : 애플케이션의 상태는 Hyperlink를 이용해 전이되어야 한다. (어플리케이션 전이을 위해선 하이퍼링크가 response data에 추가 되어 있어야 한다.) 근데 거의 모든 rest api에서 지키지 못한다. 어플리케이션의 상태가 하이퍼링크를 통해 항상 전이되어야 하는데 잘 안된다. 스프링에서는 spring-boot-hateoas 패키지로 좀 편하게 구현 가능하다. 예를 들어 게시물 조회, 게시물을 저장, 댓글 달기 등 행동들이 상태 전이가 가능한 것들이다. 이러한 것들을 응답 본문에 넣어줘야 한다. 이를 Hypermedia(링크)를 통해서 넣는다.
"comment" : "http://localhost:8080/api/article/comment"와 같이 말이다.
하지만 이도 완벽하지 않다.일단 hateoas를 함으로 좋은점은
1. API 버전을 명세하지 않아도 된다.
2. 링크 정보를 동적으로 바꿀 수 있다.
3. 링크를 통해서 상태 전이가 쉽게 가능하다.
위와 같은 방식으로 데이터를 담아 클라이언트에게 보낸다면 클라이언트는 해당 링크를 참조하는 방식으로, JPA에서 객체 그래프 탐색을 하는 것 처럼 API그래프 탐색이 가능해진다. 그러면 링크에 대한 정보가 바뀌더라도 클라이언트에선 일일이 대응하지 않아도 된다. 이를 HAL JSON을 이용한다.
HAL은 Hypertext Application Language로 JSON, XML 코드 내의 외부 리소스에 대한 링크를 추가하기 위한 특별한 데이터 타입이다.
HAL은 두 개의 타입을 갖는다.
1. application/hal+json
2. application/hal+xml
HAL타입에서는 두 가지의 특징만 이용하면 된다. 바로 리소스와 링크이다. 리소스는 일반적인 data필드에 해당한다. 링크는 하이퍼미디어로 보통 _self필드가 링크 필드가 된다. 아래는 예시이다.
data {
id : 123
name : 네임
content : HAL JSON 예시입니다
}
_links : { 링크 필드
self {
href : http//현재주소
}
profile {
href : http// 해당 api의 문서
}
next {
href : http// 다음 api
}
prev {
href : http// 이전 api 주소
}
}
독립적 진화를 하기 위함이다.
- 서버와 클라이언트가 독립적으로 진화한다. 즉 서버의 기능이 변경되어도 클라이언트를 업데이트할 필요가 없다는 것이다. 이는 Rest를 만들게 된 계기이기도 하다. 위에서 말했듯 이는 Uniform Interface에 hateoas를 통해 실현 가능하다.
- 웹은 Rest 하다. 독릭접 진화를 가장 잘 따르고 있다는 말이다. 웹페이지를 변경했다고 웹 브라우저를 업데이트 할 필요는 없다.
- 웹 브라우저를 업데이트했다고 웹 페이지를 변경할 필요도 없다.
- HTTP 명세가 바뀌어도 웹은 잘 동작한다.
- HTML 명세가 변경되어도 웹은 잘 동작한다.
- 독립전 진화에 self descriptive가 필요한 이유는 서버나 클라이언트가 변경되어도 메시지는 언제나 해석이 가능하다.
- 독립적 진화에 HATEOAS가 필요한 이유는 어디서 어디로 전이가 가능한지 미리 결정되지 않는다. 어떤 상태로 전이가 완료되고 나서야 그 다음 전이될 수 있는 상태가 결정된다. 즉 동적으로 변경될 수 있다.
REST의 장점
- HTTP 프로토콜의 인프라를 그대로 사용하므로 별도의 인프라를 구축할 필요가 없다.
- HTTP 표준 프로토콜에 따르는 모든 플랫폼에서 사용 가능하다.
- Rest API 메시지가 의도하는 바를 명확하게 파악할 수 있다.
- 서버와 클라이언트 역할을 명확하게 분리한다.
REST의 단점
- HTTP Meethod의 형태가 제한적이다. (GET,POST,PUT,UPDATE)
- Rest는 표준이 아니기 때문에 정의가 필요하다.
- Overfetching과 Underfetching이 발생하는 단점이 있다.
- 데이터를 얻기 위해 다양한 endpoint가 필요하다.
overfetching이란 데이터를 요청하게 되면 해당 구조의 모든 데이터를 리턴 받게 된다. 즉, API 호출 시 필요보다 많은 데이터(사용하지 않을)를 가져오는 것이다.
underfetching이란 내가 원하는 정보들이 여러 계층에 걸쳐서 얽혀있는 경우, 그 데이터를 얻기 위해 여러번의 요청을 하는 것이다. 즉 , 하나의 endpoint로의 요청으로는 충분한 데이터를 받지 못하는 것을 말하고 그로 인해 두 개 혹은 그 이상의 endpoint에 요청을 해야한다.
Rest API
Rest API란 Rest 기반으로 서비스 API를 구현한 것이다. Open API 대부분 REST API를 제공한다. Rest 기반으로 시스템을 분산해 확장성과 재사용성을 높여 유지보수 및 운용을 편리하게 할 수 있다. Rest 원리를 따르는 시스템을 Restful하다고 한다. 이하기 쉽고 사용하기 쉬운 REST API를 만드는 것을 목표로 한다. 예를들어 CRUD 기능을 모두 POST로만 처리한다던가 URI에 동사가 들어간다면 Restful 하다고 할 수 없다.
SOAP API
- Simple Object Access Protocol의 약자이다.
- SOAP는 예전에 많이 쓰던 방식이다.
- SOAP는 프로토콜로 보안과 메시지 전송에 있어 REST 보다 더 많은 표준이 정해져 있다.
- 이러한 표준들로 인해 오버헤드가 크다.
- 보안, 트랜잭션, ACID(일관성, 원자성, 고립성, 지속성)을 준수해야 하는 종합적인 환경에 적합한 방식이다. -> 데이터의 무결성을 지킬 수 있다.
- XML로 표현된다. -> envelope, header, body로 구성되어있어 무겁다.
- UDDI라는 전역 서비스 저장소를 통해 서버는 정의된 데이터(XML)를 등록하고, 서비스 요청자는 UUDI에서 필요한 서비스를 요청하여 결과를 받는다.
SOAP나 REST나 둘다 보통 웹 서비스라고 부른다. 이러한 서비스는 기존의 서로 다른 컴퓨터에서 네트워크를 통해 데이터를 주고 받는 통신이라고 생각하면 된다. 얘도 플랫폼에 독립적이고, 연결을 유지하지 않는 특징이 있다.
장점
- 기존의 프록시와 방화벽에 구애받지 않음
- 플랫폼이나 프로그래밍 언어에 독립적이다.
- 에러 처리가 기본적으로 내장
- 분산환경에 사용 적합
- 웹 서비스 표준(XSDL, UDDI, WS-*)이 잘 정립되어있음
단점
복잡한 구조기 때문에 어렵고 REST에 비해 상대적으로 무겁고 느리다.
SOAP vs REST
차이점 | SOAP | REST |
---|
유형 | 프로토콜 | 아키텍쳐 스타일 |
기능 | 기능 위주 : 구조화된 정보 전송 | 데이터 위주 : 데이터를 위해 리소스에 접근 |
데이터 포맷 | XML만 사용 | 일반 텍스트, HTML, XML, JSON 등 다양한 포맷을 허용 |
보안 | WS-Security와 SSL을 지원 | SSL과 HTTPS를 지원 |
대역폭 | 상대적으로 더 많은 리소스와 대역폭이 필요 | 상대적으로 리소스가 적게 필요하고, 무게가 가벼움 |
데이터 캐시 | 캐시를 사용할 수 없음 | 캐시를 사용할 수 있음 |
페이로드 처리 | 엄격한 통신 규약을 갖고 있으며, 모든 메시지는 보내기 전에 알려져야 한다. | 미리 알릴 필요 없다. |
ACID 준수 | 자체적인 ACID 기준이 있어서 데이터 손상을 줄여준다. | ACID 준수와 관련된 내용이 없다. |
- SOAP과 REST의 가장 큰 차이는 인터넷을 통해 전송되는 데이터(페이로드)를 처리하는 방식이 있다.
- REST는 JSON과 HTTP를 사용하기 때문에 페이로드를 가볍게 할 수 있다.
- SOAP는 XML에만 의존하기 때문에 페이로드가 무겁다.
- REST는 서버와 느슨한 형태로 연결되어 구현과 업데이트가 쉬운 편이다.
- SOAP은 서버와 긴밀한 형태로 연결되어 통신 방법이 엄격하고, 수정 업데이트가 어려운 편이다.
- SOAP는 UDDI라는 중간 저장소를 사용하는 반면, REST는 URI를 통해 바로 전송하기 때문에 단순하고 빠르다.
아주 엄격한 보안, 여러 다양한 요구 사항을 만족해야 할 시에 SOAP 방식을 택한다. (기업 어플리케이션)