TCP 프로토콜 작동 원리, 인터넷을 지탱하는 보이지 않는 힘

TCP 프로토콜 작동 원리, 인터넷을 지탱하는 보이지 않는 힘

0

TCP 프로토콜 작동 원리를 알고 나면 인터넷이 달라 보인다. 유튜브에서 4K 영상이 끊김 없이 흐르고, 카톡 메시지가 빠짐없이 도착하고, 결제가 한 번에 처리된다. 우리는 이걸 당연하게 여기지만, 그 밑바닥에서 묵묵히 일하는 게 바로 TCP다. 알고 보면 인터넷은 꽤 영리하게 설계된 약속 덩어리다.

TCP(Transmission Control Protocol)는 불안정한 네트워크에서도 신뢰성 있는 데이터 전송을 보장하는 인터넷의 핵심 프로토콜이다. 패킷이 사라지고, 순서가 뒤바뀌고, 중간 회선이 막혀도, 받는 쪽에는 보낸 그대로 도착한다. 네트워크를 처음 공부하는 개발자라면 반드시 짚고 넘어가야 할 토대다.

TCP 프로토콜 작동 원리를 보여주는 3-way 핸드셰이크 다이어그램, 클라이언트와 서버가 SYN, SYN-ACK, ACK를 주고받는 과정
TCP 프로토콜 작동 원리를 보여주는 3-way 핸드셰이크 다이어그램, 클라이언트와 서버가 SYN, SYN-ACK, ACK를 주고받는 과정

IP만으로는 왜 부족한가

인터넷의 기본 프로토콜인 IP는 한 호스트에서 다른 호스트로 패킷을 전달하는 일만 한다. 우편배달부가 건물 주소만 보고 편지를 던져두고 가는 것과 비슷하다. 그런데 건물 안에는 수많은 세대, 곧 프로세스가 산다. 각자 받아야 할 편지가 다르다.

여기서 포트(port)가 등장한다. IP 주소가 건물이라면 포트는 호수다. 웹 서버는 80번, SSH는 22번, 데이터베이스는 3306번 포트에 자리 잡고 각자 일한다. TCP는 이 포트 기반의 프로세스 간 통신을 책임지는 전송 계층 프로토콜이다.

하지만 TCP의 진짜 가치는 따로 있다. IP는 패킷이 제대로 도착했는지, 순서가 맞는지, 깨지지 않았는지 전혀 신경 쓰지 않는다. 반대로 TCP는 이 전부를 떠안는다. 손실되면 다시 보내고, 뒤바뀌면 재조립하고, 체크섬으로 무결성을 검증한다. 프로토콜이라는 개념 자체가 궁금하다면 MCP, AI와 현실을 잇는 프로토콜도 같은 맥락에서 읽을 만하다.

TCP 프로토콜 작동 원리의 두 축, 흐름 제어와 혼잡 제어

TCP 프로토콜 작동 원리의 핵심은 두 개의 속도 조절 장치에 있다. 흐름 제어와 혼잡 제어다.

흐름 제어는 받는 사람 사정을 본다. 빠른 서버가 느린 클라이언트에게 초당 수백 MB를 쏟아부으면, 클라이언트 수신 버퍼가 넘쳐 데이터가 유실된다. TCP는 윈도우(window)로 이걸 막는다. 수신 측이 헤더의 윈도우 필드에 “지금 16KB까지 받을 수 있어”라고 적어 보내면, 송신 측이 그만큼만 보낸다. 리눅스에서는 net.ipv4.tcp_rmem으로 수신 버퍼를 조정하고, 요즘 시스템은 윈도우 스케일링으로 크기를 자동 조절한다.

혼잡 제어는 네트워크 전체를 본다. 1986년 인터넷은 혼잡 붕괴(congestion collapse)를 겪었다. 너무 많은 데이터가 동시에 몰려 회선이 마비됐다. 이 사건 이후 TCP에 백오프 장치가 들어갔다. 지금의 TCP는 조심스럽게 시작하고(slow start), 조금씩 전송량을 늘리다가(congestion avoidance), 손실이 감지되면 다시 줄인다. 고속도로에서 차들이 흐름을 보며 속도를 맞추는 것과 같다.

C로 보는 TCP 서버의 뼈대

이론만으론 손에 안 잡힌다. 실제 소켓이 어떻게 쓰이는지 보자. 아래는 TCP 에코 서버의 핵심 흐름이다.

// 1. 소켓 생성
int server_fd = socket(AF_INET, SOCK_STREAM, 0);

// 2. 주소에 바인드
bind(server_fd, (struct sockaddr*)&address, sizeof(address));

// 3. 연결 대기
listen(server_fd, 3);

// 4. 클라이언트 연결 수락
int client_fd = accept(server_fd, ...);

// 5. 데이터 송수신
recv(client_fd, buffer, sizeof(buffer), 0);
send(client_fd, response, strlen(response), 0);

이 짧은 코드 뒤에 복잡한 메커니즘이 숨어 있다. listen() 뒤 서버가 잠깐 멈춰 있어도, 클라이언트가 보낸 데이터는 커널 수신 버퍼에 안전하게 쌓인다. 서버가 깨어나면 순서대로 처리하면 된다. HTTP 서버도 결국 이런 TCP 소켓 위에서 돈다. curl localhost:8080을 치면 TCP 연결이 맺어지고, 요청이 오가고, 서버가 HTTP/1.1 200 OK로 답한다. 이런 토대 위에서 개발 생산성을 끌어올리는 흐름은 AI가 코드를 대신 쓰는 시대 개발자의 역할에서 더 다뤘다.

