1. 라이브러리
  2. TCP와 UDP
  3. 프로토콜 기초

업데이트됨 1개월 전

웹 브라우저는 인터넷과 대화하는 방법을 모릅니다. 이메일 클라이언트도, 동영상 플레이어도, 컴퓨터에 있는 그 어떤 애플리케이션도 마찬가지입니다. 이들이 아는 것은 전송 계층과 대화하는 방법뿐이고, 나머지는 전송 계층이 모두 처리합니다.

이것이 OSI 모델의 4계층입니다. 불가능해 보이는 문제를 해결합니다: 서로 다른 기기에 있는 두 애플리케이션이, 알 수 없는 거리와 예측할 수 없는 네트워크를 사이에 두고, 어떻게 일관된 대화를 나눌 수 있을까요?

전송 계층이 해결하는 문제

웹 페이지를 불러올 때, 브라우저는 파일을 요청하려 합니다. 그 요청은 브라우저가 전혀 모르는 네트워크를 가로질러야 합니다—눈에 보이지 않는 라우터를 통과하고, 속도가 제각각인 링크를 거치며, 수백만 개의 다른 대화와 함께 이동합니다.

네트워크 계층(3계층)은 패킷을 여러분의 기기에서 서버까지 전달할 수 있습니다. 하지만 패킷은 순서가 뒤바뀌어 도착할 수 있습니다. 패킷이 손실될 수도 있습니다. 수신 측이 처리할 수 있는 것보다 빠르게 도착할 수도 있습니다. 네트워크 계층은 이를 신경 쓰지 않습니다—그것의 역할은 패킷을 라우팅하는 것이지, 패킷들이 일관된 대화를 이루도록 보장하는 것이 아닙니다.

전송 계층은 이 간격을 메웁니다. 애플리케이션의 통신 요구를 받아 네트워크가 전달할 수 있는 형태로 변환합니다. 그런 다음 네트워크가 전달하는 것—순서가 뒤바뀌고, 중간이 빠지고, 한꺼번에 몰려오는—을 받아 애플리케이션이 기대했던 형태로 재조립합니다.

네트워크는 "해볼게요"라고 말합니다. 전송 계층은 "보장합니다" 또는 "운에 맡기세요" 중 어느 쪽을 말할지 결정합니다.

포트 번호: 애플리케이션이 연결을 공유하는 방법

여러분의 기기는 하나의 IP 주소를 갖지만, 수십 개의 애플리케이션이 동시에 네트워크를 사용하려 합니다. 수신 데이터는 어떻게 올바른 애플리케이션을 찾아갈까요?

포트 번호입니다. 모든 전송 계층 연결은 네 가지로 식별됩니다: 출발지 IP, 출발지 포트, 목적지 IP, 목적지 포트. 데이터가 도착하면 전송 계층은 목적지 포트를 확인하고 해당 포트에서 수신 대기 중인 애플리케이션에 데이터를 전달합니다.

포트 번호는 16비트 정수로, 0부터 65535까지입니다. 범위는 중요합니다:

  • 0–1023: 잘 알려진 포트. HTTP는 80번, HTTPS는 443번, SSH는 22번을 사용합니다. 표준 서비스를 위해 예약되어 있습니다.
  • 1024–49151: 등록된 포트. 애플리케이션이 IANA에 이 범위의 포트를 신청할 수 있습니다.
  • 49152–65535: 임시 포트. 브라우저가 웹 서버에 접속할 때, 이 범위에서 임의의 포트를 반환 주소로 선택합니다.

웹 사이트에 접속할 때, 대화는 이런 식으로 이루어집니다: 여러분의 기기 52847번 포트가 서버의 443번 포트와 대화합니다. 양쪽의 전송 계층은 이 네 가지 숫자를 사용해 데이터를 올바른 애플리케이션으로 라우팅합니다.

TCP: 신뢰할 수 있는 전달의 약속

TCP는 약속을 합니다. 애플리케이션이 TCP를 통해 데이터를 전송하면, 이 프로토콜은 보장합니다: 모든 바이트가 올바른 순서로 정확히 한 번 도착할 것이라고.

이 약속을 지키려면 여러 메커니즘이 필요합니다:

먼저 연결을 수립합니다. 데이터가 흐르기 전에 TCP는 3방향 핸드셰이크를 수행합니다. 여러분의 기기가 SYN(동기화)을 보냅니다. 서버는 SYN-ACK(동기화-확인)으로 응답합니다. 여러분의 기기는 ACK(확인)으로 답합니다.

