본문 바로가기

CS 전공수업/컴퓨터 네트워크

[네트워크] 전송계층 - TCP와 UDP, 그리고 (De-)Multiplexing

OSI 7계층 중 전송계층은, sender와 receiver를 연결하는 통신 서비스를 제공하는 계층. 그 둘 사이의 데이터의 전달을 위한 판을 까는 역할을 함(데이터의 물리적인 전달은 X, 라우팅 등 물리적인 움직임은 그 하위계층인 네트워크부터 시작).

 

전송계층에서는 판을 까는 방법론에 있어서 몇 가지 "프로토콜"을 활용하는데, 대표적으로 TCP 혹은 UDP를 주로 씀.

요새는 HTTP3 등의 프로토콜을 QUIC 프로토콜 기반으로 만드는 등 QUIC 프로토콜도 종종 쓰는 것 같지만, 아직까지 미완성형이기 때문에 아직까지 TCP와 UDP를 실무에서 대체하기는 어려움.

 

 

 

TCP - 데이터를 안정적으로, 순서대로, 에러 없이!

좋은 예시를 보았는데, IP가 집 주소라면 TCP는 쿠팡이다 - 그러니까, 목적된 IP를 향해 택배기사가 직접 움직여서 가는 것과 별개로, 그 택배를 실시간으로(완전한 실시간은 아니지만) 추적하고, 손실되었다면 새로 보내주는 등의 관리자 역할을 하는 게 TCP. TCP가 판을 깔아두고 실시간으로 추적, 감시 그리고 보호하고 있기 때문에, 만약 도중에 몇개 패킷이 유실되더라도 얼마 안 가 유실된 패킷을 보내줄 수 있는 것.

 

(1) 연결 파트 + (2) 송/수신 & 마무리

 

(1) TCP의 연결 방식3-way handshake이라고 부르는데, 이는 다음과 같이 진행됨.

  1. SYN: 클라이언트가 서버에 연결을 요청하는 단계. 클라이언트는 SYN(Synchronize Sequence Number) 패킷을 서버로 보내고, 자신의 초기 시퀀스 번호를 함께 전송. 이 패킷은 서버에게 클라이언트가 연결을 시작하고자 함을 알림.
  2. SYN-ACK: 서버가 클라이언트의 연결 요청을 받고, 연결을 수락할 준비가 되었다는 응답을 보내는 단계. 서버는 SYN 패킷과 ACK(Acknowledgment) 패킷을 함께 클라이언트에게 보냄. 이 패킷은 서버의 초기 시퀀스 번호도 포함.
  3. ACK: 클라이언트가 서버의 SYN-ACK 패킷을 받고, 서버에게 ACK 패킷을 보내 연결이 성공적으로 수립되었음을 알리는 마지막 단계. 이 패킷을 통해 클라이언트는 서버의 시퀀스 번호를 확인하고, 양쪽 모두 데이터 전송을 준비.

이 과정을 통해 TCP는 클라이언트와 서버 간에 안정적인 세션을 구축하여 데이터를 순서대로, 신뢰성 있게 전송할 수 있는 환경을 마련함.

 

 

(2) 데이터 송/수신 및 연결 마무리

 

- 데이터 전송
연결이 설정되면, TCP는 데이터를 세그먼트로 나누고 이를 IP 패킷 내에 실어 보냄. 패킷마다 번호를 매겨서 순서를 보장하고, 추가로 데이터 무결성 검증, 그리고 ACK 및 재전송 제어 등을 통해 신뢰성 있는 데이터 전송을 보장. ACK는 어떤 패킷이 잘 도착했을 경우에 돌아오는 사인이고, 만약 아무리 기다려도 ACK가 안 돌아온다면 언제까지 기다릴 순 없으니까, 패킷 별로 타임아웃을 설정해둠. 해당 시간이 지나면 현재의 패킷을 무력화하고 똑같은 파일을 다시 보냄.

seq는 내가 보내는 데이터의 시작 byte, ACK는 니가 보낸 데이터의 마지막 byte + 1

 

- 흐름 제어(flow control) 및 혼잡 제어(congestion control)
TCP는 네트워크의 상태(데이터 손실, 네트워크 혼잡 등)를 모니터링하고, 이에 따라 데이터 전송 속도를 조절. 이는 네트워크의 효율적 사용을 보장.

 

흐름 제어: 송신이 수신보다 빨라서 수신기에서 버벅대지 않게끔 도와주는 역할.

혼잡 제어: 네트워크의 혼잡 상태를 고려하여 데이터의 전송 속도를 조절하는 메커니즘.

 

둘 다 송신 쪽에서 너무 많은 데이터를 보내는 것을 방지하는 것인데, 눈치를 보는 대상이 흐름 제어는 수신기(목적지)의 상황을 봐주는 거라면, 혼잡 제어는 네트워크(길바닥)의 상황인 것.

 

 

- 연결 종료


데이터 전송이 끝나면, TCP는 4-way handshake를 통해 연결을 종료. 이 과정에서 클라이언트와 서버는 서로에게 연결 종료 의사를 확인하고 세션을 안전하게 종료.

