전송계층의 역할은, 포트번호를 이용하여 알맞은 프로세스에 데이터를 전달하는 역할을 한다. 즉, 네트워크계층에선 호스트를 특정하여 데이터를 전송했다면 전송계층에선 호스트가 실행하는 프로세스에 데이터를 전달하는 것이다.
TCP와 UDP의 차이점
그렇다면 모두 같은 전송계층인데, 두 프로토콜의 차이점은 무엇일까? 쉽게 요약하자면
TCP는 데이터를 보내기 전, 송신자와 수신자 간의 연결을 맺고, 신뢰성을 보장하면서 데이터를 전송하는 방식이고
UDP는 연결을 맺지 않고, 신뢰성을 보장하지 않으면서 전송하는 방식이다.
그렇다면 TCP는 어떻게 신뢰성을 보장하며 전송하고, UDP는 어떻게 보장하지 않고 전송하는지 살펴보겠다.
TCP
1️⃣ 연결 지향적 (3-way handshake)
TCP의 신뢰성 보장을 위한 첫 단계로, 송신자와 수신자의 양측 연결 상태를 확인하는 과정이다.
양측 모두 서로 통신할 준비가 되었다면 연결이 완료된다.
또한, 연결 시작할때 초기 시퀀스 번호를 설정한다. 해당 번호는 데이터의 순서를 보장하는데 필수적인 요소이다.
만약 연결 설정하지 않고 데이터를 전송하면 초기 시퀀스 번호가 없기 때문에 순서보장이 불가능하고 오류제어를 위한 기반도 마련되지 않는다.
연결 설정(3-way handshake)
1. 송신자가 수신자에게 초기 시퀀스 번호를 포함한 SYN 패킷을 보낸다 (연결 요청) - 이때, 송신자의 초기 시퀀스 번호가 10이라면, "SYN, Seq=10" 형태로 보낸다.
2. 수신자가 ACK + SYN로 응답한다.( 연결 요청 수락 + 연결 요청)
- 수신자의 초기 시퀀스 번호가 50이라면 "SYN-ACK, Seq=50, Ack=11" 형태로 보낸다.
이때, ACK 번호는 송신자의 다음 패킷을 달라는 의미로, "송신자의 초기 시퀀스번호 +1" 의 형태로 보낸다.
3. 송신자가 ACK를 보낸다. (연결 요청 수락)
- "서버의 시퀀스 번호 +1"을 포함한 패킷을 보낸다. "ACK, Seq=11, Ack=21"
따라서, 연결설정을 하는 이유는,
1. 서로 연결이 가능한 상태인지 확인하여 통신을 위한 다리를 만들어주는 역할이며,
2. 연결 가능한 상태일 경우엔 세그먼트 데이터에 시퀀스 번호를 부여하여 순서보장과 오류처리를 가능하게 해주기 위해서이다.
연결 종료 (4-way handshake) 연결 설정을 해주었으면, 연결이 끝났을때 종료를 해주어야한다. 이유는, TCP는 양방향 연결을 사용하기 때문에 한 쪽이 데이터를 더 이상 보내지 않겠다고 종료요청을 해도 상대방은 여전히 데이터를 전송할 수 있기 때문이다. 따라서 양측 모두 연결 종료 절차를 거쳐야 한다.
1. FIN 패킷 송신 ( 송신: 연결 종료 요청) - 송신자는 3000번까지의 데이터를 보냈고, 이제 보낼 데이터가 없음을 알린다. "FIN, Seq=3001"
2. ACK 패킷 수신 (수신: 연결 종료 요청 확인) - 수신자가 FIN을 받았음을 확인하고, 다음 데이터는 3002번부터 받을 것임을 알린다. "ACK, Seq=5001, Ack=3002"
3. FIN 패킷 송신 (수신:연결 종료 요청) - 수신자도 더 이상 보낼 데이터가 없음을 알린다. "FIN, Seq=5001"
4. ACK 패킷 수신 (송신: 연결 종료 요청 확인) - 송신자가 수신자의 FIN을 받았음을 확인 하고, 연결을 종료시킬 것을 알린다. "ACK, Seq=3002, Ack=5002"
2️⃣ 신뢰성 보장
연결 설정 이후, 데이터를 보내면서 신뢰성(순서 뒤바뀜, 패킷 손실 문제)을 보장해줘야 한다.
🔷 순서 보장
3-way handshake 과정에서 부여된 시퀀스 번호를 이용하여 올바른 순서로 재조립한다.
1. 송신측에서 시퀀스 번호가 부여된 데이터를 전송한다.
2. 수신측에서 시퀀스 번호를 확인한다. 이때, 첫번째 세그먼트가 아닌 두번째 세그먼트가 먼저 도착하면 첫번째 세그먼트가 올때까지 기다린다.
🔷 체크섬(데이터 변형 감지)
체크섬은 송신자가 데이터를 보낼 때 계산한 값과 수신자가 받은 데이터로 다시 계산한 값을 비교하여 데이터가 손상되었는지 확인하는 방식이다.
1. 송신자는 데이터를 보내기 전에 체크섬 값을 계산하여 TCP 헤더의 Checksum 필드에 저장한다.
2. 수신자는 데이터를 받은 후 동일한 방식으로 체크섬을 계산하여 송신자가 보낸 값과 비교한다.
- 일치하면 데이터가 정상적으로 전달되었음을 의미한다.
- 불일치하면 데이터가 손상되었다고 판단하고, 해당 데이터를 폐기하고 ACK를 보내지 않는다. 송신자는 일정 시간이 지나도 ACK를 받지 못하면 해당 패킷이 손실되었다고 판단하고 재전송한다.
🔷 타임아웃 재전송(RTO->패킷손실 감지)
일정 시간이 지나면 재전송해준다.
1. 송신자는 데이터를 보낼때 타이머를 설정한다. (RTO 설정)
2. 일정 시간이 지나도 ack가 안오면 패킷이 손싱되었다고 판단하고 재전송한다.
*RTO: ACK를 기다리는 최대 시간을 의미한다.
🔷빠른 재전송(중복ACK -> 패킷손실 감지)
중복 ack를 여러번 보내면 재전송해준다.
1. 수신측이 중복 ack(같은 ack)를 여러번 보내면 송신 측은 패킷이 손실되었다고 판단하고 즉시 재전송한다.
2. 보통 세 번 연속으로 같은 ack를 받으면 바로 재전송하는데 이를 3중 중복 ack라고 한다.
3️⃣ 흐름제어와 혼잡제어
TCP는 두가지 주요 문제점이 있다.
1. 수신 측이 처리할 수 있는 속도보다 빠르게 데이터를 보낼 경우→ 수신 버퍼가 넘쳐, 패킷 손실이 발생한다 (흐름제어 필요)
2. 네트워크가 감당할 수 있는 용량보다 많은 데이터가 한꺼번에 전송될 경우 → 패킷이 유실되고, 네트워크가 혼잡해진다 (혼잡제어 필요)
🔷 흐름제어 ( 슬라이딩 윈도우 기법 )
송신 측이 너무 많은 데이터를 보내면 수신 측이 처리하지 못해 데이터가 유실될 수 있다 따라서 수신측은 윈도우크기를 조절해서 수신측의 처리속도에 맞게 송신 속도를 조절할 수 있다.
*수신 윈도우크기 (RWND) : 송신 측이 한 번에 보낼 수 있는 데이터의 양으로, 수신측 버퍼의 상태를 기준으로 한다.
1. 수신측은 수신버퍼를 확인하여, 자리가 없을 경우엔 TCP 헤더의 윈도우 크기 값을 줄여, 송신 측에게 알려준다.
2. 송신측은 해당 값을 보고 윈도우 크기를 조절해서 수신측의 처리 속도에 맞게 송신 속도를 조절한다.
🔷 혼잡제어 ( AIMD 기법 )
송신 측이 네트워크 상태를 고려하지 않고 너무 많은 데이터를 보내면 네트워크가 혼잡해진다. 따라서 tcp는 네트워크가 혼잡한지 감지하고 혼잡이 발생하면 전송속도를 줄이는 방식으로 해결할 수 있다.
*혼잡 윈도우크기(CWND): 네트워크 상태를 반영해서 동적으로 변하는 윈도우의 크기로, 네트워크 상태에 따라 송신 측이 데이터를 얼마나 빨리 보낼 수 있는지 결정하여 혼잡이 감지되면 송신 속도를 줄인다.
1. 매번 데이터가 정상적으로 전송되면 (ACK를 받을 때마다 ) CWND를 조금씩 증가시킨다.
즉, 송신 측과 수신 측은 서로 연결이 되어 있다고 가정하고 데이터를 주고받는다. 따라서 연결을 설정하는 오버헤드가 없어서 빠른 데이터 전송이 가능하다
2️⃣ 순서보장, 오류제어가 없다.
🔷 순서보장
UDP는 데이터를 전송할 때 패킷 순서를 보장하지 않는다. 만약 송신 측에서 패킷 1, 2, 3을 보냈더라도 수신 측에서는 2, 3, 1 순서로 받을 수 있다. 수신 측은 이러한 순서 오류를 자동으로 처리하지 않고, 수신 순서대로 데이터를 처리해야 한다.
🔷 오류제어
체크섬:UDP는체크섬을 통해전송 중 데이터 오류를 감지할 수 있다. 오류가 발생한 패킷은 버려지지만, 재전송이 이루어지진 않는다.
패킷손실 (RTO, 중복ACK) :패킷이 손실되거나 지연되는 상황을 감지하고 복구하는 기능이 없으며, 손실된 패킷을 자동으로 재전송하지 않는다.
3️⃣ 빠른 속도
TCP와 달리 연결을 설정하거나 오류 제어를 위한 과정이 없기 때문에, UDP는 데이터 전송 속도가 빠르고, 오버헤드가 적다. 또한, UDP의 헤더 크기는 8바이트로 매우 작기 때문에, 데이터 전송에 필요한 메타데이터 처리 비용이 적어 속도가 더욱 빠르다.
이 때문에 실시간 통신이나 스트리밍과 같은 빠른 데이터 전송이 필요한 경우에 적합하다.
4️⃣ 멀티캐스트 및 브로드캐스트 지원
UDP는 멀티캐스트와 브로드캐스트를 지원하여, 한 번에 여러 수신자에게 데이터를 전송할 수 있다.
예를 들어, 비디오 스트리밍이나 실시간 게임처럼 여러 명에게 동시에 전송이 필요한 경우에 유용하게 사용된다.
*멀티캐스트: 특정 그룹에 속한 수신자들만 데이터를 받도록 전송하는 방식이다.
*브로드캐스트: 네트워크에 연결된 모든 장비에게 데이터를 보내는 방식이다.
UDP 정리
UDP는 연결 설정 없이 데이터를 전송하며, 패킷의 순서 보장과 오류 제어 기능이 없는 대신 빠른 속도를 제공하는 프로토콜이다.
TCP와 UDP 헤더 구조
1️⃣ TCP
1. Source Port : 출발지 측에서 사용하는 포트번호
2. Destination Port : 목적지 측에서 사용하는 포트 번호
3. Sequence Number: 세그먼트 순서를 맞추기 위한 필드
4. Acknowledgement Number : 시퀀스 번호의 다음 번호를 의미하는 필드
5. Data Offset : TCP 헤더의 크기를 나타내는 필드
-> UDP는 8바이트의 고정된 헤더를 가지고 있지만 TCP는 가변적이다.
-> 기본적으로 20바이트를 가지고 있다.
6 .Reserved : 차후의 사용을 위한 예약된 필드
-> 이 필드는 현재 사용되지 않으며 0으로 설정된다. 향후 확장성에 대비한 공간으로 보통 예약된 필드로 추후 TCP 프로토콜의 확장이 있을 경우 이 공간이 사용될 수 있다.
7. Control Flags: (SYN, ACK, FIN ...등) : 긴급, 혼잡, 확인, 수신 거부 등의 기능
8. Window size : 수신자가 한번에 받을 수 있는 데이터의 양 (수신윈도우)
9. Checksum: 세그먼트 내용의 유효성과 손상 여부 검사
2️⃣ UDP
1. Source Port : 출발지 측에서 사용하는 포트번호
2. Destination Port : 목적지 측에서 사용하는 포트 번호
3. Length (2바이트): UDP 헤더와 데이터를 합친 총 길이
-> TCP는 연결 지향적 프로토콜로, 데이터 전송이 연속적인 스트림으로 이루어진다. 따라서 개별 패킷의 길이를 표현할 필요가 없다.
-> UDP는 비연결 지향적 프로토콜로, 독립적인 패킷을 처리하기 때문에 개별 패킷의 길이를 표현할 수 있다.
3. checksum : 세그먼트 내용의 유효성과 손상 여부 검사 (TCP의 체크섬과는 다르게 UDP의 체크섬은 사용해도 되고 안해도 되는 옵션)
실제 사용 예시
1️⃣ TCP
TCP는 신뢰성과 순서 보장이 중요한 애플리케이션에서 사용된다.
1. 웹통신
페이지의 내용이 손상되거나 순서가 뒤바뀌면 사용자에게 오류를 초래할 수 있기 때문에 신뢰성과 정확성이 높아야한다.
2. 파일 전송
파일을 전송할 때 데이터의 일부가 손실되거나 순서가 뒤바뀌면, 전송된 파일이 완전하지 않거나 손상될 수 있다. 예를 들어 , udp를 사용하게 되면 일부 패킷이 손실되었을때 이를 복구하지 못해 파일 전송에 오류가 생길 수 있다.
2️⃣ UDP
UDP는 빠른 전송 속도가 필요한 애플리케이션에서 사용된다.
1. 실시간 음성/영상 통화
빠르게 데이터를 전송할 수 있고 데이터의 손상이나 순서 뒤바뀜이 큰 문제가 되지 않는다.
TCP처럼 패킷이 손실될 때마다 재전송하면 영상이 끊기거나 딜레이가 발생할 수 있다.
🤔 그렇다면 웹 통신에는 무조건 tcp만 써야하고 udp는 사용하면 안되는 것인가? tcp는 속도나 지연에 있어 한계가 있을 수 있기 때문에 UDP기반 QUIC프로토콜이 사용되기도 한다. QUIC는 TCP의 신뢰성과 UDP의 속도를 결합한 상태로, 신뢰성은 보장해주지만 연결설정이 없기 때문에 속도가 빠르다.
🤔 TCP보다 QUIC가 더 좋은 것 아닌가? QUIC는 신뢰성을 보장해주면서 속도가 빠른 프로토콜이다. 그런데 왜 신뢰성만 보장해주는 TCP를 더 많이 사용하는 것일까.
바로, 호환성 문제 때문이다. TCP는 거의 모든 네트워크 환경에서 잘 작동하며, 기존의 많은 시스템과 애플리케이션에서 이미 널리 사용되고 있다. QUIC는 아직 모든 네트워크 환경과 인프라에서 기본적으로 지원되지 않아서 호환성 문제가 있을 수 있다.