왜 세 단계일까요? 양쪽 모두 상대방이 송신과 수신 모두 가능하다는 것을 확인해야 하기 때문입니다. 첫 번째 SYN은 여러분이 전송할 수 있음을 증명합니다. SYN-ACK는 서버가 전송할 수 있고 여러분의 메시지를 받았음을 증명합니다. 마지막 ACK는 여러분이 서버의 메시지를 받았음을 증명합니다. 두 단계라면 한쪽 방향이 확인되지 않은 채로 남습니다.

모든 바이트에 번호를 부여합니다. TCP는 스트림에서 각 바이트가 정확히 어디에 속하는지 추적하기 위해 일련 번호를 할당합니다. 데이터가 도착하면, 수신 측은 패킷이 순서에 맞지 않게 도착하더라도 정확히 어디에 놓아야 할지 압니다.

수신을 확인합니다. 수신 측은 송신 측에게 무엇을 받았는지 알립니다. 확인 응답이 돌아오지 않으면 송신 측은 데이터가 손실됐다고 판단하고 재전송합니다.

속도를 조절합니다. TCP는 수신 측이나 네트워크를 과부하시키지 않기 위해 두 가지 메커니즘을 사용합니다:

  • 흐름 제어: 수신 측은 윈도우—사용 가능한 버퍼 공간이 얼마나 되는지—를 알립니다. 송신 측은 이를 초과하지 않습니다. 수신 측이 "이 정도는 처리할 수 있지만 그 이상은 안 됩니다"라고 말하는 것입니다.

  • 혼잡 제어: 송신 측은 네트워크 혼잡의 징후(패킷 손실, 지연 증가)를 모니터링하고 네트워크가 힘들어할 때 속도를 줄입니다. 이를 통해 TCP는 나쁜 상황을 더 나쁘게 만들지 않습니다.

이러한 보장의 대가는 오버헤드입니다. 연결 수립에는 시간이 걸립니다. 확인 응답은 지연을 추가합니다. 재전송은 전달을 지연시킵니다. 신뢰성이 필요한 애플리케이션에게는 이 비용을 지불할 가치가 있습니다.

UDP: 안전보다 속도

UDP는 데이터를 보내고 끝입니다.

연결 수립 없음. 확인 응답 없음. 재전송 없음. 순서 보장 없음. 혼잡 제어 없음. UDP는 데이터를 최소한의 헤더(출발지 포트, 목적지 포트, 길이, 체크섬)로 감싸고 네트워크 계층에 넘깁니다.

어떤 애플리케이션이 실제로 무엇을 필요로 하는지 생각해보기 전까지는 무모해 보입니다.

화상 회의는 TCP의 신뢰성을 원하지 않습니다. 20밀리초 분량의 영상을 담은 패킷이 손실된다면, 마지막으로 바라는 것은 TCP가 재전송하는 동안 대화를 멈추는 것입니다. 재전송된 패킷이 도착할 때쯤이면 그 순간은 이미 지나갔습니다. 프레임을 잃더라도 대화를 계속 이어가는 것이 낫습니다.

온라인 게임도 같은 제약에 직면합니다. 플레이어의 위치를 담은 패킷이 손실된다면, 이전 위치가 필요한 게 아닙니다—다음 업데이트가 필요합니다. TCP는 손실된 패킷을 기다리며 모든 것을 멈춥니다. UDP는 그것을 버리고 계속 진행할 수 있게 합니다.

DNS는 쿼리가 작고 빠르기 때문에 UDP를 사용합니다. TCP의 연결 수립 오버헤드가 실제 작업보다 더 클 것입니다. DNS 쿼리가 손실되면 그냥 다시 보내면 됩니다.

UDP를 사용하는 애플리케이션은 가끔의 손실을 감수하거나, 자신의 필요에 맞게 조정된 자체 신뢰성 메커니즘을 구현합니다—필요한 것은 취하고 불필요한 것은 버립니다.

세그멘테이션: 데이터를 조각으로 나누기

네트워크에는 크기 제한이 있습니다. 이더넷은 일반적으로 패킷을 1500바이트로 제한합니다. 하지만 애플리케이션은 훨씬 더 큰 데이터—이미지, 파일, 동영상 스트림—를 다룹니다.

