센로그
6. HTTP/1.1 본문
◆ HTTP란?
서버-클라이언트 모델을 따라 데이터를 주고 받기 위한 프로토콜이다
클라가 서버에게 HTTP request을 보냄. 그러면 서버가 이에 대한 HTTP response를 클라에게 주는 형태로 동작함.
그림을 보자.
웹 브라우저가 웹 서버에게 "HTTP라는 프로토콜로 root/index.html을 달라"고 요청하면,
서버는 "알겠어, 그거 여기 있고, 총 3150 length야. 가져가." 하고 주는 것임. 굉장히 심플하다.
※ 어떻게 이렇게 심플할 수 있는 걸까?
→ 전제조건: 초기에 HTTP를 짤 때, "무조건 HTTP 밑에는 TCP가 돌아야 한다!" 라는 걸 생각하고 짰기 때문에 가능하다. 즉 어차피 TCP가 에러 검출 및 복구를 할 거기 때문에, HTTP는 그걸 신경쓰고 싶지 않고 간단하게 할 거야! 라는 초기 철학이 있었다.
이렇게 클라는 서버로부터 요청을 해서, 리소스들을 갖고 옴.
리소스는 정적 콘텐츠, 동적 콘텐츠로 나뉨
- 정적 콘텐츠: Req가 오기 전에 이미 콘텐츠가 만들어져있고, req 받은 이후에도 바뀌지 않는 콘텐츠.
기본적으로 오리지널 HTTP는 주어진 자료를 고정적인 형태로 보관하고, 요청하면 줄 뿐이었다.
ex) 워드파일, 이미지, 비디오 등등에 해당함. - 동적 콘텐츠: 요청을 받으면 그 시점에 특정 로직을 돌려서 새롭게 만들어지는 콘텐츠.
이때 요청한 사람의 추가적인 정보를 사용할 수 있다. ‘로직’이 존재하며, 관문 역할을 하는 서버가 있음.
ex) 주주가 현재 본인의 주식 가격을 요청하는 경우
※ 헷갈리지 말 것: Request 오기 전에 다 만들어져있는 경우는 정적 콘텐츠다.
비디오의 경우, 컨텐츠 내부는 동적이지만 파일 자체는 정적이다. Request 받고나서야 배우들이 자 이제 찍어볼까? 하고 콘텐츠를 만들어내지는 않음. 이미 만들어진 걸 차근차근 보내줄 뿐.
◆ URI - URL
URI : 리소스를 식별하는 식별자
URI에는 URL과 URN이 있었는데, URN은 의미가 없어져서 사라짐
URL은 우리가 알다시피 요청한 파일이 어디에 있는지 식별하는 정보.
xxx.com/index.html 이라고 한다면, xxx.com 서버의 루트 디렉토리에 있는 index.html 파일을 의미함.
◆ HTTP 클라-서버간 통신 예시
<클라>
클라가 서버로 HTTP GET request를 보냄.
- GET : 내놔! specials/saw-blade.gif 파일을 내놔.
- 모든 통신 프로토콜은 버전이 중요함. 나는 HTTP이고 버전은 1.0이니까, 이거에 맞춰서 내놔!
- Host : GET을 하는 상대방에 대한 정보를 달라고 함.
→ 엥? 이건 IP 계층이 하는 거 아니야..? IP에 그렇게 세팅이 되어있을텐데 왜 상위 레이어인 HTTP에다 저렇게 써놨을까..?
→ → 우리가 아는 웹 서버와 웹 브라우저는 실제로 그렇게 작동하지 않고, 둘 사이에 서버(프록시 서버) 하나가 떡하니 버티고있다. 회사에서 막어놓은 접속 불가 리스트 같은 게 있음. 그런걸 이 서버에서 처리하곤 함.
<서버>
- HTTP 1.0 원했지? 알겠어. 리턴값은 200 (프로그램 입장의 OK라는 뜻. 니가 원하는 거 찾았고, 니가 말한 프로토콜로 줄 수 있어~ 라는거)
- 콘텐츠 타입은 image, 그것도 gif야
- 콘텐츠 length는 8572야!
◆ HTTP Request Methods 종류
대표적인 HTTP 리퀘스트 메소드로 네 가지가 있다.
- GET: 리소스 파일을 내놔라.
- PUT: 업로드. 서버에 리소스를 저장한다.
- DELETE: 서버에 업로드한 파일을 삭제.
- POST: 서버쪽으로 입력 파라미터(text)를 전달하는 용도. 그로 인해서 서버가 작업을 하기를 원한다.
이들에 대해 뒤에서 자세하게 다룰 것임.
◆ HTTP Status Codes
서버에 요청을 했다고 해서 무조건 다 성공하는 건 아님.
어떤 상태인지 나타내는 몇 가지 코드가 있다.
- 404: 파일 요청헀는데 그 파일이 서버에 없는 것.
- 302: 리다이렉트. 서버를 갈아타는 것.
콘서트 대기창 같은 거. - 200: OK.성공
OK는 사람을 위한 정보, 200은 기계를 위한 리턴값 느낌
◆ Message 구조
HTTP 클라-서버간에 주고받는 메시지의 구조를 살펴보자.
기본적으로, 인간 이해하기 쉽도록 만들어졌다.
Start line
- 클라: 요청, URL, 프로토콜 및 버전
- 서버: 프로토콜 및 버전, 응답
Headers
Accept: 부가적인 옵션. Text의 형태는 모두 다 받을 수 있어~
Accept language: en, fr 언어만 읽을 수 있어~
Body
실제 메시지를 넣음
◆ TCP
HTTP/1.1은 TCP를 쓴다.
초기 HTTP는 req에 대한 resp만 바랐지, 오류 검출 같은 건 하고싶지 않았음
따라서 TCP/IP를 쓴다고 전제하고, 얘네가 알아서 에러 검출을 하도록 함
그러나 시대적 흐름이 변화하고 요구가 변화함에 따라, 최근에 나온 HTTP 3 같은 경우에는 TCP 안 쓰고 UDP 씀.
◆ HTTPS
암호화한 HTTP
HTTPSecurity.
HTTP를 살짝 수정해서 SSL또는 TLS(보안 레이어)를 사용하도록 한 게 HTTPS임.
서버와 클라 사이에 어떤 정보도 까볼 수 없도록 한 것.
대신 클라와 서버의 성능은 저하되며, 최초 연결시에 암호키를 주고받거나 하는 부분이 있는 만큼 최초 연결이 굉장히 느려진다
※ 최초 연결은 중요한데: TCP는 원래부터 최초 연결이 congestion window 1부터 시작하니까 느린데(slow start), 이런 보안 설정까지 하게되면 더 느려지는 것! ㅠㅠ
◆ HTTP 연결 과정
URL을 입력하면, 브라우저가 DNS 서버로 접속해서 IP 주소를 가져온 후, TCP 레이어가 소켓을 열어서 연결함.
그 위에서 HTTP GET이 날라가고, response를 받으며 정보를 전달함.
시간이 오래 지났음에도 뭔가를 안하면 연결이 끊어지는 구조.
◆ HTTP Networking - Proxy
HTTP는 클라와 서버 두 컴퓨터 사이에서만 동작한다? ㄴㄴ
→ 클라와 서버 사이에는 눈에 보이지않는 프록시 서버가 있다.
프록시 서버는 클라와 서버 사이에서 여러가지 기능을 제공한다.
ex)
- 특정 사이트 접속 차단(Web Security) 기능
- 캐싱 기능(한국에서 미국 서버에 컨텐츠를 요청했는데, 프록시 서버가 보고는 '어, 이 컨텐츠 한국 서버에도 있는데?' 하고 한국 서버의 컨텐츠를 주는 것. 응답 속도도 빨라지고 트래픽 양도 줄음)을 한다.
- 네트워크가 느린 국가에서 유튜브를 접속할 때, 무작정 하이 퀄리티를 보내면 오래 걸리고 보기 힘들 것이므로, 퀄리티를 낮추어서 보내는 기능
→ 쉽게 말해 프록시 서버는 (클라와 서버 사이에서) 클라 요청을 받고, 적합하면 요청한 서버로 보내고, 그렇지 않으면 본인이 처리하는 역할을 한다.
◆ 대표적인 HTTP Methods
나열, 각각 기능 설명
GET
리소스 파일 요청
응답: 요청한 리소스를 제공함. 성공하면 응답코드 200 OK. 못 찾으면 404 NOT FOUND
PUT
리소스 파일 업로드
응답: 성공적으로 저장하게 되면 응답코드 201.
DELETE
업로드한 파일 삭제
POST
요청한 데이터 처리. 주로 등록에 사용
웹 브라우저에서 인풋 필드에 우편번호 집어넣고 우편번호 쓴 다음에 조회! 이런거 눌렀을 때 하는 처리.
응답: 성공적으로 처리를 완료하면 응답코드 201.
HEAD
파일의 헤더 정보 요청함.
GET하고 얼추 비슷하다. 응답도 거의 똑같다. 200 OK
그러나, 파일 통째로 줄 필요는 없고, 헤더 정보만 내놔! 라는 것
이런걸 가지고 뭘하느냐?
→ 캐싱
If-modified-Since : 니가 나한테 무조건 파일을 줄 필요는 없어. 만약 파일이 언제 이후로 수정이 되어있다면 줘. 아니면 안줘도 돼.(이미 예전 거 갖고 있어)
TRACE
프록시의 정보를 확인해보고 싶을 때 사용. 주로 디버깅 용도로 이용
얘도 GET과 유사하게 동작한다.
만약 클라-서버 중간에 프록시 서버가 있으면,
프록시 서버를 거칠 때 "나는 proxy3.company.com이야. 지금 나를 경유해서 가고 있어" 라고 프록시 서버가 써준다.
이걸 서버가 받으면 그대로 본문에 적어서 클라에게 돌려준다.
이런 걸 보고 뭐가 문젠지, 뭐가 잘못된 건지, 뭘 조심해야 하는지 확인할 수 있다.
OPTIONS
서버가 어떤 메서드를 지원하는지 알려줌.
서버야 니가 뭘 지원하는지 다 보여줘~라고 하면,
서버가 "나는 GET POST PUT OPTIONS를 지원해!" 라고 알려줌
◆ 네트워크 프로그래밍의 변천사
클라투 서버, 서버투서버, 프로그램투서버로 넘어가는 이야기를 햇엇다.
1ㄷ1로 통신파이프를 열어놓고 바이트 단위로 주고받는 기법 에서 HTTP로 넘어옴.
Monolithic - 어떤 거대한 하나의 시스템이 있어서, 클라들이 그 시스템과 상호작용하는거.
- 컴퓨터 한 대가 굉장히 많은 기능들을 하는 것.
- 프로그램 하나를 짜기 위해서 수백~수천명이 기계적으로 일정 관리하면서 협업
초기에는, 보통 기업체에서 엄청 비싼 컴퓨터(서버)를 샀다. 컴퓨터가 너무 비싸서, 비싼 거 하나 사서 여러 개를 네트워크로 연결하는 게 더 저렴했기 때문.
이때 여기에 연결하는 사용자들의 컴퓨터는 터미널이라 부름. 우리가 아는 터미널 처럼 생김.
이 터미널에다가 키보드 입력을 하면, 서버로 보내고, 서버가 처리한 후 다시 돌려주는 방식으로 작동했다. (클라-서버 구조).
→ 한 컴퓨터와 상호 작용하기 때문에 데베 언어 통일, 개발 언어 통일해서 요청하고, 받고 하며 동작했다.
SOA – (서비스 중심으로) 쪼개짐. Service Oriented Architecture
- 컴퓨터 한 대에다가 모든 복잡한 기능을 다 때려박는 게 아니고, 네트워크를 통해 수많은 서버를 연결해서 쓰자
- 서버들을 쪼개서, 서비스 기능을 분할. 그들 간에는 통신을 통해 정보를 주고받도록 함.
- 처음 진행되었을 때에는 분할된 애들도 좀 덩치가 컸다.
이제는 HTTP나 통신 프로그램 등이 일반화되고, 컴퓨터가 저렴해졌다.
이제는 오히려 싸구려 인텔 씨피유 여러 개 합치니까 거대한 애 성능 나오네? 이렇게 된 것
(물론 돈이 있으면 강력한 거 하나가 성능적으로 나음. but 여러 개 합치는 방향이 더 가성비 굿)
Micoservices
- 서비스 기능들을 더 잘게 쪼개서 수천, 수만대의 컴퓨터에 나누어서 넣음
- Serverless: 굉장히 작은 단위로 분할. 극단적으로, 함수 하나만 돌리는 컴퓨터의 느낌.
- 수천-수만대 컴퓨터를 필요할 때 쓰고 필요없으면 없애는… 클라우드 컴퓨팅 개념도 등장
한번 쪼개지기 시작했더니 급속도로 쪼개지기 시작했다! 왜냐면.. 가지고 있는 컴퓨터의 개수가 엄청 많았기 때문. 구글같은 경우 200~300만개의 컴퓨터가 있음. 그래서 엄~~~~청나게 쪼개질 수 있는 거.
결국, 한 컴퓨터에서 함수 하나만 돌아가도 되는 지경에 이르렀다. 아이콘 내놓는 서버, 사진 내놓는 서버 등.
API 주면, API를 주는 정도로 req-resp가 오가는 상황이 된 것. → Serverless. 굉장히 작아진 서버. 등장
굉장히 작게 쪼개짐. 그러다보니, 거대한 누군가를 접속하기 위해 가로질러야 했던 과거에서부터, 이제 옆에있는 Microservices 끼리 대화해야 되니까, 통신의 목적이 달라진 것. 옆에 애 하고 대화하고자 하는 쪽으로 바뀜.
→ DB언어나 개발 언어는, 옛날엔 통일했는데, 이제는 걍 서비스별로 다 다름. 팀별로 독자적으로 언어를 선택할 수 있고, 팀안에서도 언어를 나눠서 짜고 돌릴 수도 있고. 각각 속성에 최적화된 쪽으로 하면 되는 것.
→ 그리고 작은 단위로 개발하고 돌아가다보니, 개발 시간도 단축되고, 업데이트도 엄청 빨라짐. 개발한 것도 우리팀꺼에만 합치면 되니까, 거대한거랑 합칠 필요는 없는것. → continuous하게 integration하고 delivery(출시).
마이크로서비스화되어있는데 서로쪼개져있는프로그램들 굳이 프로그래밍 언어를 통일할 필요가 없다!!!
◆ JSON 파일
JSON 등장 배경
처음에는 바이트 단위로 TCP통신을 했다.
그러다가, HTTP위에 XML을 주고받기 시작. HTML은 웹페이지 위에 문서를 보내는거고, XML은 좀더 확장한 느낌. 웬만한 문서들 다 표현 가능. 이걸통해서 ‘서버야 니가 이런걸 수행해줬으면 좋겠어‘를 표현.
그런데 XML은 그림처럼 엄청 많은 태그들, 표현 방식, … 같은게 필요했다. (배 < 배꼽)
그래서 등장한 JSON: int, float, set, dict, string,…등을 표현할 수 있는 방식.
■ TCP때와 다른점?!
- TCP: 바이트 단위로 보내.
- SOA, RESTful : JSON으로 보내. Int, float, set, dict, string등을 보내.
→ 주고받는 데이터의 형태를 지정해야 할 때 TCP에 비해 굉장히 쉬워짐.
쉽게 얘기하면 소스코드 형식의 데이터를 보내도록 한 것.
< JavaScript로 개발하지 않은 앱과 서버들에서 JSON 형태의 데이터를 주고 받는 이유 >
기본적으로 웹 서버 개발 시 다루는 포멧이 JSON이다.
(클래스가 컴퓨터 메모리를 점유할 때 오브젝트인 것처럼, 자바스크립트가 객체를 표현하는 양식인 JSON을 사용해서 클라 투 서버, 서버 투 서버 통신을 하는 것)
그럼 자바 스크립트를 쓰는거임? ㄴㄴ. 자바스크립트에서 데이터를 표현한 그 방식 JSON만 쓰는 것임.
인터넷 발달하면서 JS언어가 확산되었고, 웹 브라우저는 보통 JS 번역기를 내장하기에 웹 서비스에서 유리함.
그러면서도 기본적인 프로그래밍 언어의 데이터 형태들(float, int, 등)을 지원하기 때문에 쓰기 편함.
따라서, JS로 개발하지 않은 앱과 서버들에서도 자바스크립트 객체로 변환할 수 있는 텍스트 형태를 주고 받으며 통신한다.
단, 데이터만 실어나르는 것임. 메서드는 없음.
JSON 대표 함수
- json.dump() : dict 데이타를 json 포맷 화일로 저장함
- json.load() : json 화일을 읽어서 dict 데이타로 변환홤
- json.dumps() : dict 데이타를 json 포맷 문자열로 변화함
- json.loads() : json 포맷 문자열을 dict 데이타로 변환함
◆ REST 구조란?
HTTP를 기반으로 상대방의 기능을 호출하거나 데이터를 주고받는 철학.
(JSON보다는 좀 더 생산성을 높이고 개발이 용이하도록 하는 방향을 추구함)
- RESTful : REST를 좀 더 구체적인 형태로 세분화 한 것
◆ REST 구조에 대한 제한 조건
- 인터페이스 일관성)
HTTP1.1은 온갖 메서드들을 자유자재로 사용해서 프로그래밍하는 건데, REST는 그래도 좀 더 일관적 형태를 갖춰야 하지 않겠어? 라는 권장사항. - 무상태)
서버는 오직 현재 도착한 리퀘스트 정보만을 가지고 처리하며, 이를 저장해두지 않는다. - 캐시 처리 가능)
클라이언트는 응답을 캐싱할 수 있어야 함. modified가 되었는지 아닌지 확인하여, 이미 이전에 그 결과를 가지고 있는 경우 캐싱해둔걸로 사용하는 방안. - 계층화)
클라와 서버 사이에 중간 서버(ex: 프록시)들이 존재해도 잘 동작하도록 해야 함.
중간에서 수많은 서버들에게 작업을 잘 분배할 수 있어야 함. (클라-프록시-서버라든지, 클라-프록시-프록시-서버 라든지 하는 계층 구조) - [옵션] Code on demand)
전달하는 것이 프로그램일 수 있어야 함. (수업에선 안다룸) - 클라/서버구조)
클라-서버 각 파트가 독립적으로 개선될 수 있도록 함.
◆ CRUD 원칙!?
HTTP의 리퀘들을 Create, Read, Updae, Delete와 1:1로 매핑하여 쓰는 것.
누군가(클라 또는 서버) 서버에게 HTTP 리퀘스트를 보낼 때, 해당 리퀘스트를 썼다면 다른 액션을 취하도록.
예를들어 다음과 같이 쓸 수 있음
- POST: 새로운 데이터베이스 레코드인 것처럼 creation을 해줘라.
- GET: (파일을 가져오는 게 아니라) 정보를 가지고 옴. Read.
- PUT: 정보를 업데이트한다. (Write)
- DELETE: Delete
이런것들이 쓰인 Url이나 body를 통해서, 추출하고자 하는 identifier같은걸 추출한다.
※ 예를 들어: http://localhost/ 서버를 다음처럼 개발할 수 있음
http://localhost/my_api/로 해서,
서버가 “my_api”에 대응해서 제공하는 기능을 호출함
더 이상 “my_api”는 원래 의미의 directory 개념이 아님
http://localhost/my_api/{문자열} 처럼 HTTP Req를 Server에 보내면,
서버는 {문자열}과 HTTP Req의 Body로 전달한 값을 입력 파라메타로 하여,
GET/POST/PUT/DELETE에 상응하는 기능을 수 행하고, 결과를 Client에 리턴 하도록 할 수 있음
ex)
GET을 Read로 간주하여, {문자열}을 Key 값으로 하여, 서버의 record들을 찾아 대응하는 Value를 리턴
POST을 Create로 간주하여, {문자열}을 Key 값으로 하고, HTTP Req의 Body에 해당하는 값을 Value로 하는 record를 생성
◆ RESTful API에서, CRUD란 무엇인가?
HTTP/1.1을 사용한다(광의).
JSON파일을 사용한다(협의).
CRUD원칙을 따른다
+) 여기서 추가로,
"우리 회사는 키값을 url로 받고, 세부정보를 body로 받고, body는 이렇게 처리하겠다!" 까지 갔을 때, RESTful.
REST 정신을 만족시키는 API인 것.
즉, CRUD 원칙을 회사가 구현할 수 있는 형태로 조금 더 구체화 한 것이 RESTful API.
(각각의 회사들이 이걸 어떻게 정의하는지에 대한 문서가 나와있다.)
※ RESTful API를 구현하는 간단한 예시: url을 건드리는 것.
예를들어 클라-서버 간 다음과 같은 약속을 하는 것이다.
Url 에 해당하는 주소가 있으면 파일이지만, 없으면 함수로 넘기도록 하자 → RESTful API
: 파일을 주고받는 게 아니라 대화를 하는 것임(정보를 주고받는 것). Url에다가 원하는 데이터를 집어넣음ㅇㅇ
'CS > 풀스택서비스네트워킹' 카테고리의 다른 글
8. HTTP/2 (0) | 2023.12.08 |
---|---|
7. gRPC (0) | 2023.12.08 |
5. ZeroMQ (1) | 2023.10.15 |
4. Socket (0) | 2023.09.30 |
3. OSI Arghitecture L4 (0) | 2023.09.30 |