HTTP ?

HyperText Transfer Protocol의 준말로 링크 기반으로 데이터를 요청하고 받겠다는 것

- 클라이언트와 서버가 요청을 하고 응답을 하기 위해 따르는 프로토콜

- HTML 문서를 주고 받을 수 있음, 뿐만 아니라 이미지, 동영상, 오디오, 텍스트 문서 등을 주고 받을 수 있음

 

HTTP 동작 방식


- 클라이언트 : 웹어플리케이션의 경우 브라우저를 통해서 서버에 요청 ( 프로토콜 + 도메인 + URI )

- 서버 : 클라이언트로부터 받은 요청을 내부적으로 처리하여 그에 대한 결과를 응답

 

HTTP 특징 및 기능

1) connectionless + stateless

- 1번 요청-응답 후 연결을 해제

- 클라이언트의 이전 상태를 알 수 없음쿠키와 세션(클라이언트와 서버의 이전 상태 정보 저장)이 필요함

- 수십만 명이 웹서비스를 사용(요청)하더라도 최소 유지를 할 수 있기 때문에, 많은 유저의 요청을 처리할 수 있음

 

2) keep-alive : HTTP 1.1부터 지원하는 기능

- HTTP 1번의 요청에 대해 1번의 응답 하는 것을 기준으로 설계

- 웹사이트는 하나의 페이지에 수십 개 이미지, css 파일, js 파일들로 구성

- 1 요청 1응답 기준이라면 여러 번 연결을 끊었다 붙였다 해야해서 비효율적

- keep-alive 지원으로 지정된 시간 동안 연결을 끊지않고 연결된 상태를 유지할 수 있음

- keep-alive time out 내 클라이언트가 재 요청하면 새로운 연결이 아닌 기존 연결된 것을 이용함

1) 웹서버 연결

2) HTML 문서 다운로드

3) 필요한 img, css, js 등 다운로드

4) 연결 끊음

- 아래는 네이버 페이지에 대한 요청 헤더임 

             


HTTP method 그리고 REST API

메소드란?

요청의 종류를 서버에 알리기 위해 사용하는 것, 게시판 기능(CRUD, REST API)을 만들 때 사용

 

메소드 종류

1) GET : 정보를 요청하기위해 사용(Read)

2) POST : 정보를 입력하기위해 사용(Create)

3) PUT : 정보를 업데이트하기위해 사용(Update)

4) DELETE : 정보를 삭제하기위해 사용(Delete)

 

REST API?

 -  HTTP 프로토콜 장점을 살릴 수 있는 네트워크 기반 아키텍처

 -  REST API을 구현하기위해 HTTP method + 모든 개체 Resource + URL 디자인(라우팅) 필요

 - 라우팅이란? 클라이언트의 요청에 대한 결과(응답)을 어떻게 이어줄 것인가를 처리하는 것

 - URI를 이용한 접근 : 모든 개체를 리소스로 보고, 리소스에 고유번호를 부여

 - URL 디자인 원칙 : 자원에 대한 처리를 주소에 나타내지않는다(HTTP method는 내부적으로 처리하도록), 어떤 자원인지 주소에 명확하게 나타냄

 - REST API를 구현하기위해 HTTP 프로토콜에 대한 이해, method 종류, 라우팅에 대한 이해가 있어야함

 - HTTP method를 클라이언트가 필요한 처리에 맞게 선택하여 서버에 요청

l  API의 본질은 무엇인가 -> Decoupling, 탈 동조화

l  그렇다면 Web API의 본질은 무엇인가 -> Decoupling + Platform Agnostic

 Platform Agnostic 이란

   플랫폼에 종속적이 않음을 뜻한다. , 특정 기기나 OS에서만 돌아가는 것이 아닌 광범위하게 사용될 수 있는 것.

ex) 데이터 파일(텍스트파일, 그래픽 파일, 음원파일)은 윈도우든 OS X 든 안드로인드든 어디에서도 잘 돌아가니까.

 

REST하다는 것은?