전송 계층은 세그멘테이션을 통해 이를 처리합니다. TCP는 애플리케이션 데이터를 네트워크가 전달할 수 있을 만큼 작은 세그먼트로 나눕니다. 각 세그먼트는 수신 TCP가 순서대로 재조립할 수 있도록 일련 번호가 담긴 헤더를 받습니다.

UDP는 이를 다르게 처리합니다: 각 데이터그램은 독립적입니다. 애플리케이션이 하나의 패킷에 맞지 않는 데이터를 보내면 네트워크 계층이 이를 단편화합니다. UDP는 조각들을 추적하거나 모두 도착한다고 보장하지 않습니다.

슬라이딩 윈도우

TCP의 흐름 제어는 우아합니다. 수신 측은 수신 데이터를 위한 버퍼를 유지하고 송신 측에 알립니다: "내 윈도우는 X바이트입니다." 송신 측은 최대 X바이트를 전송 중—전송됐지만 아직 확인되지 않은—상태로 유지할 수 있습니다.

수신 애플리케이션이 버퍼에서 데이터를 읽으면 공간이 생깁니다. 수신 측은 더 큰 윈도우를 알립니다. 송신 측은 더 많이 보냅니다.

수신 측의 버퍼가 가득 차면—애플리케이션이 충분히 빠르게 읽지 않는 경우—윈도우는 0으로 줄어듭니다. 송신 측은 멈춥니다. 공간이 생기면 전송이 재개됩니다.

별도의 중재자 없이 두 기기가 속도를 조율합니다. 수신 측이 처리 가능한 양을 알리고, 송신 측이 그 한계를 존중합니다. 대화는 느린 쪽이 감당할 수 있는 속도로 흐릅니다.

이 계층이 존재하는 이유

전송 계층은 인터넷을 형성한 원칙을 구현합니다: 네트워크는 단순하게, 복잡성은 가장자리로.

라우터는 연결을 추적하지 않습니다. 손실된 패킷을 재전송하지 않습니다. 흐름 제어를 관리하지 않습니다. 목적지 주소를 기반으로 패킷을 전달할 뿐입니다. 이는 라우터를 빠르고 단순하게 유지합니다.

정교한 동작—신뢰할 수 있는 전달, 혼잡 관리, 다중화—은 엔드포인트에서, 전송 계층에서 이루어집니다. 여러분의 기기와 서버가 대화를 조율하고, 손실에서 복구하며, 네트워크 상황에 적응합니다. 그 사이의 라우터는 아무것도 모른 채 제 할 일만 합니다.

네트워크는 최선 노력 전달을 제공합니다. 전송 계층은 그 기반 위에 애플리케이션이 필요로 하는 보장을 구축합니다.

전송 계층에 관한 자주 묻는 질문

왜 어떤 애플리케이션은 TCP를 사용하고 다른 것은 UDP를 사용하나요?

선택은 신뢰성과 적시성 중 무엇이 더 중요한지에 달려 있습니다. 손실되거나 순서가 바뀐 데이터를 허용할 수 없는 애플리케이션—파일 전송, 웹 페이지, 이메일—은 TCP를 사용합니다. 완전성보다 적시성이 더 중요한 애플리케이션—실시간 동영상, 음성 통화, 게임—은 UDP를 사용하고 필요한 신뢰성은 스스로 처리합니다.

TCP 연결의 양쪽 모두 데이터를 전송해야 하면 어떻게 되나요?

TCP 연결은 전이중(full-duplex) 방식입니다—데이터가 양방향으로 동시에 흐릅니다. 각 방향은 자체적인 일련 번호, 확인 응답, 흐름 제어 윈도우를 갖습니다. 단일 TCP 연결이 한 방향으로는 HTTP 요청을, 다른 방향으로는 응답을 동시에 전달할 수 있습니다.

내 기기에서 사용 중인 포트를 볼 수 있나요?

네. Unix 계열 시스템에서는 netstat -an 또는 ss -tuln으로 활성 연결과 수신 대기 중인 포트를 확인할 수 있습니다. Windows에서는 netstat -an이 비슷하게 작동합니다. 어떤 로컬 포트가 연결을 기다리고 있는지, 그리고 여러분의 기기가 어떤 원격 주소와 연결되어 있는지 볼 수 있습니다.

이 페이지가 도움이 되었나요?

😔
🤨
😃