테마
TCP 연결 관리
TCP의 핵심 특성: 연결 지향(Connection Oriented)
TCP(Transmission Control Protocol)는 인터넷에서 가장 중요한 L4 프로토콜이다. TCP의 핵심 키워드는 **연결(Connection)**이다. TCP 연결은 물리적 회선이 아닌 논리적(Virtual) 개념이며, Virtual Circuit이라고도 부른다.
TCP 연결을 전화 통화에 비유하면 이해하기 쉽다.
3-Way Handshake: 연결 수립
TCP 연결은 3-Way Handshake라는 3단계 절차를 통해 수립된다.
단계별 설명
- SYN: 클라이언트가 서버에게 연결을 요청한다. 자신의 시퀀스 번호(seq=1000)를 전달한다.
- SYN + ACK: 서버가 연결을 수락하면서 자신의 시퀀스 번호(seq=4000)를 전달하고, 클라이언트의 시퀀스에 대한 확인(ack=1001)을 보낸다.
- ACK: 클라이언트가 서버의 시퀀스에 대한 확인(ack=4001)을 보낸다.
이 과정에서 양측은 시퀀스 번호와 **정책(MSS 등)**을 교환한다. 서로의 MSS를 확인하여 더 작은 값에 맞추어 통신한다.
4-Way Handshake: 연결 종료
연결을 끊을 때는 4-Way Handshake를 사용한다. 연결보다 종료가 더 복잡하다.
왜 4단계인가?
3-Way Handshake는 한쪽이 "연결하자"고 하면 바로 수락하면 되지만, 종료 시에는 서버가 아직 보내야 할 데이터가 남아 있을 수 있다. 그래서 "끊자" → "알았어(일단 확인)" → "(준비 완료) 나도 끊자" → "확인"의 4단계를 거친다.
TIME_WAIT 상태의 중요성
연결을 먼저 끊자고 한 쪽에서 TIME_WAIT 상태가 발생한다. 이 상태에서는 일정 시간(통상 2MSL, 약 60~120초) 동안 소켓 자원이 회수되지 않는다.
서버 개발 시 주의사항
소켓은 유한한 자원이다. 서버가 먼저 연결을 끊는 패턴이 반복되면 서버 쪽에 TIME_WAIT이 쌓일 수 있다. 수천 개의 연결을 처리하는 서버에서는 이 누적이 부담이 될 수 있다.
그래서 고동시성 서버에서는 보통 종료를 어느 쪽이 주도할지 프로토콜 차원에서 설계한다. 클라이언트가 종료를 주도하도록 하면 서버의 TIME_WAIT 부담을 줄이는 데 도움이 될 수 있다.
- 서버 입장: Passive Close (클라이언트의 종료 요청을 받아 처리)
- 클라이언트 입장: Active Close (자신이 먼저 종료를 요청)
TCP 상태 전이 다이어그램
TCP 연결은 상태(State) 머신으로 관리된다. 연결의 수명 주기를 상태 전이로 표현하면 다음과 같다.
연결의 본질: 논리적 합의
TCP 연결은 물리적 회선이 아니라 양쪽 엔드포인트의 주관적 판단이다. 실제로 파일을 다운로드하는 도중 랜 케이블을 뽑아도 TCP 연결은 즉시 끊기지 않는다. 물리적 연결(L1)이 끊어져도 논리적 연결(L4)은 일정 시간 유지된다.
- 케이블을 뽑으면 L1은 즉시 끊긴다 (Link Down)
- 하지만 L4 TCP 연결은 재전송 타이머가 만료될 때까지 유지된다
- 타이머 만료 후에야 OS가 연결이 끊어졌다고 판단한다
- 케이블을 다시 꽂으면 통신이 재개될 수도 있다
TCP 연결은 보안을 보장하지 않는다. 기밀성, 무결성, 가용성 모두 TCP만으로는 보장되지 않는다. 이를 위해 TLS 같은 상위 보안 계층이 필요하다.
핵심 정리
- 3-Way Handshake: SYN → SYN+ACK → ACK (연결 수립)
- 4-Way Handshake: FIN → ACK → FIN → ACK (연결 종료)
- TIME_WAIT는 Active Close 측에서 발생하며, 소켓 자원을 일정 시간 점유한다
- 서버는 누가 Active Close를 맡을지 설계해야 TIME_WAIT 누적을 관리하기 쉽다
- TCP 연결은 **논리적(Virtual)**이며, 물리적 연결과 독립적이다
- 연결의 수립과 종료는 상태 전이로 표현된다