REST(REpresentational State Transfer), "웹에 존재하는 모든 자원(이미지, 동영상, DB 자원)에 고유한 URI를 부여해 활용"하는 것으로, 자원을 정의하고 자원에 대한 주소를 지정하는 방법론을 의미한다고 한다. 따라서 RESTful API REST 특징을 지키면서 API를 제공하는 것을 의미한다.

Roy Fielding에 의해 처음 쓰인 용어(필딩 논문)로써 일반적인 웹(혹은 유사한)을 만들기 위한 제약 조건들을 나열하여 제안한 일종의 디자인 가이드이다.  

" 현재 아키텍처가 웹의 본래 설계의 우수성을 많이 사용하지 못하고 있다고 판단했기 때문에웹의 장점을 최대한 활용할 수 있는 네트워크 기반의 아키텍처를 소개한 것이 Representational state transfer(REST) 이다."

HTTP 1.0이후 웹의 성공으로 인해 HTTP 프로토콜의 의도에 맞지 않은 사용으로 인한  확장성이나 유지보수성이 좋지 않은 웹이 늘어나면서 다시 한번 주목을 받게 되었다아래 설명할 6가지 조건을 “REST”라고 하며 이를 잘 지키는 서비스 디자인을 보고 RESTful하다고 한다.

l  Uniform Interface

l  Client-Server

l  Stateless

l  Cacheable

l  Layered System

l  Code on Demand(optional)


REST
구성

REST 요소를 파악하는 데는 Richardson Maturity Model(RMM)준으로 이해하는 것이 좋은 것 같다.




 

LEVEL 0


웹의 기본 메커니즘을 전혀 사용하지 않는 단계로, HTTP를 통해 데이터를 주고받지만 모든 데이터 요청 및 응답과 관련한 정보를 HTTP body 정보를 활용한다. POX(Plain Old XML)로 요청과 응답을 주고받는 RPC 스타일 시스템이다. 이 때 HTTP method POST만 사용하며, 특정 서비스를 위해 클라이언트에서 접근할 endpoint는 하나이다.

, 하나의 URI을 가지고, 하나의 HTTP method(mainly POST)를 사용한다. 내용에 대한 구분은 XML Payload로 사용해서 요청을 구분하는 방식을 취한다.  모든걸 하나의 리소스를 가지고 처리한다.

LEVEL 1 – RESOURCE


RMM에서 REST를 위한 첫 단계는 리소스를 도입하는 것이다. 그래서 이제는 모든 요청을 단일 서비스 endpoint로 보내는 것이 아니라, 개별 리소스와 통신한다.

POST /doctors/mjones HTTP/1.1
[various other headers]
<openSlotRequest date = "2010-01-04"/>

, 함수를 호출하고 인자들을 넘기는 것이 아니라 다른 정보를 위해 인자들을 제공하는 특정 리소스로 요청을 보낸다. 이럴 경우의 이점은 자원이 외부에 보여지는 방식과 내부에 저장되는 방식을 분리 할 수 있다는 것이다.

예를 들면 클라이언트 단에서 완전히 다른 포맷으로 저장하더라도 JSON 형태의 데이터를 요청할 수 있다. 다양한 URI를 사용하지만 HTTP method는 하나만 사용한다. 그나마 URI를 통해 요청이나 파라미터를 명시한다.

 

LEVEL 2 - HTTP Method


LEVEL 1 URL + HTTP Method 조합으로 리소스를 구분하는 것으로 응답 상태를 HTTP Status code 를 활용한다. 현재 가장 많은 Restful API가 이 단계를 제공한다.

GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1
Host: royalhope.nhs.uk

 

발생한 에러의 종류를 커뮤니케이션하기 위해 상태 코드(status code)를 사용하는 것, 그리고 안전한 오퍼레이션(GET )과 안전하지 않은 오퍼레이션 간의 강한 분리를 제공하는 것이 레벨 2의 핵심 요소이다.

우선, Status Code를 사용한다는 것은 어떤 의미일까?

