Client의 요청(Request)이 있을 때만 Server가 응답(Response)하는 단방향 통신으로, 응답을 받고나면 연결이 종료된다.
ex) 버튼 클릭 시 선택된 컨텐츠 보여주기
connection당 하나의 요청을 처리하도록 설계되어있다.
그래서 위 그림과 같이 동시전송이 불가능하고 요청과 응답이 순차적으로 이루어진다.
--그렇다 보니 HTTP 문서안에 포함된 다수의 리소스를 처리하려면 요청할 리소스 개수에 비례해서 Latency(대기시간)는 길어지게 된다.
HTTP의 HOL(Head Of Line) Blocking: 특정 응답의 지연
pipelining
하나의 Connection을 통해서 다수개의 파일을 요청/응답 받을 수 있는 기법
-- 문제점
하나의 TCP연결에서 3개의 이미지(a.png, b.png, c.png)를 얻을려고 하는경우 HTTP의 요청순서는 다음 그림과 같다.
| --- a.png --- |
| --- b.png --- |
| --- c.png --- |
순서대로 첫번째 이미지를 요청하고 응답받고 다음 이미지를 요청하게 되는데 만약 첫번째 이미지를 요청하고 응답이 지연되면 아래 그림과 같이 두,세번째 이미지는 당연히 첫번째 이미지의 응답처리가 완료되기 전까지 대기하게 되며 이와 같은 현상을 HTTP의 Head of Line Blocking 이라 부르며 파이프 라이닝의 큰 문제점 중 하나
| ------------------------------- a.png --------------- --- |
| -b.png- |
| --c.png-- |
RTT(Round Trip Time) 증가
매 요청별로 connection을 만들게 되고 TCP상에서 동작하는 HTTP의 특성상 3-way Handshake 가 반복적으로 일어나고 또한 불필요한 RTT증가와 네트워크 지연을 초래하여 성능을 저하
무거운 Header 구조 (특히 Cookie)
매 요청시 마다 중복된 헤더값을 전송
HTTP 2.0이라고도 불리는 HTTP/2는 Hypertext Transfer Protocol Version 2의 약자로서, 2015년 IETF에 의해 공식적으로 발표된 HTTP/1.1(기존 표준)의 차기 버전이다.
IETF: Internet Engineering Task Force, 국제 인터넷 표준화 기구를 의미하며, 인터넷의 운영, 관리, 개발에 대해 협의하고 프로토콜과 구조적인 사안들을 분석하는 인터넷 표준화 작업기구
Frame & Stream & Messages
기존에 Plain Text(평문)를 사용하고, 개행으로 구별되면 HTTP/1.x 프로토콜과 달리, 2.0에서는 바이너리 포멧으로 인코딩 된 Message, Frame으로 구성된다.
Multiplexed Streams
한 커넥션으로 동시에 여러개의 메세지를 주고 받을 있으며, 응답은 순서에 상관없이 stream으로 주고 받는다.
Stream Prioritization
Image파일보다 CSS파일의 수신이 늦어지는 경우 브라우저의 렌더링이 늦어지는 문제가 발생하는데
HTTP/2에서는 리소스간 의존관계(우선순위)를 설정하여 이런 문제를 해결
Server Push
서버는 클라이언트의 요청에 대해 요청하지도 않은 리소스를 마음대로 보내줄 수 도 있다.
클라이언트가 HTML문서를 요청했고, 해당 HTML에 여러개의 리소스(css, image)가 포함되어있는 경우
HTTP/1.1에서는 클라이언트는 요청한 HTML문서를 수신후 HTML문서를 해석하면서 필요한 리소스를 재요청한다.
HTTP/2는 Server Push 기법을 통해서 클라이언트가 요청하지도 않은 리소스를 Push해주는 방법으로 클라이언트이 요청을 최소화하여 성능향상
Header Compression
HTTP/2는 Header 정보를 압축하기 위해 Header Table과 Huffman Encoding 기법을 사용하여 처리하는데 이를 HPACK 압축방식이라 부르며 별도의 명세서(RFC 7531)로 관리하고 있다.
데이터와 기능의 집합을 제공하여 컴퓨터 프로그램간 상호작용을 촉진하며, 서로 정보를 교환가능 하도록 하는 것
REST 기반으로 서비스 API를 구현한 것
REST 디자인 원칙
a. 클라이언트 / 서버 구조
클라이언트는 유저와 관련된 처리를, 서버는 REST API를 제공함으로써 각각의 역활이 확실하게 구분되고 일괄적인 인터페이스로 분리되어 작동할 수 있게 한다
REST Server: API를 제공하고 비지니스 로직 처리 및 저장을 책임진다.
Client: 사용자 인증이나 context (세션, 로그인 정보) 등을 직접 관리하고 책임진다.
서로 간 의존성이 줄어든다.
b. 무상태성 (Stateless)
REST는 HTTP의 특성을 이용하기 떄문에 무상태성을 갖는다.
즉 서버에서 어떤 작업을 하기 위해 상태정보를 기억할 필요가 없고 들어온 요청에 대해 처리만 해주면 되기 때문에 구현이 쉽고 단순해진다.
c. 캐시 처리 가능 (Cacheable)
HTTP라는 기존 웹표준을 사용하는 REST의 특징 덕분에 기본 웹에서 사용하는 인프라를 그대로 사용 가능하다.
대량의 요청을 효율적으로 처리하기 위해 캐시가 요구된다.
캐시 사용을 통해 응답시간이 빨라지고 REST Server 트랜잭션이 발생하지 않기 때문에 전체 응답시간, 성능, 서버의 자원 이용률을 향상 시킬 수 있다.
d. 자체 표현 구조 (Self - descriptiveness)
JSON을 이용한 메시지 포멧을 이용하여 직관적으로 이해할 수 있고 REST API 메시지만으로 그 요청이 어떤 행위를 하는지 알 수 있다.
e. 계층화 (Layered System)
클라이언트와 서버가 분리되어 있기 때문에 중간에 프록시 서버, 암호화 계층 등 중간매체를 사용할 수 있어 자유도가 높다
f. 유니폼 인터페이스 (Uniform)
Uniform Interface는 Http 표준에만 따른다면 모든 플랫폼에서 사용이 가능하며, URI로 지정한 리소스에 대한 조작을 가능하게 하는 아키텍쳐 스타일을 말한다
URI로 지정한 Resource에 대한 조작을 통일되고 한정적인 인터페이스로 수행한다.
즉, 특정 언어나 기술에 종속되지 않는다.
libcurl 라이브러리 내부 환경 초기화
#include <curl/curl.h>
CURLcode curl_global_init(long flags);
return: CURLcode 타입의 오류 값
flags: flags("CURLGLOBAL"으로 시작)
curl_global_init으로 생성된 자원 해제
curl 내부에서 할당한 메모리를 해제
CURL handle 생성
#include <curl/curl.h>
CURL *curl_easy_init();
return: CURL handle
handle은 curl_easy_init 또는 curl_easy_duphandle 호출 의 반환 코드
CURL 핸들 닫기
마지막에 호출되어야함
void curl_easy_cleanup(CURL *handle);
1번째 인자: CURL handle
CURLcode 타입의 오류 값
어떻게 행동할지 알려주는 데 사용
CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
1번째 인자: CURL handle
2번째 인자: 설정한 옵션의 종류 ("CURLOPT_"으로 시작)
n번째 인자: 2번째 인자의 옵션에 대한 값
return: 성공시 CURLE_OK, 실패시 오류코드
ex) 없는 옵션: CURLE_UNKNOWN_OPTION
옵션 지원이 컴파일 타임에 비활성화된 경우: CURLE_NOT_BUILT_IN
전달된 문자열(8000000바이트보다 짧아야) 초과: CURLE_BAD_FUNCTION_ARGUMENT
세팅된 옵션에 맞춰 작업(전송) 수행
CURLcode curl_easy_perform(CURL *easy_handle);
return: 성공시 CURL_OK, 실패시 오류코드
1번째 인자: CURL handle
CURL handle로부터 정보를 가져옴
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... );
return: 성공시 CURLEOK, 실패시 오류코드
1번째 인자: CURL handle
2번째 인자: 가져올 정보의 종류("CURLINFO"으로 시작)
n번째 인자: 2번째 인자의 정보에 대한 포인터(반드시 포인터여야 함)
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/");
res = curl_easy_perform(curl);
if(CURLE_OK == res) {
char *ct;
/* ask for the content-type */
res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
if((CURLE_OK == res) && ct)
printf("We received Content-Type: %s\n", ct);
}
/* always cleanup */
curl_easy_cleanup(curl);
}
주어진 입력 문자열 을 URL 인코딩된 문자열로 변환하고 새 할당 문자열로 반환
char *curl_easy_escape(CURL *curl, const char *string, int length);
return: 성공시 인코딩된 문자열에 대한 포인터, 실패시 NULL
1번째 인자: curl handle
2번째 인자: url 문자열
3번째 인자: url 문자열의 길이(0인 경우, strlen으로 알아서 계산)
URL 디코딩(URL 인코딩된 입력 문자열을 "일반 문자열"로 변환)
char *curl_easy_unescape(CURL *curl, const char *url, int inlength, int *outlength);
return: 성공시 디코딩된 문자열에 대한 포인터, 실패시 NULL
1번째 인자: curl handle
2번째 인자: 인코딩된 url
3번째 인자: 2번째 인자의 길이(0인 경우, strlen으로 알아서 계산)
4번째 인자: 디코딩된 문자열의 길이
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_init();
if(curl) {
/* First set the URL that is about to receive our POST. This URL can
just as well be a https:// URL if that is what should receive the
data. */
curl_easy_setopt(curl, CURLOPT_URL, "http://postit.example.com/moo.cgi");
/* Now specify the POST data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=daniel&project=curl");
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
Curl은 데이터 전송과 관련된 프로그램의 빠른 작성을 위해서 사용하는 command line tool이다.
HTTP, FTP, LDAP, TELNET, HTTPS, DICT와 같은 프로토콜을 지원
이러한 툴의 제공과는 별도로 위의 프로토콜들을 지원하는 클라이언트의 제작을 도와주기 위한 libCurl을 제공
libCurl을 사용하면 데이터 전송과 관련된 프로그램을 빠르게 작성할 수 있다.
libCurl은 이러한 프로세스의 중간에서 중계역할을 함
참고
https://www.joinc.co.kr/w/man/12/rest/about
https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html
c에서 json 데이터 읽기
libcurl 설치
http get post
libcurl 사용법
socket을 이용하여 HTTP 프로토콜