문서의 각 단락이 어느 리비전에서 마지막으로 수정되었는지 확인할 수 있습니다. 왼쪽의 정보 칩을 통해 작성자와 수정 시점을 파악하세요.

4-Way Handshake | |
이름 | 4-Way Handshake |
목적 | TCP 연결 종료 절차 |
단계 수 | 4단계 |
관련 플래그 | FIN, ACK |
양방향 종료 | 각 방향의 연결을 독립적으로 종료 |
상세 절차 및 설명 | |
1단계 (FIN 전송) | 클라이언트가 서버에 FIN 플래그를 설정한 세그먼트 전송 |
2단계 (ACK 응답) | 서버가 FIN에 대한 ACK 응답 전송 (클라이언트→서버 방향 연결 종료) |
3단계 (서버 FIN 전송) | 서버가 데이터 전송 완료 후, 클라이언트에게 FIN 플래그 설정 세그먼트 전송 |
4단계 (최종 ACK) | 클라이언트가 서버의 FIN에 대한 ACK 응답 전송 (서버→클라이언트 방향 연결 종료) |
TIME_WAIT 상태 | 클라이언트가 최종 ACK 후 일정 시간(2*MSL) 대기 |
MSL (Maximum Segment Lifetime) | 세그먼트가 네트워크에 존재할 수 있는 최대 시간 |
3-Way Handshake와 차이 | 연결 설정은 3단계, 종료는 4단계 (양방향 독립 종료 필요) |
반쪽 종료(Half-Close) | 한쪽 연결만 먼저 종료 가능한 상태 |
주요 용도 | 신뢰성 있는 TCP 연결의 정상적 종료 보장 |

TCP는 신뢰성 있는 연결 지향형 프로토콜이다. 이는 데이터를 전송하기 전에 송신자와 수신자 사이에 논리적인 연결을 먼저 설정하고, 전송이 완료된 후에는 이 연결을 정상적으로 종료해야 함을 의미한다.
연결 설정 과정은 3-Way Handshake로 알려져 있으며, 연결 종료 과정은 4-Way Handshake로 수행된다. 4-Way Handshake는 양방향 통신 연결을 안전하고 우아하게 해제하기 위한 표준 절차이다.
이 과정은 총 네 번의 패킷 교환으로 이루어지며, FIN과 ACK라는 두 가지 주요 TCP 플래그를 사용한다. 각 방향의 데이터 흐름이 독립적으로 종료되어야 하기 때문에, 연결 설정보다 단계가 하나 더 많다. 이를 통해 두 호스트 모두 데이터 전송이 완전히 끝났음을 확인하고 자원을 안전하게 반환할 수 있다.