기존에는 유저 생성 요청을 했을 경우 302 등의 Redirect Request을 서버에서 내려주는 방식이었다면, 지금은 201(created)로 유저 생성 성공을 알릴 뿐 페이지 이동은 Client 단에서 해결하는 방식이다. (login의 경우 성공은 200, 실패 시 인증 실패는 401, 성공했으나 권한 문제시엔 403 ) , 서버는 순수하게 api로서의 기능만을 제공하게 된다. View Client에서 알아서 표시한다.

두번째로, 강한 분리를 제공하는 것이 어떤 이점이 있는 것일까?

HTTP에서 GET은 멱등방식(Idempotent )으로 자원을 추출하는데, 이 말은 호출 순서나 횟수에 영향 받지 않고 매번 같은 결과를 받을 수 있게 한다. 그렇기 때문에 모든 request'캐싱'기능을 지원하는 다양한 방법을 제공한다.

  Idempotent(멱등)의 개념을 설명한 이유는 REST는 각 개별 API를 상태 없이 수행하게 된다따라서 해당 REST API를 다른 API와 함께 호출하다가 실패하였을 경우, 트랜잭션 복구를 위해서 다시 실행해야 하는 경우가 있는데,  Idempotent 하지 않은 메서드들의 경우는 기존 상태를 저장 했다가 다시 복원해 줘야하는 문제가 있지만, Idempotent한 메서드의 경우에는 반복적으로 다시 메서드를 수행해주면 됩니다.

   예를 들어 게시물 조회를 하는 API가 있을 때, 조회 시 마다 조회수를 올리는 연산을 수행한다면 이 메서드는 Idempotent 하다고 볼 수 없고조회하다가 실패 하였을 때는 올라간 조회수를 다시 -1 만큼 빼줘야 합니다 Idempotent 하지 않은 메서드에 대해서는 트랜잭션에 대한 처리에 특히 주의가 필요하다.

 

LEVEL 3 - HYPERMEDIA CONTROL


HATEOAS(Hypertext As The Engine Of Application State)

하이퍼미디어란 하나의 컨텐츠가 텍스트나 이미지, 사운드와 같은 다양한 포맷의 컨텐츠를 링크하는 개념이다. 이것은 관련 컨텐츠를 보기 위해 링크를 따라가는 방식과 유사한 방식으로 동작하는데, 클라이언트가 다른 자원에 대한 링크를 통해 서버와 (잠재적으로 상태 변이를 초래하는) 상호작용을 한다.

, 특정 API를 요청한 후 다음 단계로 할 수 있는 작업을 알려주는 것이며, 다음 단계의 작업을 위한 리소스의 URI를 알려주는 것이다. 이 단계를 적용하면 클라이언트에 영향을 미치지 않으면서 서버를 변경하는 것이 가능하다.

 

GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1

Host: royalhope.nhs.uk

HTTP/1.1 200 OK
[various headers]
<openSlotList>

 <slot id = "1234" doctor = "mjones" start = "1400" end = "1450">
            <link rel = "/linkrels/slot/book"
            uri = "/slots/1234"/>
 </slot>
 <slot id = "5678" doctor = "mjones" start = "1600" end = "1650">
            <link rel = "/linkrels/slot/book"
            uri = "/slots/5678"/>
 </slot>
</openSlotList>

단점은, 클라이언트가 수행할 작업을 찾기 위해 링크를 따라가기 때문에 컨트롤 탐색에 꽤 많은 호출이 발생할 수 있다는 것이다. 또한 복잡성이 증가할 수 있으며, HTTP 요청 상에 나타나는 부하로 낮은 지연시간이 요구될 때 문제가 될 수 있다. HTTP 기반의 REST Payload JSON 또는 바이너리 등의 포맷을 지원하므로 실제로 SOAP 보다 훨씬 간결할 수 있지만 Thrift와 같은 바이너리 프로토콜에는 상대가 되지 못한다.

또한 WebSocket의 경우 HTTP 초기 handshake 후에 클라이언트와 서버 간에 TCP 접속이 이루어지고 브라우저에서 스트림 데이터를 보낼 때 효율적일 수 있다. 따라서 HTTP가 대규모 트래픽에는 적합할 수 있지만 TCP 또는 다른 네트워킹 기술 기반의 프로토콜과 비교하면 낮은 지연시간이 필요한 통신에는 그다지 좋은 선택이 아닐 수 있다.

