업데이트됨 1개월 전
모든 대화에는 반송 주소가 필요합니다.
브라우저가 서버에 연결할 때, 서버는 응답을 어디로 보낼지 알아야 합니다. IP 주소는 어떤 컴퓨터인지 알려주지만, 그것만으로는 부족합니다. 탭을 50개 열어놓고 각각 다른 서버(또는 같은 서버)와 통신하고 있을 수 있으니까요. 서버는 컴퓨터 전체가 아니라 특정 대화에 도달해야 합니다.
그것이 바로 임시 포트가 하는 일입니다. 컴퓨터가 연결을 시작할 때마다, 운영체제는 그 대화에 임시 포트 번호를 할당합니다. 완전한 주소는 여러분의 IP 주소와 임시 포트의 조합이 됩니다. 서버가 응답할 때, 패킷을 그 특정 포트로 돌려보내고, 운영체제는 이를 올바른 애플리케이션으로 라우팅합니다.
임시 포트의 작동 방식
임시(Ephemeral)란 수명이 짧다는 뜻입니다. 이 포트들은 연결이 유지되는 동안에만 존재합니다. 브라우저 탭을 닫으면, 그 탭의 연결에 할당되었던 임시 포트는 결국 사용 가능한 풀로 돌아갑니다.
IANA는 공식적으로 49152-65535 포트를 동적 범위로 지정했습니다. 임시 할당을 위해 사용 가능한 16,384개의 포트입니다. 하지만 운영체제들은 역사적으로 각자의 방식을 따라왔습니다:
- Linux: 32768-60999 (28,232개 포트)
- Windows (Vista 이후): 49152-65535
- macOS/FreeBSD: 49152-65535
- 구형 Windows: 1024-5000 (고통스러울 만큼 적은 3,977개 포트)
이러한 차이는 문제를 해결할 때 중요합니다. 40000번대의 포트 번호는 시스템마다 다른 의미를 가집니다. Linux에서는 임시 할당일 수 있지만, Windows에서는 설정된 서비스일 수 있습니다.
운영체제가 포트를 선택하는 방법
애플리케이션이 포트를 지정하지 않고 연결을 생성하면, 운영체제는 임시 범위에서 하나를 선택합니다. 현대 시스템은 순차적이 아닌 무작위 선택을 사용합니다. 예측 불가능성을 위한 것이기도 하지만, 주로 최근에 닫힌 연결과의 충돌을 피하기 위해서입니다.
여기서 흥미로운 점이 있습니다. TCP 연결이 종료된 후, 포트는 즉시 사용 가능해지지 않습니다. TIME_WAIT라는 상태에 들어가며, 일반적으로 60~240초 동안 지속됩니다. 시스템이 종료된 연결을 잠시 유지하는 이유는 유령 때문입니다. 이미 끝난 대화에서 늦게 도착하는 패킷들이죠. 포트가 즉시 재사용된다면, 이전 연결에서 지연된 패킷이 새 연결에 속하는 것으로 잘못 해석될 수 있습니다.
포트 선택 알고리즘은 TIME_WAIT를 고려합니다. 사용되지 않으면서 유령도 기다리지 않는 포트를 찾는 것입니다. 평상시에는 이 과정이 눈에 띄지 않게 돌아갑니다. 부하가 높아지면 제약 요소가 됩니다.
방화벽과 임시 포트 범위
상태 저장 방화벽은 연결을 추적합니다. 컴퓨터가 어떤 서버의 443 포트로 연결을 시작하면, 방화벽은 이를 기록하고 서버의 응답 패킷이 여러분의 임시 포트에 도달하도록 자동으로 허용합니다. 간단하죠.
상태 비저장 방화벽과 기본 ACL은 연결을 추적하지 않습니다. 임시 포트 범위로 들어오는 인바운드 트래픽을 명시적으로 허용하는 규칙이 필요합니다. "32768-65535 포트로의 인바운드를 허용"한다고 하면 수천 개의 문을 활짝 여는 것처럼 보여 불안하게 느껴질 수 있습니다. 하지만 실제 보호는 운영체제가 담당합니다. 방화벽이 무엇을 허용하든, 활성 연결과 일치하지 않는 패킷은 운영체제가 거부합니다.
NAT 장치는 또 다른 계층을 추가합니다. 내부 임시 포트와 변환을 위해 할당된 외부 포트 간의 매핑을 추적해야 합니다. 활성 연결마다 NAT 테이블의 항목 하나를 소비합니다. 트래픽이 많은 네트워크에서는 임시 포트가 고갈되기 전에 NAT 용량이 먼저 바닥날 수 있습니다.
포트 고갈
포트 고갈은 실제로 일어납니다. 16,000~28,000개의 임시 포트와 종료 후 각 포트를 수 분간 붙잡고 있는 TIME_WAIT 때문에, 수천 개의 단기 연결을 만들어내는 시스템은 포트가 바닥날 수 있습니다.
숫자는 냉혹합니다. TIME_WAIT가 120초 지속되고 초당 200개의 연결을 열고 있다면, 대기 중인 연결만을 위해 24,000개의 포트가 필요합니다. 여기에 활성 연결까지 더하면 대부분의 기본 범위를 가볍게 초과합니다.
증상은 갑자기 나타납니다. 애플리케이션이 연결에 실패합니다. 오류 로그에 바인딩 실패가 가득 찹니다. 초당 150개에서는 멀쩡히 돌아가던 시스템이 200개에서는 멈춰버립니다.
해결책:
- 범위 확장: Linux의 기본값인 32768-60999는 IANA의 권고보다 훨씬 넉넉한 여유를 제공합니다
- 연결 풀링: 각 요청마다 새 연결을 만드는 대신 연결을 재사용합니다
- 여러 IP 주소: 임시 포트는 IP별로 할당되므로, 주소를 추가하면 용량이 배가됩니다
- TIME_WAIT 단축: 가능하지만 위험합니다. 유령들이 존재하는 데는 이유가 있습니다
임시 포트에 관한 자주 묻는 질문
애플리케이션이 왜 아웃바운드 연결에 자체 포트를 지정하지 않나요?
지정할 수 있습니다. 하지만 그럴 이유가 없습니다. 임시 포트는 그냥 반송 주소일 뿐입니다. 서버는 포트 번호 자체에는 관심이 없고, 응답이 올바른 곳에 도달하는지만 신경 씁니다. 운영체제에 포트 선택을 맡기면 충돌을 피할 수 있고 애플리케이션 코드도 단순해집니다.
현재 사용 중인 임시 포트를 확인할 수 있나요?
네. Linux에서는 ss -tuln 또는 netstat -tuln 명령어로 포트 할당 정보와 함께 활성 연결을 확인할 수 있습니다. Windows에서는 netstat -ano가 유사한 정보를 제공합니다. 아웃바운드 연결의 로컬 주소 열에서 임시 포트를 찾아볼 수 있습니다.
TIME_WAIT가 왜 그렇게 긴가요?
TCP의 최대 세그먼트 수명(MSL)은 2분으로 정의됩니다. TIME_WAIT는 이전 연결에서 지연된 패킷이 완전히 사라졌는지 확인하기 위해 2×MSL 동안 지속됩니다. 이를 단축하면 패킷이 잘못 전달될 위험이 있습니다. 물론 실제로 현대 네트워크에서 2분에 가까운 지연은 거의 발생하지 않습니다.
UDP도 임시 포트를 사용하나요?
네. 특정 포트에 바인딩하지 않은 UDP 애플리케이션은 TCP와 마찬가지로 임시 포트를 받습니다. 하지만 UDP에는 TIME_WAIT에 해당하는 개념이 없습니다. 애플리케이션이 소켓을 닫으면 포트는 즉시 사용 가능해집니다.
이 페이지가 도움이 되었나요?