TCP 연결은 신뢰성 있는 양방향 통신 채널을 확립하기 위한 절차이다. 이 과정은 두 호스트 간에 연결 매개변수를 협상하고, 초기 시퀀스 번호를 교환하며, 양측이 통신할 준비가 되었음을 확인하는 것을 목표로 한다.
연결 설정의 핵심은 3-Way Handshake이다. 이 과정은 세 단계의 패킷 교환으로 이루어진다. 먼저, 연결을 시작하는 클라이언트는 SYN 플래그가 설정된 패킷을 서버로 보낸다. 이 패킷에는 클라이언트의 초기 시퀀스 번호가 포함된다. 서버는 이에 응답하여 SYN과 ACK 플래그가 모두 설정된 패킷을 보낸다. 이 패킷은 클라이언트의 SYN을 수신했음을 확인(ACK)하면서, 서버 자신의 초기 시퀀스 번호를 담은 SYN을 함께 전송한다. 마지막으로 클라이언트는 서버의 SYN에 대한 확인 응답으로 ACK 패킷을 보낸다. 이 세 번째 패킷이 전송되면 연결이 성립되고, 데이터 전송이 시작될 수 있다.
3-Way Handshake는 다음과 같은 기술적 필요성을 해결한다.
* 초기 시퀀스 번호 동기화: 양측이 데이터 스트림의 시작점을 일치시키기 위해 반드시 필요한 과정이다.
* 양측 준비 상태 확인: 클라이언트와 서버 모두 연결을 수용하고 데이터를 송수신할 준비가 되었음을 보장한다.
* 이중 통신 채널 확립: 정방향(클라이언트→서버)과 역방향(서버→클라이언트)의 두 개의 논리적 채널을 독립적으로 설정한다.
이 과정은 신뢰성 없는 IP 네트워크 위에서 신뢰성 있는 연결 지향형 통신을 제공하는 TCP의 핵심 메커니즘 중 하나이다.
TCP는 연결 지향형 프로토콜이다. 이는 두 호스트 간에 데이터를 교환하기 전에 먼저 논리적인 연결을 수립해야 함을 의미한다. 연결 설정 과정은 통신을 시작하는 양측이 서로의 존재를 확인하고, 초기 시퀀스 번호를 교환하며, 다양한 통신 매개변수를 협상하는 중요한 절차이다.
연결 설정이 없으면, 데이터를 보내는 쪽은 상대방이 데이터를 받을 준비가 되었는지, 또는 상대방이 아예 존재하는지조차 알 수 없다. 이는 신뢰성 없는 통신으로 이어질 수 있다. 예를 들어, 상대방 호스트가 다운되었거나 네트워크 경로에 문제가 있는 상황에서 데이터를 무작정 전송하는 것은 자원 낭비이다. 따라서 3-Way Handshake라는 신뢰할 수 있는 절차를 통해 상호 합의된 연결을 먼저 설정하는 것이 필수적이다.
이 과정은 단순한 인증을 넘어, 혼잡 제어와 흐름 제어를 위한 초기 정보를 교환하는 기반이 된다. 양측이 교환한 초기 시퀀스 번호는 이후 전송되는 모든 데이터 바이트에 대한 순서와 정확성을 보장하는 기준점이 된다. 결국, 연결 설정은 신뢰성 있는 전송이라는 TCP의 근본적인 목표를 달성하기 위한 첫 번째이자 가장 중요한 단계이다.
TCP 연결 설정은 3-Way Handshake라는 과정을 통해 이루어진다. 이 과정은 통신을 시작하기 전에 양쪽 호스트가 서로의 존재를 확인하고 초기 순서 번호를 교환하여 신뢰성 있는 데이터 전송 채널을 확립하는 것을 목표로 한다.
과정은 다음과 같은 세 단계로 구성된다.
1. SYN (Synchronize): 연결을 시작하려는 클라이언트가 서버에게 SYN 플래그가 설정된 패킷을 보낸다. 이 패킷에는 클라이언트의 초기 시퀀스 번호가 포함된다.
2. SYN-ACK (Synchronize-Acknowledgment): 서버는 클라이언트의 SYN 패킷을 수신하면, SYN과 ACK 플래그가 모두 설정된 패킷으로 응답한다. 이 패킷은 서버의 초기 시퀀스 번호와 함께, 클라이언트의 시퀀스 번호에 1을 더한 값을 확인 응답 번호로 담아 클라이언트의 요청을 정상적으로 받았음을 알린다.
3. ACK (Acknowledgment): 마지막으로 클라이언트는 서버로부터 받은 SYN-ACK 패킷에 대한 응답으로 ACK 패킷을 보낸다. 이 패킷의 확인 응답 번호는 서버의 시퀀스 번호에 1을 더한 값이다.
이 세 번째 ACK 패킷의 전송이 완료되면, 양측 모두 연결이 성립되었다고 판단하고 데이터 전송 단계로 진입한다. 이 과정은 신뢰성 없는 IP 네트워크 상에서 두 지점 간에 논리적인 연결을 안전하게 수립하는 핵심 메커니즘이다.

