TIME-WAIT 소켓이 쌓이는 이유: TCP의 2×MSL과 리눅스의 60초, tcp_fin_timeout의 오해
TCP에서 먼저 연결을 닫은 쪽이 TIME-WAIT에 머무는 이유, RFC 9293의 2×MSL과 리눅스의 60초 고정값을 정리했습니다. tcp_fin_timeout이 실제로 정하는 것과 tcp_tw_reuse의 기본값도 다룹니다.
소켓 목록에 TIME-WAIT가 수천 개씩 보이면 어딘가 새는 것 같지만, 대부분은 TCP가 명세대로 동작한 결과입니다. 규칙은 TCP 표준인 RFC 9293에 있고, 실제로 얼마나 기다릴지는 구현이 정합니다. 아래의 리눅스 동작은 커널 v7.2 소스를, 기본값은 2026년 10월 6일에 확인한 커널 문서의 ip-sysctl 페이지(버전 표기 없음)를 기준으로 했습니다.
먼저 닫은 쪽에 남는다
정상 종료에서는 먼저 닫는 쪽 A가 FIN을 보내고 그 ACK를 받습니다. 이어서 상대 B가 FIN을 보내면 A는 ACK로 답하고 TIME-WAIT에 들어갑니다. B는 그 마지막 ACK를 받는 즉시 CLOSED가 됩니다. RFC 9293은 능동적으로 닫은 쪽이 TIME-WAIT에 2×MSL 동안 머물러야 한다(MUST)고 정합니다.
그림: 양쪽이 동시에 닫지 않는 일반적인 FIN 종료입니다. 시간은 위에서 아래로 흐릅니다.
그래서 양쪽이 동시에 닫지 않는 일반적인 FIN 종료라면, TIME-WAIT 소켓 하나가 먼저 닫은 쪽에 남습니다. 서버인지 클라이언트인지는 상관이 없습니다.
왜 기다릴까
RFC 9293이 드는 목적은 두 가지입니다. 하나는 상대가 자기 FIN에 대한 ACK를 받았다고 확신할 때까지 기다리는 것입니다. 마지막 ACK가 사라지면 상대가 FIN을 다시 보내고, TIME-WAIT 쪽은 다시 ACK를 보낸 뒤 타이머를 처음부터 셉니다. 다른 하나는 이전 연결에서 늦게 도착한 세그먼트가 새 연결에 섞이지 않게 하는 것입니다. 연결은 양 끝의 주소와 포트 조합으로 식별되므로, 같은 조합으로 곧바로 새 연결을 열면 옛 세그먼트가 끼어들 수 있습니다.
MSL(Maximum Segment Lifetime)은 세그먼트가 네트워크에 존재할 수 있는 시간이고, RFC 9293은 이를 2분으로 둡니다. 2×MSL은 4분입니다. 명세는 이 값이 공학적 선택이라 바뀔 수 있다고도 적습니다.
리눅스는 60초로 고정한다
리눅스 v7.2의 include/net/tcp.h는 TCP_TIMEWAIT_LEN을 60*HZ(약 60초)로 정의하고, net/ipv4/tcp_minisocks.c의 tcp_time_wait()는 TIME-WAIT에 들어가는 소켓의 대기 시간을 이 상수로 정합니다. 명세의 4분보다 짧고, ip-sysctl 문서에서 TIME-WAIT를 언급하는 항목 중 이 길이를 바꾸는 것은 없습니다.
헷갈리기 쉬운 것이 tcp_fin_timeout입니다. 문서에 따르면 이 값은 어떤 애플리케이션도 참조하지 않는(orphaned) 연결이 FIN_WAIT_2에 머무는 시간이고, 기본값이 60초라 TIME-WAIT 길이와 같습니다. 하지만 tcp_time_wait()는 TIME-WAIT 상태라면 넘겨받은 값과 관계없이 TCP_TIMEWAIT_LEN을 씁니다. 그래서 tcp_fin_timeout을 줄여도 TIME-WAIT는 짧아지지 않습니다.
tcp_tw_reuse는 프로토콜상 안전할 때 TIME-WAIT 소켓을 새 연결에 다시 쓰게 하는 설정입니다. 0은 끔, 1은 전체, 2는 루프백 트래픽만이며 기본값은 2입니다. 문서는 기술 전문가의 조언 없이 바꾸지 말라고 적고 있습니다.
포트는 몇 개나 버틸까
클라이언트가 먼저 닫으면서 같은 목적지로 짧은 연결을 계속 열면 임시 포트 풀이 병목이 될 수 있습니다. ip_local_port_range의 기본값은 32768부터 60999까지, 28,232개입니다. 포트 하나가 60초씩 묶이므로 28,232 ÷ 60, 초당 약 470개가 정상 상태에서 이어 갈 수 있는 신규 연결 수의 어림값입니다. TCP 자체의 한계가 아니라 다음 가정 아래의 계산입니다. 출발지 IP와 네트워크 네임스페이스가 하나, 포트 범위는 기본값 그대로, 예약 포트 없음, 커널의 일반적인 자동 포트 할당, 목적지 주소와 포트가 하나로 고정, 적용되는 TIME-WAIT 재사용 없음.
이런 패턴이라면 sysctl을 건드리기 전에 연결을 재사용해서 닫는 횟수 자체를 줄일 수 있는지부터 보는 편이 낫습니다.
참고한 문서
- RFC 9293 Transmission Control Protocol (TCP): 3.3.2, 3.4.1, 3.4.2, 3.6, 3.6.1, 3.10.7.4절
- 리눅스 v7.2
include/net/tcp.h:TCP_TIMEWAIT_LEN - 리눅스 v7.2
net/ipv4/tcp_minisocks.c:tcp_time_wait() - 리눅스 커널 문서 IP Sysctl:
tcp_fin_timeout,tcp_tw_reuse,ip_local_port_range,ip_local_reserved_ports
링크와 내용은 2026년 10월 6일에 확인했습니다.