이번 유닛에서는 지난 유닛에서 다루었던 네트워크를 조금 더 깊이 알아보고 학습하는 시간이었다. 학습을 한 내용 정리를 시작해보겠다.
인터넷 프로토콜(IP : Internet Protocol)
IP와 IP Packet : 인터넷 통신의 기본
- 클라이언트와 서버는 IP 주소를 컴퓨터에 부여하여 이를 이용해 통신한다.
- IP는 지정한 IP Address에 패킷이라는 통신단위로 데이터를 전달한다.
IP Packet
- IP Packet은 출발지 IP, 도착지 IP와 같은 정보가 포함돼 있다.
- 패킷 단위로 전송을 하면 노드(컴퓨터)들은 목적지 IP에 도달하기 위해 서로 데이터를 전달한다.
- 서버에서 데이터를 전송받는다면 클라이언트에게 응답을 해주어야 하며, IP 패킷을 이용해 클라이언트에게 응답을 전달한다.
IP 프로토콜의 한계
- 비연결성 : 패킷을 받을 대상이 없거나, 서비스 불능 상태여도 패킷을 전송한다.
- 비신뢰성
- 중간에 패킷이 사라질 수 있다.
- 패킷의 순서를 보장할 수 없다.
TCP, UDP
- IP 프로토콜의 한계를 네트워크 계층을 통해 보완한다.
- 네트워크 계층은 OSI 7계층과 TCP/IP 4계층으로 나눌 수 있다.
- IP 프로토콜보다 더 높은 계층에 TCP 프로토콜이 존재하기 때문에 IP 프로토콜의 한계를 보완할 수 있다.
- 소켓은 프로그램이 네트워크에서 데이터를 송수신할 수 있도록, 네트워크 환경에 연결할 수 있게 만들어진 연결부가 네트워크 소켓이다.
- 예시
- HTTP 메시지가 생성되면 Socket 라이브러리를 통해 전달된다.
- IP 패킷을 생성하기 전 TCP 세그먼트를 생성한다.
- 생성된 TCP/IP 패킷은 LAN 카드와 같은 물리적 계층을 지나기 위해 이더넷 프레임워크에 포함돼 서버로 전송된다.
TCP/IP 패킷 정보
-
TCP 세그먼트에는 IP 패킷의 출발지 IP, 도착지 IP, 정보를 보완할 수 있는 출발지 PORT, 도착지 PORT, 전송제어, 순서, 검증 정보 등을 포함한다.
-
TCP의 특징 : 전송 제어 프로토콜(Transmission Control Protocol)
- 연결지향 : TCP 3 way handshake(가상연결)
- 장치들 사이에 논리적인 접속을 성립하기 위함
- 연결방식
- 클라이언트는 서버에 접속을 요청하는 SYN 패킷을 보낸다.
- 서버는 SYN 요청을 받고 클라이언트에게 요청을 수락한다는 ACK과 SYN이 설정된 패킷을 발송하고 클라이언트가 ACK으로 응답하기를 기다린다.
- 클라이언트가 서버에게 ACK을 보내면 이 이후로부터 연결이 성립되며 데이터를 전송할 수 있다.(Established)
- 데이터 전달보증
- 데이터 전송이 성공적으로 이루어진다면 이에 대한 응답을 돌려주기 때문에 IP 패킷의 한계인 비연결성을 보완할 수 있다.
- 순서보장
- 패킷이 순서대로 도착하지 않는다면, TCP 세그먼트에 있는 정보를 토대로 다시 패킷 전송을 요청할 수 있다. 이를 통해 순서를 보장하지 않는 비신뢰성을 보완할 수 있다.
- 신뢰할 수 있는 프로토콜
UDP : 사용자 데이터그램 프로토콜(User datagram Protocol)
- 기능의 거의 없다. 그래서 커스터마이징이 가능하다.
- 비연결 지향 : TCP 3 way handshake를 사용하지 않는다.
- 데이터 전달 보증 X
- 순서보장 X
- 데이터 전달 및 순서가 보장되지 않지만, 단순하고 빠르다.
- 신뢰성보다는 연속성이 중요한 서비스(ex. 실시간 스트리밍)에 자주 사용된다.
- UDP는 IP 프로토콜에 PORT, 체크섬 필드정보만 추가된 단순한 프로토콜이다.
- 체크섬(checksum)은 중복 검사의 한 형태로, 오류 정정을 통해 공간(전자통신)이나 시간(기억장치) 속에서 송신된 자료의 무결성을 보호하는 단순한 방법이다.
HTTP
- HTTP/1.1, HTTP/2는 TCP기반이며, HTTP/3은 UDP 기반 프로토콜이다.
특징
클라이언트 서버 구조
- Request, Response 구조
- 클라이언트는 서버에 요청을 보내고, 응답을 대기
- 서버가 요청에 대한 결과를 만들어 응답.
무상태 프로토콜 : 서버가 클라이언트의 상태를 보존하지 않음
- 장점 : 서버 확장성이 높다.(스케일 아웃 : 수평확장에 유리)
- 무상태는 응답 서버를 쉽게 바꿀 수 있다. -> 무한한 서버 증설이 가능하다
- 단점 : 클라이언트가 추가 데이터 전송할 때, 실무의 한계
비연결성
- HTTP는 기본이 연결을 유지하지 않는 모델이다.(HTTP/1.0 기준)
- 일반적으로(트래픽이 많지 않고, 빠른 응답을 제공할 수 있는 경우) 초 단위 이하의 빠른 속도로 응답한다. 그러므로 트래픽이 많고 규모가 커지면 한계가 있다.
- 1시간동안 수천명이 서비스를 이용해도 실제 서버에서 동시에 처리하는 요청은 수십개 이하로 매우 적다. 예를 들면 웹 브라우저의 검색 버튼이 있겠다.
- 한계와 극복
- TCP/IP 연결을 새로 맺어야 한다. -> 3 way handshake 시간 추가
- 웹 브라우저로 사이트를 요청하면 HTML 뿐 아니라 js, css, 추가이미지등 수많은 자원이 함께 다운로드된다.
- 지금은 HTTP 지속 연결(Persistent Connections)로 문제 해결
- HTTP/2, HTTP/3에서 더 많은 최적화가 이루어졌다.
HTTP 메세지
단순함, 확장 기능
HTTP 헤더
HTTP 헤더
HTTP 헤더와 바디(HTTP 메시지의 구분)
- HTTP 바디에서는 데이터 메시지 본문(message body)을 통해서 표현데이터를 전달한다.
- 메시지 본문(페이로드) : 데이터를 실어나르는 부분
- 표현은 요청이나 응답에서 전달할 실제 데이터다.
- 표현 헤더는 표현데이터를 해석할 수 있는 정보제공(데이터 유형(html, json), 데이터길이, 압축 정보 등)
HTTP 헤더
- 헤더 형식 <field_name>:<field_value>의 형식이며 name은 대소문자 구분이 없다.
- 용도
- HTTP 전송에 필요한 모든 부가정보(메시지 바디의 내용, 메시지 바디의 크기, 압축, 인증, 요청 클라이언트, 서버 정보, 캐시관리 정보...)를 담기 위해 사용한다.
- 표준 헤더가 너무 많다.
- 필요시 임의의 헤더 추가가 가능하다.
- 표현 헤더는 요청, 응답 모두 사용한다.
Content-Type : 표현 데이터 형식
- 미디어 타입, 문자 인코딩. e.g) Text/html;charset=utf-8, application/json, Image/png
Content-Encoding : 표현 데이터의 압축 방식
- 데이터를 전달하는 곳에서 압축 후 인코딩 헤더 추가
- 데이터를 받는 쪽에서 인코딩 헤더의 정보로 압축 해제 e.g))gzip, deflate, identity
Content-Language : 표현 데이터의 자연 언어 표현 e.g)ko, en, en-US
Content-Length : 표현 데이터의 길이
- 바이트 단위
- Transfer-Encoding(전송 인코딩)을 사용하면 chunked의 방식을 사용하는데, chunked 방식의 인코딩은 많은 양의 데이터를 분할하여 보내기 때문에 전체 데이터 크기를 알수 없으며, 표현 데이터의 길이를 명시해야 하는 Content-Length 헤더와 함께 사용할 수 없다.
HTTP 주요 헤더
From : 유저 에이전트의 이메일 정보
- 잘 사용하지 않는다.
- 검색 엔진에서 주로 사용한다.
- 요청에서 사용한다.
Referer
- 현재 요청된 페이지의 이전 웹 페이지 주소
- A -> B로 이동하는 경우 B를 요청할 때
Referer:A
를 포함해서 요청한다.
- Referer를 사용하면 유입 경로 수집이 가능하다.
- 요청에서 사용한다.
User Agent : 유저 에이전트 애플리케이션 정보
- 클라이언트의 애플리케이션 정보(웹 브라우저 정보 등)
- 통계 정보
- 어떤 종류의 브라우저에서 장애가 발생하는지 파악이 가능하다.
- 요청에서 사용
Server : 요청을 처리하는 Origin 서버의 소프트웨어 정보
- 응답에서 사용 ex) Server:Apache/2.2.22(debian), Server:nginx
Date : 메시지가 발생한 날짜와 시간, 응답에서 사용
Host : 요청한 호스트 정보(도메인)
- 요청에서 사용
- 필수 헤더
- 하나의 서버가 여러 도메인을 처리해야 될 때
- 하나의 IP 주소에 여러 도메인이 적용되어 있을 때
Location : 페이지 리디렉션
- 웹 브라우저는 3xx 응답의 결과에 Location 헤더가 있으면, Location 위치로 리다이렉트한다(자리이동)
- 201(created) : Location 값은 요청에 의해 생성된 리소스 URI
- 3xx(Redirection) : Location 값은 요청을 자동으로 리디렉션하기 위한 대상 리소스를 가리킨다.
Allow : 허용 가능한 HTTP 메소드
- 405(method Not Allowed)에서 응답에 포함. e.g)Allow:GET,HEAD,PUT
Retry-After : 유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간
- 503(Service Unavailable): 서비스가 언제까지 불능인지 알려줄 수 있다.
Authorization : 인증 토큰(e.g. JWT)을 서보로 보낼 때 사용하는 헤더
- 토큰의 종류 + 실제토큰 문자를 전송한다. e.g) Authorization:Basic sadkjasdW3daDDa..(토큰문자)
Origin : 서버로 POST 요청을 보낼 때, 요청을 시작한 주소를 나타낸다.
- 요청을 보낸 주소와 받은 주소가 다르면 CORS 에러가 발생한다.
- 응답 헤더의 Access-Control-Allow-Origin과 관련
Access-Control-Allow-Origin : 요청을 보내는 주소와 받는 주소가 다르면 CORS 에러 발생
- 서버에서 이 헤더에 프론트 주소를 적어주어야 에러가 발생하지 않는다. 프로토콜, 서브 도메인, 도메인, 포트 중 하나만 달라도 CORS 에러가 발생한다.
- 유사한 헤더로 Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Allow-Method, Access-Control-Allow-Headers 등이 있다.
콘텐츠 협상 (Content Negotiation)
콘텐츠 협상 : 클라이언트가 선호하는 표현 요청
- Accept : 클라이언트가 선호하는 미디어 타입 전달
- Accept-Charset : 클라이언트가 선호하는 문자 인코딩
- Accept-Encoding : 클라이언트가 선호하는 압축 인코딩
- Accept-Language : 클라이언트가 선호하는 자연 언어
- 협상 헤더는 요청 시에만 사용한다.
협상 헤더에서는 원하는 콘텐츠에 대한 우선순위를 지정할 수 있다.
- Quality Value(q) 값 사용
- 0~1, 클수록 높은 순위
- 생략하는 경우, 1
- ex) Accept-Language:ko-KR, ko;q=0.9, en-US;q-0.8, en;q=0.7
캐시
HTTP 헤더 - 캐시
캐시(데이터나 값을 미리 복사해 놓는 임시장소)가 없다면?
- 데이터가 변경되지 않아도 계속 네트워크를 통해서 데이터를 다운로드 받아야 한다
- 인터넷 네트워크는 매우 느리고 비싸다
- 브라우저 로딩 속도가 느리다
- 느린 사용자 경험 제공
캐시를 적용한다면?
- 캐시는 캐시의 접근 시간에 비해 원래 데이터를 접근하는 시간이 오래 걸리는 경우나 값을 다시 계산하는 시간을 절약하고자 하는 경우 사용한다
- 데이터를 미리 복사해 놓으면 계산이나 접근 시간 없이 더 빠른 속도로 데이터레 접근할 수 있다
- 브라우저에 캐시를 저장할 때느네 cache-control 속성을 통해 캐시가 유효한 시간을 정할 수 있다. ex) Cache-Control:max-age=60 (sec)
캐시 시간이 초과하는 경우
- 다시 서버에 요청을 하고 응답을 받게 되며, 다시 네트워크 다운로드가 발생한다.
- 응답 결과를 브라우저가 렌더링하면 브라우저 캐시는 기존 캐시를 지우고 새 캐시로 데이터를 업데이트한다. 유효시간 또한 초기화 된다.
검증헤더와 조건부 요청 : 캐시 제어
Last-Modified and If-Modified_Since
- 검증 헤더 Last-Modified를 이용해 캐시의 수정 시간을 알 수 있다.
- Last-Modified는 데이터가 마지막으로 수정된 시간 정보를 헤더에 포함한다.
- 캐시 유효 시간이 초과되더라도 If-Modified-Since 헤더를 이용해 조건부 요청을 할 수 있다.
- 과정
- 데이터가 수정됐는지 검증한다.
- 수정되지 않았다면 바디를 제외한 HTTP 헤더만 전송한다. 304 Not Modified
- 브라우저 캐시에서 응답 결과를 재사용, 헤더 메타데이터 또한 갱신된다.
- 브라우저는 캐시에서 조회한 데이터를 렌더링한다.
- 단점
- 1초 미만 단위로 캐시 조정이 불가능하다.
- 날짜 기반 로직 사용
- 데이터를 수정해서 날짜가 다르지만, 같은 데이터를 수정해서 데이터 결과가 똑같을 경우
- 서버에서 별도의 캐시 로직을 관리하고 싶은 경우
ETag 와 If-None-Match : 서버에서 완전히 캐시를 제어하고 싶은 경우, 더 간단한 방식
- ETag(Entity tag)
- 캐시용 데이터에 임의의 고유한 버전 이름을 담아둔다.
- 데이터가 변경되면 이 이름을 바꿔 변경한다 (Hash를 다시 생성)
- 단순하게 ETag만 보내서 같으면 유지, 다르면 다시 받는 방식
Cache-Contorol(캐시지시어)
- Cache-Control:max-age : 캐시 유효시간, 초단위
- Cache-Control:no-cache
- 데이터는 캐시해도 되지만, 항상 원(origin)서버에 검증하고 사용
- Cache-Control:no-store
- 데이터에 민감한 정보가 있으므로 저장X (메모리에서 사용하고 최대한 빨리 삭제한다)
Expires(캐시 만료일 지정) : Cache-Control의 하위호환
- 캐시 만료일을 정확한 날짜로 지정한다.
- HTTP 1.0부터 사용했다
- Cache-Control:max-age가 더 유연하고 권장하기 때문에, 같이 사용하면 Expires는 무시된다.
프록시 캐시
프록시 서버
- 프록시 : 클라이언트와 버서 사이에 대리로 통신을 수행하는 것
- 그 중계 기능을 하는 서버가 프록시 서버다.
- 클라이언트가 다른 네트워크 서비스에 간접적으로 접속할 수 있게 하는 컴퓨터 시스템이나 응용 프로그램이다.
클라리언트에서 사용하고 저장하는 캐시는 private 캐시, 프록시 캐시 서버를 public 캐시라고 한다.
Cache-Control
- Cache-Control:public : 응답이 public 캐시에 저장되어도 된다.
- Cache-Control:private : 응답이 해당 사용자만을 위한 것이므로, private 캐시에 저정해야 한다.(기본값)
- Cache-Control:s-maxage : 프록시 캐시에서만 적용되는 max-age속성이다.
- Age:60 (HTTP 헤더) : 오리진 서버에서 응답 후 프록시 캐시 내에 머문 시간(초)
캐시 무효화(Cache-Control)
-
Cache-Control:no-cache
- 데이터는 캐시해도 되지만, 항상 원(origin)서버에 검증하고 사용(이름에 주의한다.)
-
Cache-Control:no-store
- 데이터에 민감한 정보가 있으므로 저장X (메모리에서 사용하고 최대한 빨리 삭제한다)
-
Cache-Control:must-revalidate
- 캐시 만료 후 최초 조회 시 원 서버에 검증해야한다.
- 원 서버 접근 실패 시 반드시 오류가 발생해야한다. 504(gateway timeout)
- must-revalidate는 캐시 유효 시간이라면 캐시를 사용한다.
-
Pragma:no-cache : HTTP 1.0 하위 호환
-
확실한 캐시 무효화 응답을 하고 싶다면, 아래와 같이 모두 적용한다.
- Cache-Control:no-cache, no-store, must-revalidate
- Pragma:no-cache
no-cache vs must-revalidate
- 모두 원 서버에 검증해야 하지만 응답에 대해 다른 점이 있다.
- no-cache의 경우
- 캐시 서버 요청을 하면 프록시 캐시 서버에 도착하면 no-cache인 경우 원 서버에 요청을 하게 되고 원 서버에서 검증 후 304 응답을 하게 된다. 그런데 원 서버에 접근이 불가능 하다면, 응답으로 오류가 아닌 오래된 데이터라도 보여주자라는 개념으로 200OK 응답을 한다.
- must-revalidate의 경우
- 위와 같은 경우 504 Gateway Timeout 오류를 보낸다. 중요정보에 관한 큰 문제가 생기는 것이라면 must-revalidate를 사용해야 한다.
Reference