TCP 란?


프로토콜 계층

  • TCP 는 연결 지향형 프로토콜이다.
  • TCP 는 가상 회선을 만들어 신뢰성을 보장하도록 하는 프로토콜로 속도가 느리다.
  • TCP 는 파일전송과 같은 신뢰성이 중요한 서비스에 사용된다.

TCP (Transmission Control Protocol) 특징

  1. 연결지향 - TCP 3 way handshake (가상 연결)
  2. 데이터 전달을 보증한다.
    • 메시지를 받지 못했을 경우 데이터가 전달되지 않았다는 사실을 알 수 있다.
  3. 패킷의 순서를 보장한다.

TCP 3 way handshake

  • TCP 가 가상회선을 수립하는 단계이다.
  • 클라이언트는 서버에 요청을 전송할 수 있는지, 서버는 클라이언트에게 응답을 전송할 수 있는지 확인하는 과정이다.
  • SYN ACK 패킷을 주고받으며 임의의 난수로 SYN 플래그를 전송하고 ACK 플래그에 1을 더한값을 전송한다.

TCP 4 way handshake

  • TCP 연결을 해제하는 단계로 클라이언트는 서버에게 연결 해제를 통지하고 서버가 이를 확인하고 클라이언트에게 이를 받았음을 전송해주고 최종적으로 연결이 해제된다.
  • 단, 서버에서 소켓이 닫혔다고 통지해도 클라이언트 측에서는 일정시간 대기하는데 이는 혹시나 패킷이 나중에 도착할 수도 있기 때문이다.

흐름 제어