이러한 단점에도 HTTP 기반의 REST는 서비스 대 서비스의 상호작용을 위해 합리적이고 기본적인 선택이다.



RMM을 통한 REST 핵심 요소

l  자원(RESOURCE) - URI  , 애플리케이션에서 제공하는 resource를 어떻게 분할하고 통합할 것인가?, ( LEVEL 1의 고민 )

l  행위(METHOD) - HTTP METHOD, STATUS CODE , 에러 상황에 대한 적절한 처리와 method 도입을 통한 불필요한 다양성(복잡성) 제거 (LEVEL 2의 고민)

l  표현(Representations) -  hypermedia, API가 스스로 문서화 가능하도록 지원할 것인가? ( LEVEL 3의 고민 )

 

REST의 특성

1.   Uniform Interface

REST HTTP 표준만 따른다면, 어떠한 기술이든 사용이 가능한 인터페이스 스타일이다

예를 들어 HTTP + JSON으로 REST API를 정의했다면, 안드로이드 플랫폼이건, IOS 플랫폼이건,  또는 C Java / Python 이건 특정 언어나  기술에 종속 받지 않고 HTTP JSON을 사용할 수 있는 모든 플랫폼에 사용이 가능한 느슨한 결합(Loosely Coupling) 형태의 구조이다.

 

※ 흔히들 근래에 REST를 이야기하면, HTTP + JSON을 쉽게 떠올리는데, JSON은 하나의 옵션일 뿐, 메시지 포맷을  JSON으로 적용할 필요는 없다. 자바스크립트가 유행하기전에만 해도 XML 형태를 많이 사용했으며, 근래에 들어서 사용의 편리성 때문에 JSON을 많이 사용하고 있지만, XML을 사용할 경우, XPath, XSL 등 다양한 XML 프레임워크을 사용할 수 있을 뿐만 아니라 메시지 구조를 명시적으로 정의할 수 있는 XML Scheme DTD등을 사용할 수 있기 때문에복잡도는 올라가더라도, 메시지 정의의 명확성을 더할 수 있다.   

리소스 식별

 각각의 리소스는 URI를 구분자로 식별이 가능해야 한다. 예를 들어http://www.google.com은 구글의 메인 페이지를 나타낸다. TO-DO list 웹사이트를 예로 들자면 아래와 같을 것이다.

 

http://www.example.com/v2/tasks # 일들의 collection

http://www.example.com/v2/tasks/2 # id 값이 2

http://www.example.com/v2/tasks/14 # id 값이 14

 

표현을 통한 리소스 처리

리소스 자체를 전송하는 것이 아닌 리소스의 표현을 전송한다

예를 들어, GET http://www.example.com/v2/apple 는 사과 그 자체(리소스)가 아닌 사과를 묘사한 표현를 전송한다. 리소스 자체가 아닌 표현을 사용함으로써 서버의 코드에 얽매이지 않고 client를 구현할 수 있고, 서버의 수정에 거의 영향을 받지 않는다.(최소한 영향을 줄일 수 있다.)  

예를 들어 Database에 있는 리소스를 요청할 경우에 Database에 있는 그대로 응답을 할 경우에는 추후 database scheme가 변경될 경우에 클라이언트가 영향을 받을 수 있어 수정에 제약이 걸릴 수도 있다.

 

자기 서술형 메시지 ( Self-descriptiveness )

REST는 메시지가 자신을 어떻게 처리해야 할 지에 대한 정보를 포함하고 있어야 한다. 즉 수신자가 이해하기 위한 모든 정보를 가지고 있어야 한다. , API 메시지 자체만 보고도 API를 이해할 수 있는 Self-descriptiveness 구조를 갖는 다는 것이다

아래 내용을 로이 필딩의 논문에서 제시된 몇가지 예시다:

-       state-less 시스템에서 서버는 클라이언트의 요청을 처리했던 이력을 저장하지 않는다. 그렇기 때문에 각각의 요청에 해당 정보가 포함되어야 한다.