4-Way Handshake는 TCP 연결을 정상적으로 종료하기 위해 사용되는 네 단계의 패킷 교환 절차이다. 이 과정은 통신을 종료하려는 양측이 서로의 종료 의사를 확인하고, 모든 데이터가 안전하게 전송되었음을 보장하는 데 목적이 있다. 연결 설정 시 사용되는 3-Way Handshake가 신뢰성 있는 통신 채널을 구축하는 것이라면, 4-Way Handshake는 그 채널을 안전하게 해제하는 절차에 해당한다.
3-Way Handshake와의 핵심적인 차이점은 연결 종료가 단방향이 아닌 양방향으로 이루어진다는 점이다. TCP 연결은 전이중 통신 방식으로, 클라이언트와 서버 모두 독립적인 송신 및 수신 채널을 가진다. 따라서 한쪽의 데이터 전송이 끝났다고 해도 반대쪽에서 아직 보낼 데이터가 남아 있을 수 있다. 4-Way Handshake는 이 양방향 채널을 각각 독립적으로 닫기 위해 설계되었다. 클라이언트가 먼저 종료 의사(FIN 플래그)를 보내고 서버가 이를 확인(ACK 플래그)한 후, 서버도 자신의 데이터 전송이 끝나면 별도의 FIN 패킷을 보내는 두 단계의 FIN-ACK 교환이 필요하게 된다.
이 절차의 필요성은 데이터의 신뢰성과 연결 상태의 명확한 동기화에서 비롯된다. 갑작스러운 연결 단절은 전송 중이던 데이터의 손실을 초래할 수 있다. 4-Way Handshake를 통해 각 측은 상대방의 FIN 패킷에 대해 ACK로 응답함으로써 "종료 요청을 받았음"을 알린다. 이는 잠재적으로 네트워크상에 지연되어 도착할 수 있는 마지막 데이터 패킷을 수신할 시간을 벌어주는 역할도 한다. 결과적으로 이 과정은 두 호스트가 연결이 완전히 종료되었다는 상태에 동시에 도달하도록 보장한다.
4-Way Handshake는 TCP 연결을 정상적으로 종료하기 위해 사용되는 네 단계의 패킷 교환 절차이다. 이 과정은 통신을 종료하려는 양측이 서로의 종료 의사를 확인하고, 모든 데이터가 안전하게 전송되었음을 보장하는 것을 목적으로 한다.
3-Way Handshake가 연결을 설정하는 절차라면, 4-Way Handshake는 그 반대로 연결을 해제하는 절차이다. 연결 종료는 한쪽이 먼저 종료를 요청하고, 다른 쪽이 이를 확인한 후 자신의 종료 요청을 보내는 비대칭적인 과정이기 때문에 기본적으로 네 번의 핸드셰이크가 필요하다. 이는 양방향 통신 채널 각각을 독립적으로 닫아야 하기 때문이다.
주요 목적은 신뢰성 있는 연결 종료를 보장하는 것이다. 이 과정을 통해 네트워크상에 지연되어 도착할 수 있는 이전 연결의 패킷이 새로운 연결과 혼동되지 않도록 하고, 양측 모두 연결이 완전히 종료되었다는 사실을 인지할 수 있게 한다. 이는 데이터 무결성과 신뢰성을 핵심 원칙으로 하는 TCP의 특성을 반영한다.
3-Way Handshake는 TCP 연결을 설정하는 과정이며, 4-Way Handshake는 연결을 종료하는 과정이다. 이는 두 핸드셰이크의 근본적인 목적 차이를 보여준다. 연결 설정은 통신 채널을 열고 양방향 데이터 전송을 가능하게 하는 반면, 연결 종료는 열려 있는 채널을 안전하게 닫고 모든 데이터가 손실 없이 전달되었음을 보장하는 데 목적이 있다.
주요 차이점은 패킷 교환 횟수와 사용되는 TCP 플래그에 있다. 3-Way Handshake는 SYN과 ACK 플래그를 사용한 세 번의 패킷 교환으로 구성된다. 반면, 4-Way Handshake는 FIN과 ACK 플래그를 사용하며, 일반적으로 네 번의 패킷 교환이 필요하다. 이는 연결이 양방향으로 독립적으로 닫힐 수 있기 때문이다. 한쪽이 데이터 전송을 완료했다고 해서 반대쪽도 즉시 완료되었다는 보장이 없으므로, 각 방향에 대해 별도의 FIN-ACK 교환이 필요하다.
과정의 비대칭성도 중요한 차이점이다. 3-Way Handshake는 상대적으로 대칭적인 과정으로, 한쪽이 SYN을 보내면 다른 쪽이 SYN-ACK로 응답하고, 최종 ACK로 완료된다. 그러나 4-Way Handshake는 비대칭적일 수 있다. 먼저 연결 종료를 시작하는 측(주로 클라이언트)이 FIN을 보내면, 수신 측(서버)은 즉시 ACK로 응답하지만, 자신의 데이터 전송이 완료될 때까지 자신의 FIN 전송을 지연시킬 수 있다. 이로 인해 중간에 Half-Close 상태가 발생할 수 있다.
다음 표는 두 핸드셰이크의 핵심 차이를 요약한다.