흐름 제어 (flow control) = 수신측이 감당 못 할 속도로 송신측이 보내는 것을 막는 메커니즘. “받는 쪽 버퍼 넘침” 방지.

  • 문제 = 송신측이 빠르고 수신측이 느리면 수신 TCP buffer 가 가득 참 → 이후 도착 패킷은 drop → 재전송 → 낭비.
  • 해법 = 수신측이 매 ACK 에 receive window (rwnd) 를 실어 “나 지금 이만큼 더 받을 수 있다” 통보. 송신측은 그 window 이내로만 in-flight 유지.
  • window = 수신측 TCP buffer 의 남은 여유 공간. 가변. 아래 ### Sliding Window·### Window-Size 가 이 메커니즘.
  • 극단 = 수신 buffer 가 0 이면 window 0 통보 = Zero-Window. 송신측은 멈추고 주기적으로 window probe 를 보내며 회복 대기. (위 ## 대표적인 TCP 장애 유형 의 Zero-Window 참고)

→ 흐름 제어 = 수신측 capacity 에 맞춤. 1:1 (송신↔수신) 관계.

혼잡 제어

혼잡 제어 (congestion control) = 네트워크(중간 경로)가 감당 못 할 속도로 보내는 것을 막는 메커니즘. “네트워크 혼잡” 방지.

  • 흐름 제어와 다른 점 = 흐름 제어는 수신측 버퍼, 혼잡 제어는 중간 네트워크(라우터 큐) 가 대상.
  • 송신측이 congestion window (cwnd) 를 따로 유지. 실제 송신량 = min(rwnd, cwnd).
  • 혼잡 신호 = 패킷 손실 (timeout 또는 dup ACK 3회). 손실 = 어딘가 라우터 큐가 넘쳤다는 뜻으로 해석.

기본 알고리즘 (TCP Reno 계열):

  1. Slow Start = cwnd 를 1 MSS 부터 시작, ACK 마다 2배씩 (지수 증가). 빠르게 대역 탐색.
  2. Congestion Avoidance = ssthresh (임계값) 넘으면 1 MSS 씩 (선형 증가). 조심스럽게.
  3. Fast Retransmit = dup ACK 3회 = 손실로 판단, timeout 안 기다리고 즉시 재전송.
  4. Fast Recovery = 손실 시 cwnd 절반으로 줄이고 선형 증가 재개 (timeout 시엔 1 로 리셋).

현대 알고리즘:

  • CUBIC = 리눅스 기본. 고대역·고 latency (BDP 큰) 환경에 최적화. window 증가가 3차 함수.
  • BBR = 구글. 손실 대신 대역폭·RTT 측정 기반. bufferbloat 회피.

→ 혼잡 제어 = 네트워크 capacity 에 맞춤. 손실을 신호로 송신 속도 조절.

정리 — 송신측은 두 window 의 최솟값으로 보낸다:

제어보호 대상신호window
흐름 제어수신측 buffer수신측의 rwnd 통보receive window (rwnd)
혼잡 제어중간 네트워크패킷 손실·RTTcongestion window (cwnd)

대표적인 TCP

프로토콜포트주요 기능사용 예시
HTTP (HyperText Transfer Protocol)80 (HTTP), 443 (HTTPS)웹 페이지 요청/응답웹브라우저로 웹사이트 보기
FTP (File Transfer Protocol)21 (제어), 20 (데이터)파일 전송 (평문)옛날 웹 서버에 파일 업로드
SFTP (SSH File Transfer Protocol)22보안 파일 전송서버에 로그/파일 업로드
SMTP (Simple Mail Transfer Protocol)25, 587, 465이메일 발송Gmail이 메일 보내는 방식
LDAP (Lightweight Directory Access Protocol)389 (LDAP), 636 (LDAPS)사용자 인증, 디렉터리 조회회사 사내 로그인 시스템, SSO

TCP 커넥션의 본질


TCP 커넥션 = 물리적 연결이 아니라 양쪽 OS 커널 메모리에 들고 있는 상태(state) 다. 핸드셰이크가 “establish” 하는 건 케이블이 아니라 양쪽 커널의 자료구조이고, 핸드셰이크 전후로 물리 경로(케이블·라우터·스위치) 는 동일하다.

커널이 커넥션마다 들고 있는 것

커넥션이 맺어지면 양쪽 커널이 TCP control block · socket structure 를 메모리에 만든다.

  • 4-tuple (src IP, src port, dst IP, dst port) = 커넥션의 고유 신원
  • 시퀀스 번호 = 어디까지 보냈고 받았는지
  • 윈도우 크기 = 상대가 받을 수 있는 양
  • 송수신 버퍼, 타이머

“커넥션이 ESTABLISHED” = 이 자료구조가 양쪽에 만들어졌고 두 쪽 다 ESTABLISHED 상태라는 뜻.

3-way handshake 가 실제로 하는 일

물리적 연결이 아니라 초기 시퀀스 번호 교환·합의다.

단계방향의미
SYNA → B”대화 시작. 내 시작 시퀀스 번호 X”
SYN-ACKB → A”X 받음. 내 시작 시퀀스 번호 Y”
ACKA → B”Y 받음”

왜 3 번인가 = 양쪽이 각자의 시퀀스 번호를 보내고 + 도달 확인까지 받아야 한다. A 번호는 1·2 번에서 확인, B 번호는 2·3 번에서 확인 → 양방향 확인에 최소 3 번.

UDP 와의 본질적 차이

TCP 의 “연결” = 신뢰성(순서 보장·손실 감지·재전송) 을 위한 공유 상태다. UDP 는 이 상태가 없어 “연결” 개념 자체가 없고 핸드셰이크도 없다.

사고실험 — 한쪽이 상태를 잃으면

A 와 B 가 커넥션 맺은 뒤 B 가 리부팅 → B 의 상태는 사라지지만 A 는 모른다.

  • A 는 여전히 혼자 ESTABLISHED.
  • A 가 다음 데이터를 보낼 때 B 가 RST 로 응답해야 비로소 끊긴 걸 안다.

귀결 = 연결은 양쪽의 상태이고, 한쪽이 상태를 잃어도 다른 쪽은 즉시 알 수 없다.

DB 커넥션과의 관계

DB 커넥션 = TCP 커넥션 위에 얹힌 상위 층.

  • 수립 순서
    1. TCP 커넥션 수립 (3-way handshake). DB 는 정해진 포트에서 listen — MySQL 3306, PostgreSQL 5432.
    2. 그 위에서 DB 프로토콜 핸드셰이크 — 인증, DB 선택, 문자셋·세션 파라미터 협상.
  • “DB 커넥션 수립” = TCP 커넥션 + DB 세션 상태.
  • DB 커넥션이 TCP 커넥션보다 무겁다 → 매 쿼리마다 새로 맺으면 비효율 → 커넥션 풀(HikariCP 등) 로 재사용.

송·수신 흐름과 encapsulation


TCP 데이터가 어떻게 네트워크를 타고 가나 — 각 계층이 자기 헤더를 차곡차곡 쌓는 게 핵심.

데이터 단위 (각 계층의 PDU)

단위어느 계층헤더 내용
SegmentTCP (L4)src/dst port, seq·ack 번호, window, flags
Packet (Datagram)IP (L3)src/dst IP, TTL, protocol
FrameEthernet (L2)src/dst MAC, EtherType, FCS (checksum)

Encapsulation — 송신 시

각 계층이 위에서 받은 데이터에 자기 헤더 부여:

[application data]
└─ TCP 부여  → [TCP hdr | data]                                = Segment
   └─ IP 부여 → [IP hdr | TCP hdr | data]                       = Packet
      └─ Eth → [Eth hdr | IP hdr | TCP hdr | data | FCS]        = Frame

흐름:

  1. Application = 데이터를 socket 에 write().
  2. TCP = 데이터를 MSS 단위로 split, TCP 헤더(seq·ack·window·port) 부여 → Segment.
  3. IP = Segment 에 IP 헤더(src·dst IP, TTL) 부여 → Packet. 필요 시 fragmentation (MTU 보다 크면 쪼갬).
  4. Ethernet (NIC) = Packet 에 Ethernet 헤더(src·dst MAC, EtherType) + 끝에 FCS 부여 → Frame. 전기 신호로 송출.

Decapsulation — 수신 시

역순. 각 계층이 자기 헤더 검증·제거하고 위로 전달.

[Eth hdr | IP hdr | TCP hdr | data | FCS]
   ↓  Eth hdr·FCS 검증·제거
[IP hdr | TCP hdr | data]
   ↓  IP hdr 검증·제거
[TCP hdr | data]
   ↓  TCP hdr 검증·시퀀스 정렬·제거
[data]
   ↓  application 이 read 로 가져감

MSS 와 MTU

둘 다 “한 번에 보낼 수 있는 최대 크기” 인데, 어느 계층의 무엇에 대한 제한인지가 다르다.

항목풀네임계층무엇의 최대표준값
MTUMaximum Transmission UnitL2 (Ethernet)frame 의 payload (= IP 패킷 통째)이더넷 1500
MSSMaximum Segment SizeL4 (TCP)TCP segment 의 data 부분 (헤더 제외)1460

관계 = MSS = MTU − IP 헤더(20) − TCP 헤더(20). 표준 이더넷·옵션 없는 케이스 = 1500 − 20 − 20 = 1460.

[Eth hdr | IP hdr (20) | TCP hdr (20) | data | FCS]
              └─────── MTU 안에 들어가야 함 (1500) ──────┘
                              └─── MSS ───┘  (= MTU − 20 − 20 = 1460)

누가 강제하나

  • MTU = L2 매체·NIC·드라이버. 이걸 넘으면 IP 가 packet 을 쪼개야 (= IP fragmentation, 성능 저하·loss 위험).
  • MSS = TCP 가 사전에 fragmentation 안 일어나게 segment 크기를 미리 줄이는 장치. 3-way handshake 의 SYN 옵션으로 양쪽이 자기 MSS 광고 → 작은 쪽 채택.

왜 둘 다 필요한가

  • MTU 만 있으면 TCP 가 “이 매체에서 안전한 데이터 크기” 를 모름 → 매번 큰 segment 만들고 IP 가 쪼개야 함.
  • MSS 가 있어 TCP 가 application 데이터를 처음부터 안전 크기로 split → fragmentation 회피.

특수 케이스

  • Jumbo frame = MTU 9000. MSS = 9000 − 40 = 8960. 데이터센터 내부 throughput 용.
  • VPN·터널 = VPN 헤더(예: WireGuard ~60B) 추가로 실효 MTU 감소 → MSS 도 줄여야. 자동 처리 = iptables ... --clamp-mss-to-pmtu.
  • IPv6 = IP 헤더 40B → MSS = MTU − 40 − 20 = 1440.
  • PMTUD (Path MTU Discovery) = 경로 중 가장 작은 MTU 를 찾아 그에 맞춰 조정. ICMP “Fragmentation Needed” 메시지 사용.

MSS vs TCP buffer vs window

MSS·TCP buffer·window 셋 다 “TCP 크기” 와 관련이지만 의미가 완전히 다르다. 흔한 혼동.

항목의미크기어디서 정해짐
MSS한 TCP segment 의 data 최대~1460 BTCP 3-way handshake 합의
TCP buffer소켓별 송·수신 큐16K~수MB커널 sysctl net.ipv4.tcp_{r,w}mem
Window size상대가 한 번에 받을 수 있는 byte (in flight)동적TCP flow control (헤더의 window 필드)

비유

  • TCP buffer = 창고 (전체 보관량, 큼)
  • MSS = 트럭 한 대 적재 한도 (한 번 운반 단위, 작음)
  • window = 상대가 “지금 더 받을 수 있어요” 통보하는 양

송신 시 셋 다 어떻게 같이 동작

  1. application write() → 데이터가 TCP send buffer 에 들어감.
  2. TCP 가 buffer 에서 꺼내 MSS 단위로 잘라 segment 만듦.
  3. 한 번에 보낼 수 있는 양은 상대의 receive window 까지 (window 가 작으면 buffer 가득 차도 못 보냄).
  4. ACK 받기 전까지 buffer 에서 안 지움 (재전송 대비).

확인 도구 — 자세한 건 07. Linux Networking > 패킷 버퍼 — 커널 vs 유저 공간 참고.

  • buffer 현재량 = ss -tmRecv-Q·Send-Q
  • buffer 크기 한도 = sysctl net.ipv4.tcp_rmem (수신), tcp_wmem (송신)
  • MSS 협상 결과 + window = ss -timss:1460, snd_wnd

흔한 혼동

  • “TCP buffer 가 1460?” → 아니. buffer 는 훨씬 큼 (수십 KB~MB). MSS 는 segment 단위 한도.
  • “MSS 크게 하면 buffer 도 커야?” → 아니. 독립 노브. MSS 는 L4·매체 관련, buffer 는 커널 메모리 관리.
  • “Window = buffer?” → 부분 관계. receive window 가 receive buffer 의 남은 공간을 광고하는 식. buffer = 내 쪽 메모리, window = 상대에게 알리는 “더 받을 수 있어요” 양.

OSI / TCP-IP 계층 매핑

OSI 7TCP/IP 4데이터 단위예시
L7 ApplicationApplicationdataHTTP, SSH, DNS
L6 Presentation(Application)dataTLS (일부 견해), 인코딩
L5 Session(Application)dataSocket API, RPC
L4 TransportTransportSegmentTCP, UDP
L3 NetworkInternetPacketIP, ICMP, ARP
L2 Data LinkLinkFrameEthernet, MAC, NIC driver
L1 PhysicalLinkbit케이블·전기 신호, NIC PHY
  • Segment / Packet / Frame 은 헷갈리기 쉬움 — 계층마다 다른 단위 이름.
  • TCP/IP 4 layer 가 실무에 가까움 (Session·Presentation·Application 묶음).

리눅스 커널 구현 측면

위는 프로토콜 보편 흐름. 실제 리눅스 커널이 이걸 어떻게 구현하나 — user/kernel mode 경계, socket buffer, syscall 복사, driver/NIC 까지 — 는 07. Linux Networking > TCP 송·수신 — 커널 구현 관점 참고.

대표적인 TCP 장애 유형


  1. AWS 같은 가상환경처럼 네트워크 인프라 환경이 좋은 상황에서는 비교적 발생 빈도가 낮은 장애 유형
    • Packet Loss
      • 패킷이 유실된 경우
      • 보안 정책 때문에 패킷 필터링에서 걸러지는 상황이 다수
      • 패킷을 못받은 호스트 입장에선 여전히 장애
    • TCP Out of order
      • 패킷의 순서가 뒤바뀐 경우
    • Retransmission 과 Dup ACK
      • 네트워크 혼잡 상황에 돌입
      • 위 2가지 상황 때문에 따라오는 상황
  2. 명백하게 응용 프로그램의 논리적 오류일 가능성이 매우 높은 유형
    • Zero-Window
      • 수신측 버퍼에 여유 공간이 하나도 없는 경우
    • 즉, TCP buffer 에서 패킷을 읽는 recv() 와 처리 간 시차 때문에 TCP buffer 가 가득 차는 경우 발생
    • 패킷을 읽는 recv() 를 실행하는 스레드와 패킷 처리를 위한 스레드는 반드시 분리해야한다

SACK

SACK, Selective Acknowledgement 란 수신측 OS 가 Sliding Window 에서 대기중이던 패킷이 일부 로스됐을 때 로스된 패킷만 재수신하겠다는 ACK 이다. 즉, 기본 ACK 는 로스된 패킷부터 마지막 패킷까지 재수신을 요청하지만 SACK 은 로스된 패킷만 재수신한다.

Sliding Window

패킷을 watch 하는 window 로 패킷 수신양에 따라 크기가 변한다.

Window-Size

수신측 TCP buffer 의 여유공간이다. 즉, Zero-Window 는 Window-Size 가 0 일 때 발생한다.

UDP 란?


  • UDP 는 데이터를 데이터그램 단위로 전송하는 프로토콜이다.
  • IP 와 거의 같지만, PORT 와 체크섬 정도만 추가된 상태다.
  • UDP 는 따로 신뢰성을 보장하기 위한 절차가 없어 속도가 빠르다.
  • UDP 는 스트리밍 RTP 와 같은 연속성이 중요한 서비스에 사용된다.
  • UDP 도 신뢰성을 UDP 자체에서 보장하지 않는 것 뿐이지 개발자가 직접 신뢰성을 보장하게끔 할 수 있다.
  • HTTP/3 는 QUIC 이라는 프로토콜을 기반으로 하는데 이는 UDP 를 기반으로 한다.
  • 즉, UDP 자체는 신뢰성을 보장하지 않지만 추가적인 정의를 통해 신뢰성을 보장받을 수 있다.