-       표준 method(GET, POST, DELETE, PUT)와 미디어 유형을 사용하여 별도의 설명 없이 명확하게 파악할 수 있도록 한다

-       PUT method를 사용할 경우 수정한다는 의미를 파악할 수 있고 Content-Type json이 명시되어 있을 경우 client response 메시지를 읽기 위한 방법을 알 수 있다.

-       Response에 캐시 가능성을 지정한다. Client가 아닌 server가 해당 내용을 header에 명시해야 한다.

 

하이퍼미디어 제약

어플리케이션의 상태는 하이퍼미디어에 의해 변경된다는 의미이다.

<!-- GET task들의 list를 가져오고 -->

<a href="http://example.com/v2/tasks"/>

<!-- POST task를 추가한다 -->

<form action="http://example.com/v2/tasks"/>

 

위에서처럼 클라이언트의 하이퍼미디어에 의해 어플리케이션에 task가 추가되고 제거(상태 변화) 된다는 제약이다.

2.  Client-Server

서비스가 수행되길 기대하는 클라이언트 구성 요소는 연결자를 통해 서버에 요청을 보내며, 서버는 해당 요청을 거절하거나 수행하고 클라이언트에 응답을 보낸다. 그리고 모든 통신은 클라이언트-서버 간의 일대일로 연결된다.  

REST 서버는 API를 제공하고, 제공된 API를 이용해서 비즈니스 로직 처리 및 저장을 책임진다클라이언트의 경우 사용자 인증이나 Context(세션, 로그인 정보)등을 직접 관리하고 책임 지는 구조로 역할이 나뉘어 지고 있다

 

 - 클라이언트는 서버의 자세한 사항에 대해서 신경 쓸 필요 없이(e.g., 데이터베이스) 제공되는 인터페이스를 통해 접근하여 응답을 받는다. 대신 자신의 Context를 관리한다.

- 서버는 클라이언트의 상태를 신경 쓰지 않고 제공한 인터페이스에 대한 처리만 담당하여 요청이 들어올 때 그에 맞는 응답을 제공한다.

 

이렇게 역할이 각각 확실하게 구분되면서, 개발 관점에서 클라이언트와 서버에서 개발해야 할 내용들이 명확하게 되고 서로의 개발에 있어서 의존성이 줄어들게 된다.

 

 

3.  Stateless

State가 있다/없다의 의미는 사용자나 클라이언트의 Context를 서버 쪽에 유지 하지 않는다는 의미로쉽게 표현하면 HTTP Session과 같은 Context 저장소에 상태 정보를 저장하지 않는 형태를 의미한다

상태 정보를 저장하지 않으면 각 API 서버는 들어오는 요청의 메시지로만 처리하면 되며세션과 같은 Context 정보를 신경 쓸 필요가 없기 때문에 구현이 단순해 진다.

다시 말하면, 각각의 요청 시에 클라이언트의 Context가 서버에 저장되지 않는다. 그렇기 때문에 위에서 언급한 자기 서술형 메시지가 지켜져야 한다. 이 조건을 지킨 서버는 요청에 대한 처리만 하면 되기 때문에 구현이 단순해 진다. 또한 URI에 해당 내용을 포함시키지 않음으로써 Caching 사용 범위가 넓어질 수 있다.

상태에 대한 정보는 클라이언트가 가지고 있고 서버는 전혀 신경쓰지 않는다. 만약 어떠한 상태가 너무 중요한 나머지 서버에 두어야 할 경우에는 Resource에 추가하는 것을 고려한다.

 

4.  Cacheable

자기 서술형 메시지 덕분에 각각의 요청에 대한 응답은 그 자체로 해석이 가능하다. 그렇기 때문에 독립적으로 처리가 가능한데, 이로 인해 Caching이 가능해진다. 다른 상황에 영향을 받았다면 Caching을 했을 경우 잘못된 결과가 나올 수 있다. 네트워크를 사용하는 비용이 가장 오래 걸리므로 이를 줄이는 것이 어플리케이션 성능을 향상시키는 좋은 방법이 될 수 있다.

 