4-Way Handshake는 TCP 연결을 양방향으로 안전하게 종료하기 위한 네 단계의 절차이다. 이 과정은 두 개의 FIN 패킷과 두 개의 ACK 패킷이 교환되며, 각 방향의 데이터 흐름을 독립적으로 닫는다.
단계 | 송신자 → 수신자 | 전송 패킷 | 주요 목적 |
|---|---|---|---|
1 | 클라이언트 → 서버 | FIN | 클라이언트의 데이터 전송 종료 선언 |
2 | 서버 → 클라이언트 | ACK | 1단계의 FIN 패킷에 대한 확인 응답 |
3 | 서버 → 클라이언트 | FIN | 서버의 데이터 전송 종료 선언 |
4 | 클라이언트 → 서버 | ACK | 3단계의 FIN 패킷에 대한 확인 응답 |
첫 번째 단계에서 연결 종료를 시작하는 호스트(일반적으로 클라이언트)는 상대 호스트(서버)에게 FIN 플래그가 설정된 세그먼트를 전송한다. 이는 송신 측의 데이터 전송이 끝났음을 알린다. 그러나 이 시점에서 수신 측은 아직 보낼 데이터가 남아 있을 수 있다. 두 번째 단계에서 수신 측은 이 FIN 패킷을 정상적으로 수신했음을 확인하기 위해 ACK 패킷으로 응답한다.
세 번째 단계는 수신 측이 자신의 데이터 전송도 완료되었을 때 수행된다. 수신 측은 자신도 더 이상 보낼 데이터가 없음을 알리기 위해 FIN 플래그가 설정된 세그먼트를 송신 측에게 보낸다. 마지막 네 번째 단계에서 최초의 송신 측은 이 FIN 패킷에 대한 ACK 패킷을 보냄으로써 전체 종료 절차를 완료한다. 최종 ACK를 보낸 호스트는 일정 시간 TIME_WAIT 상태를 유지한 후 연결 리소스를 완전히 해제한다[1].
TCP 연결은 양방향 통신 채널이다. 따라서 한쪽 방향의 연결만 종료하는 것이 가능하며, 이를 Half-Close라고 부른다. 4-Way Handshake의 첫 단계는 일반적으로 연결을 종료하려는 측(이 예시에서는 클라이언트)이 자신의 데이터 송신을 완료했음을 상대방(서버)에게 알리는 과정이다.
클라이언트는 애플리케이션 계층에서 연결 종료를 요청(예: close() 시스템 콜 호출)받으면, 전송 계층에서 TCP 세그먼트를 생성한다. 이 세그먼트의 TCP 헤더에는 컨트롤 플래그 중 FIN 비트가 1로 설정된다. FIN은 'Finish'의 약자로, 데이터 전송의 종료를 의미한다. 이 패킷을 서버로 전송함으로써, 클라이언트는 "더 이상 보낼 데이터가 없다"는 메시지를 전달한다.
이 단계 이후, 클라이언트는 FIN을 보낸 방향, 즉 클라이언트 → 서버 방향의 데이터 흐름은 종료된 상태가 된다. 그러나 서버 → 클라이언트 방향의 데이터 흐름은 아직 열려 있어, 서버가 아직 전송 중이거나 버퍼에 남아 있는 데이터를 클라이언트에게 보낼 수 있다. 이 상태가 바로 Half-Close 연결이다.
서버가 클라이언트의 FIN 패킷을 수신하면, 이는 클라이언트가 더 이상 보낼 데이터가 없음을 의미합니다. 서버는 이에 대한 확인 응답으로 ACK 패킷을 즉시 전송합니다. 이 ACK 패킷의 시퀀스 번호는 클라이언트의 FIN 패킷에 담긴 시퀀스 번호에 1을 더한 값으로 설정됩니다[2].
이 단계에서 서버는 클라이언트로의 데이터 전송 채널만 닫힌 상태입니다. 서버는 클라이언트의 FIN에 대한 ACK를 보낸 후에도 자신의 송신 버퍼에 남아 있는 데이터가 있다면 계속해서 클라이언트에게 전송할 수 있습니다. 이 상태를 Half-Close 연결이라고 부릅니다.
서버가 ACK를 보내는 주된 목적은 클라이언트의 연결 종료 요청을 정상적으로 수신했음을 알리는 것입니다. 이를 통해 클라이언트는 서버가 자신의 FIN을 받았다는 것을 확신하고, 더 이상 해당 연결로 데이터를 재전송하지 않아도 됩니다.
이 단계는 4-Way Handshake의 세 번째 단계로, 서버가 클라이언트에게 연결 종료를 시작한다는 신호를 보내는 단계이다. 서버는 자신의 데이터 전송이 완전히 끝나고 연결을 종료할 준비가 되었을 때, 클라이언트에게 FIN 플래그가 설정된 패킷을 전송한다.
이 FIN 패킷의 전송은 서버 측의 애플리케이션이 close() 시스템 콜을 호출한 결과로 발생한다. 서버는 이 패킷을 보내면서 자신의 송신 채널을 닫고, 더 이상 클라이언트에게 데이터를 보내지 않을 것임을 알린다. 그러나 이 시점에서 서버는 여전히 클라이언트로부터 오는 데이터를 수신할 수 있는 상태를 유지할 수 있다[3]] 연결이라고 함].
단계 | 송신자 | 수신자 | 전송 플래그 | 상태 변화 |
|---|---|---|---|---|
3단계 | 서버 | 클라이언트 | FIN | 서버: FIN_WAIT_2 → TIME_WAIT 준비 클라이언트: CLOSE_WAIT → LAST_ACK 준비 |
서버가 이 FIN 패킷을 보내기까지의 시간은 서버 애플리케이션의 로직과 남은 데이터 처리량에 따라 달라진다. 이로 인해 2단계의 ACK 응답과 3단계의 FIN 전송 사이에 상당한 지연이 발생할 수 있다.
클라이언트는 서버로부터 받은 FIN 패킷에 대한 응답으로 ACK 패킷을 전송합니다. 이 ACK 패킷의 시퀀스 번호는 서버의 FIN 패킷에 담긴 시퀀스 번호에 1을 더한 값으로 설정됩니다. 이는 서버의 FIN 세그먼트를 정상적으로 수신했음을 확인하는 절차입니다.
이 ACK 패킷을 수신한 서버는 CLOSED 상태로 완전히 전환되어 연결을 종료합니다. 반면, ACK 패킷을 보낸 클라이언트는 즉시 종료되지 않고 TIME_WAIT 상태로 들어갑니다. 이 상태는 일반적으로 2*MSL(Maximum Segment Lifetime)의 시간 동안 유지됩니다[4]. TIME_WAIT 상태의 주요 목적은 두 가지입니다.
첫째, 클라이언트가 보낸 최종 ACK 패킷이 전송 중 유실될 경우를 대비하기 위함입니다. 만약 ACK가 유실되고 서버가 자신의 FIN 패킷에 대한 응답을 받지 못하면, 서버는 FIN 패킷을 재전송합니다. 클라이언트가 TIME_WAIT 상태에 머물러 있다면 이 지연된 FIN 패킷을 다시 수신하고 ACK를 재전송할 수 있어, 서버가 정상적으로 종료될 수 있도록 보장합니다.
둘째, 이전 연결에서 지연되어 도착한 패킷이 새로 생성된 동일한 주소와 포트를 사용하는 새로운 연결에 혼란을 주는 것을 방지합니다. TIME_WAIT 상태 동안에는 해당 연결의 소켓 쌍(출발지 IP/포트, 목적지 IP/포트)이 사용 중인 것으로 간주되어, 같은 4-tuple을 가진 새로운 연결이 즉시 생성되는 것을 막아 이러한 문제를 예방합니다.

