네트워크를 부분적으로 공부한 후 간결하게 정리하였습니다.
개선점들을 알려주신다면 적극 반영하겠습니다.
(개발 입문 시 간단히 공부했던 TCP / UDP에 대해 재정리했습니다.)
TCP (Transmission Control Protocol)
TCP(전송 제어 프로토콜)은 IP의 핵심 프로토콜 중 하나로, OSI 4계층인 전송 계층에 위치하는 프로토콜이다.
IP 네트워크에서의 데이터 통신은 데이터 전송의 불확실성, 데이터 손실, 라우팅 과정에서의 패킷 손실 등이 있는데, 이는 우편을 받기까지의 과정을 생각해본다면 쉽게 이해할 수 있다.
편지가 우체국에서 분류될 때, 실수로 잘못된 주소로 보내지거나 운송 중 분실될 수 있다. 이는 IP 네트워크에서 패킷이 전송 중에 손실되거나, 네트워크 경로를 이탈하여 수신자에게 도달하지 않는 것과 같다.
또한 편지가 예상보다 늦게 도착하는 것처럼, IP 네트워크에서도 패킷이 중간의 여러 노드들을 거치며 지연될 수 있다.
이와 같이, IP 네트워크에서의 데이터 전송의 불확실성과 손실은 우편 시스템에서 편지를 보내는 과정에서 발생할 수 있는 분실, 지연, 손상의 문제와 유사하다. 이러한 이유로 TCP와 같은 프로토콜이 등장하게 되었다.
TCP는 이러한 IP의 단점을 보완해 패킷 전송을 제어하여 신뢰성을 보장할 수 있는 프로토콜이다.
IP 위에 TCP를 얹어 신뢰성을 보장할 수 있게 되었다고 보면 되는데 이를 풀어서 얘기하면 다음과 같다.
목적지에 도달하게끔 하는 IP위에 TCP를 얹어 목적지에 올바르게 도착했는지, 원활하게 소통이 완료되었는지 등을 확인하고, 데이터가 제대로 전달이 되지 않았다면 다시 요청을 보낸다. 이러한 메커니즘을 통해 데이터 전송의 신뢰성을 보장한다.
특징
1. 연결형 서비스로 가상 회선 방식을 제공(Handshake, Connection-Oriented) 하여 높은 신뢰성을 보장한다.
- TCP는 데이터를 보내기 전 수신자와 연결을 확립하고 데이터 전송이 끝날 때 까지 연결을 유지한다.
2. 데이터 처리속도를 조절하여(흐름 제어) 수신자의 버퍼 오버플로우를 방지한다.
- 송신자가 수신자의 처리 능력에 맞춰 데이터 전송 속도를 조절한다.
3. 네트워크 내의 패킷 수가 과도하게 증가하지 않도록 방지한다.(혼잡 제어)
- 네트워크 혼잡 상황을 감지하여 데이터 전송 속도를 조절한다.
4. 전이중, 점대점 방식을 사용한다.
- 전이중(Full-Duplex) 방식 - 전송이 양방향으로 동시에 일어날 수 있다.
- 점대점(Point to Point)방식 - 각 연결에 2개의 종단점을 가지고 있다.
이러한 TCP의 특징들 덕분에 데이터 전송의 신뢰성을 보장하고, 패킷 손실이나 데이터 손실이 발생하더라도 이를 복구할 수 있다.
구조
기존 IP 패킷이 프레임에 포함되어 전송되는것 처럼, TCP또한 세그먼트(Segment)라 불리우는 데이터가 IP 패킷에 포함되어 전송된다.
TCP 세그먼트가 IP 패킷에 포함되어 전송되며, TCP 세그먼트를 포함한 IP 패킷은 프레임에 포함되어 물리적으로 전송된다.
아래 그림과 표에서, TCP 세그먼트의 구조와 간단한 설명을 확인할 수 있다.
SYN(동기화)
시퀀스 번호의 동기화를 위해 사용하는 플래그로, 상대방에게 어떤 시퀀스 번호를 수락해야 하는지 알려주는 데 사용된다.
ACK(승인)
호스트가 성공적으로 수신한 패킷을 승인하는 데 사용된다. 확인 번호 필드에 유효한 확인 번ㅂ호가 포함되어 있으면 플래그가 설정된다.
FIN(Finish)
연결 종료를 요청하는데 사용되며, 발신자가 보내는 마지막 패킷이다. 리소스를 해제하고 연결을 정상 종료한다.
PSH(Push)
데이터를 즉시 전달하기 위해 사용하는 플래그로 수신자가 데이터를 버퍼에 저장하지 않고 즉시 처리하도록 지시한다. 주로 상위 계층의 빠른 데이터 전송이 필요할 때 사용한다.
통신 과정
TCP의 통신과정은 연결 수립 - 데이터 통신 - 연결 해제의 3단계로 통신이 이루어지는데, 각 단계별로 나눠서 간단히 설명해보자.
연결 수립(3-way Handshake)
Handshake란?
서로가 손을 내밀고, 악수를 하는 모습과 유사하게 TCP 연결 수립, 종료가 이루어진다.
이에 비유하여 Handshake라는 용어를 사용하며, 수립은 3단계의 HandShake, 종료는 4단계의 Handshake과정이 이루어져 3-way Handshake, 4-way Handshake라고 부른다.
1. 연결 요청(SYN)
클라이언트에서 서버(Source Port to Destination Port)로 연결 수립을 위한 요청을 보낸다.
이 때 SYN 플래그를 가진 세그먼트를 보내며, 시퀀스 번호(Sequence Number)는 랜덤하게 선택되지만, 예시로 0으로 두었다.
2. 응답 확인(SYN-ACK)
서버에서는 올바른 연결일 경우, 연결 수립이 되었다는 세그먼트를 ACK 플래그를 담아 보낸다.
이 때 응답 번호(Acknowledgement Number)를 보내는데, 이는 다음 요청에 대한 시퀀스 번호의 기대값을 의미한다.
3. 연결 확인(ACK)
클라이언트가 서버에게 다시 통신을 하여, 올바르게 연결이 수립되었다는 확인 세그먼트를 보낸다.
서버에서 예상하는 기대값인 1을 시퀀스 번호에 담아 전송한다.
데이터 통신
1. 서버로 데이터 전송
클라이언트에서 서버로 데이터를 전송한다. 이 때 데이터는, 단순 요청일 수도 있고, 서버에 적재해야하는 데이터일 수도 있다. 이 때 시퀀스 넘버는 연결 수립 시의 시퀀스 번호 그대로 1이다.
2. 서버에서 성공적으로 수신 확인(ACK)
요청을 성공적으로 수신하였다면, 서버는 성공적으로 수신되었다는 확인 응답(ACK)을 보낸다.
이 응답은 기존 시퀀스 넘버에 데이터의 바이트를 합친 값만큼 다음 요청의 기대값이 된다.
3. 클라이언트로 데이터 전송
클라이언트에서 데이터를 보낼 때, 새로운 시퀀스 넘버는 이전의 ACK 번호가 된다.
4. 클라이언트에서 성공적으로 수신 확인(ACK)
서버가 데이터를 수신하고 새로운 ACK 번호를 보내어 수신 확인을 응답한다.
만약 이 과정들에서 ACK를 받지 못하였다면, 데이터 송신을 실패한 것으로 판단하여 데이터를 재전송하게 된다.
Data의 Bytes는 제한이 있을까?
데이터가 설정된 MTU(Maximum Transmission Unit)을 초과하면, 데이터를 여러 세그먼트로 분할하여 전송된다.
위의 TCP 구조에서 언급했던 것 처럼, 분할된 세그먼트의 순서를 보장해주는 것이 시퀀스 번호와 응답 번호이다.
MTU와 MSS
MTU(Maximum Transmission Unit)
네트워크 인터페이스에서 전송할 수 있는 최대 패킷 크기. 이더넷의 경우 일반적으로 1500바이트이다.
MSS(Maximum Segment Size)
TCP 계층에서 한 번에 전송할 수 있는 최대 세그먼트 크기로, MTU에서 IP헤더와 TCP헤더의 크기를 뺀 값이다.
연결 종료(4-way Handshake)
1. 클라이언트 연결 종료(FIN)
클라이언트가 서버에게 연결 종료 플래그를 설정한 세그먼트를 보낸다. 이 때 시퀀스 번호는 마지막으로 보낸 데이터의 시퀀스 번호다.
2. 서버에서 수신 확인(ACK)
서버는 클라이언트의 FIN 세그먼트를 수신하고 이를 확인하는 ACK 응답을 보낸다.
3. 서버 연결 종료(FIN)
1과 마찬가지로 FIN 플래그를 설정한 세그먼트를 클라이언트에게 보낸다.
4. 클라이언트에서 수신 확인(ACK)
2와 마찬가지로 ACK 응답을 서버로 보낸다.
응답 번호는, 마지막 수신한 시퀀스 번호 + 1이 된다.
데이터의 순서를 보장하며, 데이터의 무결성을 확인할 수 있고, ACK 번호를 통해 흐름제어가 가능하다.
또한 ACK 번호가 예상보다 낮다면 이전 데이터가 손실되었음을 의미하여 데이터를 재전송할 수 있게 해준다.
TCPdump로 패킷 분석
결국 직접 코드로 보면서 이해한다면, 더 좋을 것이라 생각했다. tcpdump를 사용해 네트워크 트래픽을 실제로 보냈을 때의 패킷을 분석해보자.
설치 및 셋팅
준비물은 두 개의 터미널이다. 하나의 터미널엔 모니터링 세팅을, 하나의 터미널은 요청을 보내보자.
# 설치
## Linux
apt-get install tcpdump
## Mac
brew install tcpdump
# 트래픽 캡처
## 모든 네트워크 인터페이스의 패킷 중 HTTP 트래픽만, 숫자 형식으로 출력
sudo tcpdump -i any -nn port 80
요청 보내서 응답 받기
# 요청 보내기
## mag1c.tistory.net:80에 success를 전송한다. (TCP연결 테스트)
echo "success" | nc magic.tistory.net 80
패킷 분석
캡쳐된 패킷들을 분석해보자.
총 10개의 패킷이 캡처되었고 12개의 패킷이 필터링되어 수신되었으며, 커널에서 드롭된 패킷이 없다고 나와있다.
TCP의 한계
휴대폰을 로컬 데이터로 사용하다 와이파이 연결 시 기존 이용하던 애플리케이션의 끊김 현상을 본 적이 있을 것이다.
TCP는 네트워크 환경이 변경될때 마다 새로운 커넥션을 맺어 연결을 확립해야하기 때문에 끊김 현상이 발생한다.
TCP 통신에서, 시퀀스 넘버와 응답번호를 통해 패킷의 순서를 보장받을 수 있었다. 조금 다르게 말하면 반드시 순서대로 처리되어야 한다는 뜻이다. 처리되는 순서가 정해져있기 때문에 이전에 받은 패킷을 파싱하기 전까지 다음 패킷을 처리할 수 없다.
설정한 시간동안 패킷이 수신되지 않는다면? TCP의 특성 때문에 패킷을 다시 보내서 처리해야한다.
이러한 특성 때문에, 병목 현상이 발생할 수 있는데, 이를 HOL Blocking(Head of Line Blocking)이라 한다.
TCP의 한계 때문에, HTTP 3.0에서는 TCP 대신 UDP기반의 새로운 프로토콜인 QUIC가 채택되게 되었다.
UDP (User Datagram Protocol)
TCP는 핸드쉐이크 과정을 거쳐 신뢰성 있는 통신을 할 수 있도록 보장했고, 데이터 전달 여부를 확인하는 등 데이터를 전송하기 위한 작업들이 많았다.
시대가 변하면서 전송해야하는 데이터도 단순 텍스트를 넘어 동영상이나 웹 스트리밍, 음악 같은 멀티미디어를 전송하면서 데이터의 크기가 점점 커져갔고, TCP의 특징 때문에 속도의 한계가 존재했다. 확실한 전달, 안전성 등을 제공하기 위해 추가적인 오버헤드와 대기 시간이 소요됐던 만큼, 데이터 크기에 비례하여 속도가 느려졌다.
UDP는 데이터그램 방식을 사용하는 프로토콜로, 패킷 간의 순서가 존재하지 않는 독립적인 패킷을 사용한다.
하나의 데이터를 전송할 때, 연결 상태를 보장하지 않아 소통이 안전하지 않고, 데이터가 잘 전달됐는지를 확인하지 않는다. 확인하지 않기 때문에 TCP처럼 재전송하지 않는다는 얘기다.
이런 단점에도 불구하고, TCP보다 빠르고 가볍다는 장점이 있어서 동영상이나 웹 스트리밍, 실시간 회의, 게임 등의 분야에서 널리 사용된다. TCP처럼 데이터를 전송하기 위한 추가작업들이 없고 단순 전달만 하기 때문에 전송 속도가 빠르며, 헤더 크기또한 8bytes로 20bytes ~ 60bytes인 TCP보다 가볍다.
구조
TCP의 세그먼트 구조에 비해 굉장히 단순하며 이를 통해서도 TCP에 비해 가볍고 빠르다는 걸 유추해볼 수 있다.
통신 과정
TCP는 데이터를 전송하면, ACK 플래그를 통해 데이터 전송의 신뢰성, 순서 보장등을 제공했다. 하지만 UDP는 단순 데이터를 보내줄 뿐이다. 위의 그림을 보면, 데이터 하나를 보내기위해 TCP는 데이터 전송의 확인 과정을 거치기 때문에 한 데이터를 전송하기 위한 과정이 UDP보다 많고 복잡하다.
이처럼, UDP는 데이터를 단순히 던져놓기 때문에 빠르고 단순하다.
TCP의 패킷 분석에서, 총 10줄의 패킷이 발생했던 것과 다르게 UDP는 단 한줄로 마무리된다. 아래 명령어를 이전의 터미널에 입력해보자. 위에서 말한것 처럼추가 과정 없이 단순 데이터를 전송만 한다는 것을 알 수 있다.
echo "UDP TEST" | nc -u mag1c.tistory.com 80
QUIC (Quick UDP Internet Connections)
TCP의 한계 때문에, HTTP/3 에서는 QUIC라는 새로운 프로토콜이 채택되게 되었다.
QUIC는 구글이 개발한 UDP를 기반으로 TCP + TLS + HTTP를 구현한 새로운 OSI 4계층의 프로토콜로, HTTP/3 에서 표준으로 채택되었다.
TCP를 사용하는 경우, TCP를 통한 핸드셰이크 과정이 필요하며, TLS또한 자체 핸드셰이크가 필요하다. 각 핸드셰이크는 클라이언트와 서버 사이를 완전히 왕복해야하며, 클라이언트가 서버의 물리적인 거리에 비례해 시간이 길어진다. 하지만 QUIC은 단 한번의 핸드셰이크면 된다.
또한 TCP는 방화벽 및 NAT 디바이스와 같은 수많은 장치들에 의해 읽히고 조작된다. 하지만 QUIC는 UDP를 사용하여 완전히 암호화되어 세부 정보를 검사거나 조작할 수 없게 만든다.
기존의 TCP에서는 IP와 포트로 식별했기 때문에, 네트워크 환경이 바뀌면 연결을 다시 수립했어야하지만 QUIC은 연결을 식별하기 위해 연결 ID를 사용하는데, 이는 네트워크 경로가 변경되더라도 그대로 유지된다. 유튜브를 보면, 네트워크를 와이파이로 변경하거나 로컬 데이터로 돌아오더라도 원활하게 스트리밍이 되는 것을 볼 수 있다.
정리하면, QUIC는 UDP를 기반으로 빠른 연결과 데이터 통신을 가능하게 한다.
단일 라운드 트립 또는 0-RTT로 연결을 설정하여 연결 지연을 최소화하였고, TCP의 연결 및 데이터 전송 기능, TLS의 보안 기능, HTTP/2의 멀티플렉싱 기능을 모두 통합하여 단일 프로토콜로 구현한 것이 QUIC이다.
참조
2023.04 ~ 백엔드 개발자의 기록
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!