# 첫번재 요청

GET /v2/tasks/2

# Reponse

200 OK

Last-Modified: Sun, 03 Apr 2016 16:09:23 GMT

# 두번째 요청

GET /v2/tasks/2

If-Modified-Since: Sun, 03 Apr 2016 16:09:23 GMT

# Reponse

304 Not Modified

# 기존의 데이터를 그대로 사용한다(이건 구현에 따라서 달라질 수 있다)

 

 

REST의 큰 특징 중의 하나는 HTTP라는 기존의 웹 표준을 그대로 사용하기 때문에웹에서 사용하는 기존의 인프라를 그대로 활용이 가능하다

HTTP 프로토콜 기반의 로드밸러서나 SSL은 물론이고, HTTP가 가진 가장 강력한 특징 중에 하나인 캐싱 기능을 적용할 수 있다.

일반적인 서비스 시스템에서 60%에서 많게는 80% 가량의 트랜잭션이 Select와 같은 조회성 트랜잭션인 것을 감안하면, HTTP의 리소스들을 웹 캐시 서버 등에 캐싱하는 것은 용량이나 성능 면에서 많은 장점을 가지고 올 수 있다.

구현은 HTTP 프로토콜 표준에서 사용하는 "Last-Modified" 태그나 E-Tag를 이용하면 캐싱을 구현할 수 있다.

아래와 같이 Client HTTP GET "Last-Modified" 값과 함께 보냈을 때, 컨텐츠가 변화가 없으면 REST 컴포넌트는 "304 Not Modified"를 리턴 하면 Client는 자체 캐쉬에 저장된 값을 사용하게 된다.

 



이렇게 캐시를 사용하게 되면 네트워크 응답시간 뿐만 아니라, REST 컴포넌트가 위치한 서버에 트랜잭션을 발생시키지 않기 때문에, 전체 응답시간과 성능 그리고 서버의 자원 사용률을 비약적으로 향상시킬 수 있다.

 

- E-Tag : 메시지에 담겨있는 Entity를 위한 Entity 태그를 제공한다. 이를 활용하여 리소스를 식별할 수 있다.

- Last-Modified : Entity가 마지막으로 변경된 시각에 대한 정보를 제공한다. (파일인 경우 파일 시스템이 제공해 준 최근 변경 시각, 동적으로 생성된 리소스라면 응답이 만들어진 시간)

 

5.  Layered System

서버는 클라이언트가 모르게 API 서버에 여러 계층을 추가하여 유연한 구조로 개발될 수 있다클라이언트 입장에서는 REST API 서버만 호출한다그러나 서버는 다중 계층으로 구성될 수 있다.

순수 비즈니스 로직을 수행하는 API 서버와 그 앞 단에 사용자 인증(Authentication), 암호화(SSL), 로드밸런싱 등을 하는 계층을 추가해서 구조상의 유연성을 둘 수 있는데이는 근래에 들어서 앞에서 언급한 마이크로 서비스 아키텍쳐의 API Gateway나 간단한 기능의 경우에는 HA Proxy Apache와 같은 Reverse Proxy를 이용해서 구현하는 경우가 많다.

6.  Code on Demand(optional)

클라이언트는 리소스에 대한 표현을 응답으로 받고 처리해야 하는데, 어떻게 처리해야 하는지에 대한 Code를 서버가 제공하는 것을 의미한다. Html에서의 javascript가 가장 대표적인 예이다하지만 서버에서 제공되는 코드를 실행해야 하기 때문에 보안 문제를 야기할 수 있다.

참조

https://joonyon.tistory.com/13

https://brainbackdoor.tistory.com/53

https://meetup.toast.com/posts/92

http://bcho.tistory.com/m/321

http://amazingguni.github.io/blog/2016/03/REST%EC%97%90-%EB%8C%80%ED%95%9C-%EC%9D%B4%ED%95%B4-1

http://jinbroing.tistory.com/96

https://blog.npcode.com/2017/04/03/rest%EC%9D%98-representation%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80/

 



+ Recent posts