TIME_WAIT 상태는 4-Way Handshake 과정의 마지막 단계에서, 최종 ACK 패킷을 보낸 측(일반적으로 연결을 먼저 종료하려는 클라이언트)이 도달하는 상태이다. 이 상태는 TCP 연결이 완전히 종료되기 전에 일정 시간 동안 유지되는 대기 기간이다. 표준적으로 이 시간은 Maximum Segment Lifetime의 두 배, 즉 2MSL로 설정된다[5].
TIME_WAIT 상태의 주요 역할은 두 가지이다. 첫째, 지연되어 도착하는 패킷을 처리하여 새로운 연결에서의 데이터 혼란을 방지한다. 네트워크 상에서 이전 연결의 패킷이 지연되어 늦게 도착할 수 있다. 만약 같은 IP 주소와 포트 번호 쌍으로 즉시 새로운 연결이 수립된다면, 이 지연된 패킷이 새 연결의 데이터로 잘못 해석될 수 있다. TIME_WAIT 상태는 이러한 지연 패킷이 네트워크에서 소멸될 때까지 기다리는 시간을 보장한다.
둘째, 연결 종료의 신뢰성을 보장한다. 마지막으로 보낸 ACK 패킷이 유실될 경우, 상대방(서버)은 자신이 보낸 FIN 패킷에 대한 응답을 받지 못해 FIN 패킷을 재전송하게 된다. TIME_WAIT 상태에 있는 호스트는 이 재전송된 FIN 패킷을 수신할 수 있고, 자신의 ACK 패킷을 다시 보냄으로써 연결 종료 절차를 완료할 수 있다. 이 과정이 없으면 ACK가 유실되었을 때 서버는 불필요하게 오랜 시간 LAST_ACK 상태에 머무를 수 있다.
상태 | 설명 | 지속 시간 |
|---|---|---|
TIME_WAIT | 최종 ACK를 보낸 후 대기. 지연 패킷 처리 및 종료 신뢰성 보장. | 2MSL (일반적으로 60초) |
CLOSE_WAIT | 상대방의 FIN을 받고 애플리케이션의 종료를 기다리는 상태. | 애플리케이션 종료 시까지 |
LAST_ACK | 자신의 FIN을 보내고 그에 대한 ACK를 기다리는 상태. | 상대방의 ACK 도착 시까지 |
따라서 TIME_WAIT 상태는 네트워크의 신뢰성을 해치지 않으면서 정상적인 연결 종료를 완료하기 위한 필수적인 메커니즘이다. 그러나 서버와 같이 특정 포트에 대한 빈번한 연결과 종료가 발생하는 시스템에서는 TIME_WAIT 상태의 소켓이 과도하게 쌓여 리소스 부족을 초래할 수 있다[6].
TIME_WAIT 상태는 TCP 연결이 4-Way Handshake를 통해 완전히 종료된 후, 최종 ACK를 보낸 측(일반적으로 연결을 먼저 종료하려는 클라이언트)이 일정 시간 동안 유지하는 상태이다. 이 상태의 기본적인 목적은 지연되거나 중복된 패킷이 같은 연결의 새로운 세션에 영향을 주지 않도록 처리하기 위함이다.
TIME_WAIT 상태는 일반적으로 2*MSL(Maximum Segment Lifetime)의 시간 동안 지속된다[7]. 이 시간 동안 해당 연결에 사용되었던 소켓 쌍(출발지 IP, 출발지 포트, 목적지 IP, 목적지 포트)은 새로운 연결에 즉시 재사용될 수 없다. 이는 두 가지 중요한 문제를 방지한다. 첫째, 이전 연결의 지연된 패킷이 같은 주소와 포트를 사용하는 새로운 연결에 잘못 전달되는 것을 막는다. 둘째, 연결 종료 과정의 마지막 ACK가 유실되었을 경우, 상대방이 재전송한 FIN 패킷에 대한 응답을 보낼 수 있도록 한다.
상태 | 역할 | 지속 시간 |
|---|---|---|
TIME_WAIT | 지연/중복 패킷 소멸 대기, FIN 재전송 대응 | 2*MSL (예: 60초) |
CLOSE_WAIT | 로컬 애플리케이션이 연결 종료를 처리할 때까지 대기 | 애플리케이션 종료 호출까지 |
TIME_WAIT 상태가 불필요하게 길어지면, 특히 서버 측에서 고부하 환경에서 사용 가능한 포트 자원이 고갈되는 문제를 일으킬 수 있다. 이를 완화하기 위해 소켓 옵션(예: SO_REUSEADDR)을 설정하여 TIME_WAIT 상태의 소켓 주소를 재사용하도록 조정하는 경우가 있다. 그러나 이는 신중하게 적용해야 하며, 기본적으로 TIME_WAIT은 TCP의 신뢰성 있는 연결 종료를 보장하는 필수적인 메커니즘이다.
TIME_WAIT 상태가 유지되는 동안, 지연되어 도착한 이전 연결의 패킷을 올바르게 처리하는 것이 핵심 역할 중 하나이다. 네트워크 환경에서는 패킷이 라우팅 경로 변경이나 네트워크 혼잡 등 다양한 이유로 지연되어 도착할 수 있다. 만약 동일한 IP 주소와 포트 번호의 새 연결이 즉시 수립된다면, 이 지연된 패킷은 새 연결의 데이터로 오인되어 처리될 위험이 있다.
이러한 문제를 방지하기 위해 TIME_WAIT 상태는 일정 시간(보통 최대 세그먼트 수명의 두 배, 2MSL[8]]) 동안 연결 정보를 유지한다. 이 시간은 네트워크 상에서 패킷이 생존할 수 있는 최대 시간을 고려하여 설정된다. 지연된 패킷이 도착하면, 해당 패킷의 시퀀스 번호는 이미 종료된 연결의 범위에 속하므로, 시스템은 이를 오래된 패킷으로 인식하고 단순히 폐기한다.
아래 표는 지연된 패킷이 새 연결에 미치는 영향을 TIME_WAIT 상태 유무에 따라 비교한다.
상황 | TIME_WAIT 상태 없음 | TIME_WAIT 상태 있음 |
|---|---|---|
지연된 패킷 도착 | 동일한 사양(IP:포트)의 새 연결이 존재할 경우, 해당 패킷이 새 연결의 데이터로 오인될 수 있음. | 시스템이 이 패킷을 이전 연결의 것으로 인식하고 안전하게 폐기함. |
데이터 무결성 | 오염된 데이터 스트림으로 인해 무결성이 훼손될 위험이 높음. | 새 연결의 데이터 스트림이 보호됨. |
연결 안정성 | 예측 불가능한 동작으로 연결이 불안정해질 수 있음. | 네트워크 지연으로 인한 부작용으로부터 연결이 보호됨. |
따라서 지연된 패킷 처리는 TCP가 신뢰성 있는 연결 종료를 보장하고, 순서가 뒤바뀐 또는 중복된 세그먼트가 새 세션에 간섭하지 않도록 하는 중요한 메커니즘이다.