세그먼트 해부와 3-way 핸드셰이크

TCP 패킷, 정확히는 세그먼트는 이런 정보를 담는다.

  • 출발지/목적지 포트(각 16비트): 포트는 65,536개까지
  • 시퀀스 번호: 보낸 바이트의 위치
  • ACK 번호: 다음에 받기를 기대하는 바이트
  • 윈도우 크기: 받을 수 있는 데이터 양
  • 체크섬: 무결성 검증
  • 플래그: SYN, ACK, FIN, RST 같은 상태 제어

하나의 연결은 (프로토콜, 출발지 IP, 출발지 포트, 목적지 IP, 목적지 포트)라는 5-튜플로 고유하게 식별된다. 덕분에 서버 하나가 수천 클라이언트와 동시에 떠들 수 있다.

연결은 3단계로 맺어진다. 클라이언트가 SYN을 던지고(“연결하고 싶어”), 서버가 SYN-ACK로 답하고(“좋아, 나도”), 클라이언트가 ACK로 확인한다(“알겠어”). 끊을 때는 양쪽이 FIN과 ACK를 주고받는 4-way로 정중히 작별한다. 물론 사고가 나면 RST 플래그로 그냥 끊어버릴 수도 있다.

데이터가 중간에 사라지면 어떻게 될까. 1000~2000, 2000~3000, 3000~4000 바이트를 보냈는데 가운데가 유실됐다고 하자. 수신 측은 계속 ACK 2000을 보낸다. “2000까지는 받았는데 그다음이 안 와.” 송신 측은 같은 ACK가 반복되거나 타임아웃이 나면 그 패킷을 다시 보낸다. 성공하면 수신 측이 누적 ACK로 답한다. “이제 4000까지 다 받았어.” 이 약속 덕분에 개발자는 네트워크의 불안정을 잊고 로직에만 집중할 수 있다.

현장에서 바로 쓰는 TCP 팁

  • 상태 모니터링: 리눅스에서 ss -tnp로 연결 상태를 본다. 수신/송신 버퍼 크기까지 확인된다.
  • Keep-Alive: 오래 노는 연결을 유지하려면 활성화한다. 주기적 프로브로 살아있는지 확인한다.
  • Nagle 알고리즘: 작은 패킷을 묶어 효율을 높이지만, 실시간 게임이나 채팅처럼 지연이 치명적인 곳에서는 TCP_NODELAY로 꺼야 한다.

성능이 곧 사용자 경험이라는 점은 웹 자원도 마찬가지다. 같은 고민을 폰트 쪽으로 풀어본 폰트 성능 최적화 가이드도 함께 보면 감이 온다.

2026년, TCP는 끝났을까

요즘 TCP를 공부하다 보면 이런 질문이 든다. QUIC과 HTTP/3가 뜨는데 TCP는 한물간 거 아닌가. 절반만 맞다.

Cloudflare 같은 엣지망 기준으로 HTTP/3는 이미 약 35%의 트래픽을 차지한다. QUIC은 UDP 위에서 동작하며 TCP의 고질병이던 헤드 오브 라인 블로킹을 없앴고, 와이파이에서 셀룰러로 바뀌어도 연결이 끊기지 않는 연결 이전(connection migration)을 지원한다. MDN 문서에도 HTTP/3가 표준으로 자리 잡았다고 정리돼 있다.

그런데 QUIC이 푸는 문제도 결국 TCP가 수십 년간 다듬어온 개념의 재해석이다. 시퀀스 번호, ACK, 혼잡 제어 같은 아이디어는 그대로 살아 있다. 실제로 IETF의 BBR 혼잡 제어 표준안은 TCP와 QUIC 양쪽에서 쓰인다. 손실이 아니라 대역폭과 지연을 보고 속도를 맞추는 BBR은, TCP가 쌓아온 혼잡 제어 계보의 최신 버전이다. 그러니 QUIC을 제대로 이해하려면 먼저 TCP를 알아야 한다.

복잡함을 양 끝으로 밀어낸 설계

1980년대엔 몇 KB 파일 전송도 버거웠다. 지금은 4K 스트리밍이 기본이다. 이 도약은 TCP의 정교한 설계와 끊임없는 개선 덕분이다. TCP는 복잡성을 네트워크 양 끝단, 곧 호스트로 밀어냈다. 중간 라우터는 단순히 패킷만 넘기면 되고, 신뢰성은 양 끝이 알아서 챙긴다. 이 단순함이 인터넷을 폭발적으로 키운 철학이다.

HTTP, SMTP, SSH, FTP 같은 주요 서비스가 전부 이 위에서 돈다. 다음에 웹사이트를 열거나 메일을 보낼 때, 보이지 않는 곳에서 TCP가 일하고 있다는 걸 떠올려보자. TCP 프로토콜 작동 원리를 이해하는 일은 단순한 지식 쌓기가 아니라, 현대 인터넷 인프라가 어떻게 돌아가는지 들여다보는 첫걸음이다.

원리를 글로 읽었다면, 직접 만들어보며 익히는 게 가장 빠르다. 학습 자료나 다이어그램이 필요할 때 Gen Studio로 콘텐츠와 이미지를 만들어보는 것도 방법이다.

참고 자료: cefboud.com, “The Internet is Cool. Thank you, TCP”

답글 남기기