이렇게, 일련의 과정을 '연결'이라는 판떼기 위에서 굴리는 형식이므로, TCP는 stateful에 해당함.

참고로, HTTP, DNS, UDP 등은 모두 일련의 정보를 기억하지 않는, stateless임.

 

HTTP 1.0 + TCP connection example

 

 

 

UDP - 운송 중 좀 떨굴 순 있어도, 일단 빠름

TCP가 결과론적인 운송 실수 zero라는 슬로건을 내걸었다면, UDP는 운송 좀 떨궈도 없어진 데이터들 복구 못해줌, 아니 사실 없어졌는지 아닌지도 모름. 그러나 반대로, 연결도 안 하고 에러 처리에도 심혈을 안 기울이기 때문에, 운송이 빠르다는 장점이 있음.

 

데이터는 순서가 있는 segment 단위로 쪼갰던 TCP와는 달리, UDP는 데이터를 순서없는 Datagram으로 쪼갬. 데이터그램끼리는 서로 독립적인 관계를 가지고, 순서 상관없이 그냥 목적지에 도착하는대로 스며듦.

 

UDP의 헤더는 다음과 같이 생김.

https://webstone.tistory.com/147

 

출발지 포트와 목적지 포트, 길이, 오류검사(checksum) 이렇게 4개 항목이 있음.

 

Checksum이란, 에러를 잡아내는 부분임. 1의 보수 형태로 저장하고, 에러가 나면 여기에 표시하는데, 일단 기억할 것은, 출발지에서 만약 오류 검사를 비활성화하고 싶으면 해당 칸을 전부 0으로 채운다는 것과, 만약 에러가 없이 무결한 상태면 전송이 끝나고 checksum 파트가 모두 1이라는 것.

 

당연히, Reliable Data Transfer의 일종인 TCP와 달리, UDP는 Unreliable Data Transfer임. 그럼 왜 쓰냐? 모든 데이터 전송이 완전무결한 전송을 요구하지는 않기 때문. 좀 잃어버리더라도, 빠른 전송이 필요한 경우가 있음. 그 대표적인 경우가 스트리밍. 예를 들어 비디오를 송출한다고 하면, 픽셀 하나 나간다고 큰 무리가 없고, 그것보다는 안 끊기게끔 빠른 전송이 유지되는 게 중요하므로 UDP를 활용함.

 

그런데 UDP를 쓰면서도, 이걸 좀 reliable하게 만들고 싶다면 다~ 방법이 있음. 다만 전송 계층에서는 못하고, 응용 계층에서 손봐줘야 함. 방법은 바로바로 Automaitc Repeat reQuest, 즉 ARQ를 추가하는 것.

 

 

Automatic Repeat reQuest

ARQ는 응용계층에서 unreliable인 프로토콜을 reliable로 만들어주는 방법. 이 부분만 따로 포스트화 했으니 이 포스트를 보도록 하자.

 

 

 

Multiplexing / Demultiplexing - 다중화 / 역다중화

UDP든, TCP든 관계없이, transport 계층에서 제공하는 기본적인 기능.

 

큰틀에서는, application에서 여러 개의 데이터가 생성되고, 적절한 형식으로 포맷됨. 그러고 나서 전송계층으로 넘어가기 전에 잘게 분쇄되어 넘어감. 전송계층에서는 이 정보들을 모아 큰 데이터로 뭉치고, 네트워크 쪽으로 넘김. multiplexing.

https://www.geeksforgeeks.org/multiplexing-and-demultiplexing-in-transport-layer/

 

* 참고로 소켓은 응용 계층과 전송 계층 사이를 연결하는 통로역할임.

 

정리하면 다음과 같음.

 

Sender의 multiplexing: 여러 개의 소켓을 통해 넘어온 여러 개의 데이터를 모아 더 큰 형태로 만들고 (TCP의 경우 segment, UDP는 datagram이라 부름) 전송계층의 헤더를 붙임.

 

Receiver의 demultiplexing: 헤더의 내용을 떼서, 이걸 참조해서 맞는 소켓에 갖다 넣어줌.

 

멀티/디멀티플렉싱 시 참고하는 내용이 UDP(connectionless)와 TCP(connection-oriented)가 다름.

 

UDP의 경우: 소켓이 port #로 특정되므로, 디멀티플렉싱이 목적지 IP 주소와 목적지 port #를 참고함.

 

 

TCP의 경우: 목적지의 IP와 port #, 출발지의 IP와 port #의 총 4개의 정보를 참고함.

 

결과적으로 크게 다른 점: UDP의 경우 모든 포트가 서로 다른 번호를 가지지만, TCP의 경우 4개의 정보가 모두 존재하기 때문에, 목적지 입장에서는 본인 앞으로 동일한 dest IP, port 조합을 가진 여러 개의 데이터가 날아와도, 그 녀석 옆의 source IP와 port 조합을 기준으로 어떤 program 것인지 구분하여 나눌 수 있다는 점.