TCP의 Half-Close 연결은 연결 종료 과정에서 한쪽 방향의 데이터 흐름만 먼저 중단할 수 있도록 하는 기능이다. 일반적인 4-Way Handshake는 양방향 연결을 모두 끊지만, Half-Close는 데이터 전송이 끝난 한쪽에서 FIN 패킷을 보내어 송신을 종료한 후에도 상대방으로부터의 데이터 수신은 계속 가능한 상태를 유지한다.
이 과정은 주로 클라이언트가 서버에 모든 요청 데이터를 보낸 후, 서버의 응답만을 기다려야 하는 상황에서 활용된다. 클라이언트는 FIN 플래그가 설정된 패킷을 보내어 자신의 송신 채널을 닫는다. 서버는 이에 대해 ACK 패킷으로 응답하며, 클라이언트의 송신 종료를 승인한다. 이 시점에서 클라이언트에서 서버로의 데이터 흐름은 종료되지만, 서버는 아직 보내야 할 데이터가 있다면 계속해서 클라이언트에게 패킷을 전송할 수 있다. 서버의 데이터 전송이 모두 완료되면, 비로소 서버도 FIN 패킷을 보내어 연결 종료 절차를 마무리한다.
Half-Close 상태는 FIN_WAIT_2와 CLOSE_WAIT 상태를 통해 구현된다. 초기 FIN을 보낸 호스트는 FIN_WAIT_2 상태에 들어가 상대방의 추가 데이터와 최종 FIN 패킷을 기다린다. 데이터를 보내는 호스트는 CLOSE_WAIT 상태에 머물며 자신의 데이터 전송을 계속한다. 이 메커니즘은 TCP가 제공하는 전이중 통신의 이점을 활용하여, 연결 종료를 보다 유연하고 효율적으로 관리할 수 있게 해준다.

4-Way Handshake 과정에서 핵심적인 역할을 하는 TCP 헤더 내의 제어 비트는 FIN과 ACK이다. 이 두 플래그의 조합이 연결 종료의 각 단계를 정의하고 신뢰성을 보장한다.
FIN 플래그는 'Finish'의 약자로, 송신 측이 더 이상 보낼 데이터가 없으며 연결 종료를 원한다는 신호이다. 이 플래그가 설정된 세그먼트를 수신한 측은 상대방이 데이터 전송을 완료했음을 인지한다. 한편, ACK 플래그는 'Acknowledgment'의 약자로, 상대방으로부터 성공적으로 수신한 시퀀스 번호에 대한 확인 응답을 의미한다. 모든 4-Way Handshake 단계는 이 두 플래그가 단독 또는 함께 설정된 패킷의 교환으로 이루어진다.
과정별 플래그의 역할은 다음과 같다.
단계 | 송신자 → 수신자 | 설정된 플래그 | 의미 |
|---|---|---|---|
1단계 | 클라이언트 → 서버 |
| 클라이언트의 연결 종료 요청 및 최근 데이터에 대한 확인 응답 |
2단계 | 서버 → 클라이언트 |
| 클라이언트의 |
3단계 | 서버 → 클라이언트 |
| 서버의 연결 종료 요청 및 확인 응답 |
4단계 | 클라이언트 → 서버 |
| 서버의 |
이 표에서 볼 수 있듯, 첫 번째와 세 번째 단계의 FIN 패킷은 일반적으로 마지막으로 수신한 데이터에 대한 확인 응답을 함께 전송하기 위해 ACK 플래그도 함께 설정된다. 이는 효율성을 높이는 기법이다. 반면, 두 번째와 네 번째 단계의 응답은 순수한 확인 응답(ACK)만으로 구성된다. 이러한 플래그의 엄격한 교환은 양방향 연결이 모두 정상적으로 닫혔음을 보장하는 신뢰성의 기반이 된다.

일반적인 웹 브라우저와 웹 서버 간의 HTTP 세션 종료를 예로 들어 4-Way Handshake의 패킷 흐름을 설명한다. 클라이언트(브라우저)가 서버와의 연결을 종료하려는 상황을 가정한다.
단계 | 송신자 → 수신자 | 패킷 타입 | 주요 플래그 | 설명 |
|---|---|---|---|---|
1 | 클라이언트 → 서버 | FIN=1, ACK=1, Seq=u | 클라이언트가 활성 데이터 전송을 마치고 연결 종료를 시작한다. | |
2 | 서버 → 클라이언트 | TCP 세그먼트 | ACK=1, Seq=v, Ack=u+1 | 서버는 |
3 | 서버 → 클라이언트 | TCP 세그먼트 | FIN=1, ACK=1, Seq=w, Ack=u+1 | 서버가 자신의 데이터 전송을 모두 마치면, 클라이언트에게 |
4 | 클라이언트 → 서버 | TCP 세그먼트 | ACK=1, Seq=u+1, Ack=w+1 | 클라이언트는 서버의 |
이 과정에서 패킷은 순차적으로 교환되며, 각 단계는 이전 단계의 성공적인 수신에 의존한다. 2단계와 3단계가 분리되어 있기 때문에 전체 과정이 4번의 패킷 교환으로 이루어진다. 만약 최종 ACK가 유실되면, 서버는 자신이 보낸 FIN 패킷을 재전송하게 된다.

4-Way Handshake는 일반적인 연결 종료 절차이지만, 특정 상황에서는 변형된 형태로 진행될 수 있다. 또한 이 절차는 전송 계층의 프로토콜 동작으로, 상위 애플리케이션 계층의 동작과 밀접하게 연관되어 있다.
일반적인 4-Way Handshake는 한쪽이 먼저 FIN 패킷을 보내는 비대칭적인 종료 절차이다. 그러나 통신 양측이 거의 동시에 연결을 종료하려고 할 경우, "동시 종료(Simultaneous Close)"라는 변형 절차가 발생할 수 있다. 이 경우, 양측이 서로에게 FIN 패킷을 보내고, 각각의 FIN 패킷에 대해 ACK 패킷으로 응답하는 교차 형태의 패킷 교환이 이루어진다. 이 과정은 4개의 패킷 교환으로 이루어지지만, 순서가 일반적인 경우와 다르며, 양측 모두 FIN_WAIT_1 상태와 CLOSING 상태를 거쳐 TIME_WAIT 상태로 진입하게 된다.
4-Way Handshake는 TCP 프로토콜 스택이 자체적으로 수행하는 절차이지만, 그 시작과 완료는 애플리케이션의 제어를 받는다. 예를 들어, 웹 브라우저에서 탭을 닫거나, 소켓 프로그래밍에서 close() 시스템 콜을 호출하면 운영체제의 TCP 구현이 FIN 패킷을 생성하여 절차를 시작한다. 반대로, 애플리케이션이 갑자기 종료되면(예: 프로세스 강제 종료), 정상적인 4-Way Handshake 없이 RST 패킷을 보내 연결을 강제로 끊을 수도 있다. 따라서 애플리케이션의 설계와 종료 로직은 하위 계층의 연결 종료 신뢰성에 직접적인 영향을 미친다.
TCP 연결 종료는 일반적으로 한쪽이 먼저 종료를 요청하는 비대칭적인 4-Way Handshake 과정을 따르지만, 양측이 거의 동시에 연결 종료를 시작하는 경우도 발생할 수 있다. 이를 동시 종료(Simultaneous Close)라고 부른다.
동시 종료 시나리오에서는 양쪽 호스트가 서로에게 FIN 패킷을 보내는 것으로 절차가 시작된다. 각 호스트는 자신의 FIN 패킷을 보낸 직후, 상대방으로부터 FIN 패킷을 수신하게 된다. 이때의 패킷 교환 과정은 다음과 같다.
단계 | 송신자 → 수신자 | 전송 플래그 | 상태 변화 |
|---|---|---|---|
1 | 호스트 A → 호스트 B | FIN | 호스트 A는 FIN_WAIT_1 상태로 진입 |
2 | 호스트 B → 호스트 A | FIN | 호스트 B도 FIN_WAIT_1 상태로 진입 |
3 | 호스트 B → 호스트 A | ACK | 호스트 B는 호스트 A의 FIN에 대한 응답으로 ACK를 보내고, CLOSING 상태로 전환 |
4 | 호스트 A → 호스트 B | ACK | 호스트 A는 호스트 B의 FIN에 대한 응답으로 ACK를 보내고, TIME_WAIT 상태로 전환 |
동시 종료 과정에서 총 4개의 세그먼트가 교환되지만, 일반적인 4-Way Handshake와는 패킷 흐름이 다르다. 핵심 차이는 두 번째와 세 번째 단계가 하나의 패킷(FIN + ACK)으로 합쳐질 수 없다는 점이다. 각 호스트가 상대방의 FIN을 수신했을 때, 자신의 FIN을 이미 보낸 후이므로, 이에 대한 ACK 응답만을 별도로 전송해야 한다. 결과적으로 두 개의 FIN 패킷과 두 개의 ACK 패킷이 교환된다.
이 과정을 마친 양측은 최종적으로 TIME_WAIT 상태에 진입하게 된다. TIME_WAIT 상태는 지연되어 도착할 수 있는 패킷을 처리하기 위해 설정된 대기 시간으로, 동시 종료 후에도 이 상태를 유지함으로써 연결의 안정적인 완전 종료를 보장한다.
애플리케이션 계층은 TCP의 4-Way Handshake와 직접적으로 연관되어 있다. 4-Way Handshake는 전송 계층에서 연결을 정상적으로 종료하는 절차이지만, 이 과정의 시작과 완료는 대부분 상위의 애플리케이션 계층 프로세스에 의해 결정되고 통보받는다. 예를 들어, 웹 브라우저에서 탭을 닫거나 SSH 세션에서 exit 명령을 입력하면, 해당 애플리케이션은 운영체제의 소켓 API를 통해 close() 시스템 호출을 수행한다. 이 호출이 4-Way Handshake를 시작하는 신호가 된다.
반대로, 애플리케이션은 연결 종료 과정에서 중요한 제어를 행사할 수 있다. Half-Close 연결은 그 대표적인 예시이다. 애플리케이션이 shutdown() 시스템 호출을 사용하여 출력 스트림만 닫으면(FIN 전송), 해당 측은 더 이상 데이터를 보낼 수 없지만 상대방이 보내는 데이터는 계속 수신할 수 있다. 이는 파일 전송 시 수신 확인을 보내거나, 일방적인 데이터 스트리밍을 종료할 때 유용한 기법이다. 애플리케이션의 설계와 요구사항이 전송 계층의 종료 방식을 결정하는 경우이다.
애플리케이션 계층 프로토콜은 자체적인 종료 절차를 정의하기도 하며, 이는 4-Way Handshake와 협력적으로 동작한다. 예를 들어, HTTP/1.1에서는 Connection: close 헤더를 교환하여 양측이 더 이상의 요청/응답을 원하지 않음을 알린 후 TCP 연결 종료를 진행한다. FTP의 QUIT 명령이나 SMTP의 QUIT 명령도 애플리케이션 수준의 정상 종료 신호를 먼저 교환한 후, 하위의 TCP 연결을 종료하는 패턴을 따른다. 이는 통신의 의미론적 완결성을 보장하는 데 기여한다.
애플리케이션 계층 동작 | 전송 계층(TCP)에 미치는 영향 |
|---|---|
| 일반적인 4-Way Handshake 시작 |
| Half-Close 연결 상태로 진입 |
프로토콜별 종료 명령(예: HTTP | 애플리케이션 데이터 교환 종료 후 4-Way Handshake 트리거 |
프로세스 강제 종료(예: |
따라서, 4-Way Handshake는 전송 계층의 신뢰성 있는 연결 해제 메커니즘을 제공하지만, 그 실행과 세부적인 형태는 애플리케이션의 의도와 설계에 깊이 의존한다. 두 계층의 협력이 안정적인 네트워크 통신의 완결을 보장한다.