네트워크 패킷 브로커 TCP 연결의 핵심 미스터리: 트리플 핸드셰이크의 필요성에 대한 해부

TCP 연결 설정
웹서핑을 하거나, 이메일을 보내거나, 온라인 게임을 할 때 우리는 그 이면에 숨겨진 복잡한 네트워크 연결에 대해 생각하지 않는 경우가 많습니다. 하지만 바로 이러한 사소해 보이는 단계들이 우리와 서버 간의 안정적인 통신을 보장하는 핵심입니다. 그중에서도 가장 중요한 단계 중 하나는 TCP 연결 설정이며, 그 핵심은 3방향 핸드셰이크입니다.

이 글에서는 3방향 핸드셰이크의 원리, 과정 및 중요성에 대해 자세히 살펴보겠습니다. 단계별로 3방향 핸드셰이크가 필요한 이유, 연결 안정성과 신뢰성을 보장하는 방법, 그리고 데이터 전송에 있어 얼마나 중요한지 설명하겠습니다. 3방향 핸드셰이크에 대한 깊이 있는 이해를 통해 네트워크 통신의 기본 메커니즘을 더 잘 파악하고 TCP 연결의 신뢰성을 더욱 명확하게 이해할 수 있을 것입니다.

TCP 3방향 핸드셰이크 프로세스 및 상태 전환
TCP는 연결 지향형 전송 프로토콜로, 데이터 전송 전에 연결 설정이 필요합니다. 이 연결 설정 과정은 3방향 핸드셰이크를 통해 이루어집니다.

 TCP 3방향 핸드셰이크

각 연결에서 전송되는 TCP 패킷을 좀 더 자세히 살펴보겠습니다.

초기에 클라이언트와 서버 모두 닫힌 상태입니다. 먼저 서버는 특정 포트에서 수신 대기(LISTEN) 상태가 되는데, 이는 서버가 시작되었음을 의미합니다. 다음으로 클라이언트는 웹페이지에 접속할 준비가 됩니다. 클라이언트는 서버와 연결을 설정해야 합니다. 첫 번째 연결 패킷의 형식은 다음과 같습니다.

 SYN 패킷

클라이언트가 연결을 시작하면 임의의 초기 시퀀스 번호(client_isn)를 생성하여 TCP 헤더의 "시퀀스 번호" 필드에 넣습니다. 동시에 클라이언트는 SYN 플래그 위치를 1로 설정하여 전송되는 패킷이 SYN 패킷임을 나타냅니다. 클라이언트는 서버로 첫 번째 SYN 패킷을 전송함으로써 서버와의 연결을 설정하려는 의사를 표시합니다. 이 패킷에는 애플리케이션 계층 데이터(즉, 전송된 데이터)가 포함되어 있지 않습니다. 이 시점에서 클라이언트의 상태는 SYN-SENT로 표시됩니다.

SYN+ACK 패킷

서버가 클라이언트로부터 SYN 패킷을 수신하면, 서버는 자체 시리얼 번호(server_isn)를 임의로 초기화한 후 TCP 헤더의 "시리얼 번호" 필드에 해당 번호를 입력합니다. 다음으로, 서버는 "승인 번호" 필드에 client_isn + 1을 입력하고 SYN 비트와 ACK 비트를 모두 1로 설정합니다. 마지막으로, 서버는 애플리케이션 계층 데이터(및 서버가 전송할 데이터)가 포함되지 않은 패킷을 클라이언트로 전송합니다. 이때 서버는 SYN-RCVD 상태가 됩니다.

ACK 패킷

클라이언트가 서버로부터 패킷을 수신하면, 최종 응답 패킷에 응답하기 위해 다음과 같은 최적화 작업을 수행해야 합니다. 첫째, 클라이언트는 응답 패킷의 TCP 헤더의 ACK 비트를 1로 설정합니다. 둘째, "응답 번호 확인" 필드에 server_isn + 1 값을 입력합니다. 마지막으로, 클라이언트는 서버로 패킷을 전송합니다. 이 패킷은 클라이언트에서 서버로 데이터를 전달할 수 있습니다. 이러한 작업이 완료되면 클라이언트는 ESTABLISHED 상태가 됩니다.

서버는 클라이언트로부터 응답 패킷을 수신하면 ESTABLISHED 상태로 전환됩니다.

위 과정을 보시면, 3방향 핸드셰이크에서 세 번째 핸드셰이크는 데이터를 전송할 수 있지만, 처음 두 번의 핸드셰이크는 데이터를 전송할 수 없다는 것을 알 수 있습니다. 이는 면접에서 자주 나오는 질문입니다. 3방향 핸드셰이크가 완료되면 양측 모두 ESTABLISHED 상태가 되어 연결이 성공적으로 설정되었음을 나타내며, 이때부터 클라이언트와 서버는 서로 데이터를 주고받을 수 있습니다.

왜 악수를 세 번이나 하는 거죠? 두 번이 아니라 네 번이나요?
흔히 듣는 대답은 "삼자 악수는 수신과 송신을 보장하기 때문이다"입니다. 이 대답도 맞지만, 표면적인 이유일 뿐 근본적인 이유는 제시하지 못합니다. 이하에서는 삼자 악수의 이유를 세 가지 관점에서 분석하여 이 문제에 대한 이해를 심화시켜 보겠습니다.

3방향 핸드셰이크는 과거에 반복되었던 연결의 초기화를 효과적으로 방지할 수 있습니다(주요 이유).
3자 핸드셰이크는 양측 모두 신뢰할 수 있는 초기 순번을 받았음을 보장합니다.
삼자 악수는 자원 낭비를 방지합니다.

이유 1: 과거 데이터 중복 조인을 방지하기
간단히 말해, 3방향 핸드셰이크의 주된 이유는 중복된 연결 초기화로 인한 혼란을 방지하기 위해서입니다. 복잡한 네트워크 환경에서는 데이터 패킷 전송이 항상 지정된 시간에 목적지 호스트에 도달하는 것은 아니며, 네트워크 혼잡 등의 이유로 오래된 데이터 패킷이 먼저 목적지 호스트에 도착할 수 있습니다. 이를 방지하기 위해 TCP는 3방향 핸드셰이크를 사용하여 연결을 설정합니다.

3방향 핸드셰이크는 과거의 중복 연결을 방지합니다.

클라이언트가 네트워크 혼잡과 같은 상황에서 여러 개의 SYN 연결 설정 패킷을 연속적으로 전송할 경우 다음과 같은 현상이 발생할 수 있습니다.

1. 이전 SYN 패킷이 최신 SYN 패킷보다 먼저 서버에 도착합니다.
2. 서버는 이전 SYN 패킷을 수신한 후 클라이언트에게 SYN + ACK 패킷으로 응답합니다.
3. 클라이언트가 SYN + ACK 패킷을 수신하면, 자체 컨텍스트에 따라 해당 연결이 과거 연결(시퀀스 번호 만료 또는 타임아웃)인지 판단한 후 서버에 RST 패킷을 전송하여 연결을 종료합니다.

두 번의 핸드셰이크를 거치는 연결에서는 현재 연결이 과거 연결인지 여부를 확인할 방법이 없습니다. 반면 세 번의 핸드셰이크를 거치는 연결에서는 클라이언트가 세 번째 패킷을 전송할 준비가 되었을 때 컨텍스트를 기반으로 현재 연결이 과거 연결인지 여부를 판단할 수 있습니다.

1. 과거 연결(시퀀스 번호 만료 또는 타임아웃)인 경우, 세 번째 핸드셰이크에서 전송되는 패킷은 과거 연결을 종료하기 위한 RST 패킷입니다.
2. 만약 과거 연결이 아닌 경우, 세 번째로 전송되는 패킷은 ACK 패킷이며, 두 통신 당사자는 성공적으로 연결을 설정합니다.

따라서 TCP가 3방향 핸드셰이크를 사용하는 주된 이유는 과거 연결을 방지하기 위해 연결을 초기화하기 때문입니다.

두 번째 이유: 양측의 초기 순번을 동기화하기 위함
TCP 프로토콜의 양쪽 모두는 시퀀스 번호를 유지해야 하는데, 이는 안정적인 전송을 보장하는 핵심 요소입니다. 시퀀스 번호는 TCP 연결에서 중요한 역할을 하며 다음과 같은 기능을 수행합니다.

수신기는 중복 데이터를 제거하고 데이터의 정확성을 보장할 수 있습니다.

수신기는 데이터의 무결성을 보장하기 위해 시퀀스 번호 순서대로 패킷을 수신할 수 있습니다.

● 순번을 통해 상대방이 수신한 데이터 패킷을 식별할 수 있으므로 안정적인 데이터 전송이 가능합니다.

따라서 TCP 연결이 설정되면 클라이언트는 초기 시퀀스 번호가 포함된 SYN 패킷을 서버로 전송하고, 서버는 클라이언트의 SYN 패킷을 성공적으로 수신했음을 나타내는 ACK 패킷으로 응답해야 합니다. 그러면 서버는 초기 시퀀스 번호가 포함된 SYN 패킷을 클라이언트로 전송하고 클라이언트의 응답을 기다립니다. 이렇게 최종적으로 초기 시퀀스 번호가 안정적으로 동기화되도록 합니다.

양측의 초기 일련 번호를 동기화하십시오.

4방향 핸드셰이크를 통해서도 양측의 초기 시퀀스 번호를 안정적으로 동기화할 수 있지만, 두 번째와 세 번째 단계를 하나로 통합하여 3방향 핸드셰이크를 사용할 수도 있습니다. 그러나 3방향 핸드셰이크는 한쪽의 초기 시퀀스 번호가 다른 쪽에 성공적으로 수신되는 것만 보장할 뿐, 양측의 초기 시퀀스 번호를 모두 확인할 수 있다는 보장은 없습니다. 따라서 TCP 연결의 안정성과 신뢰성을 확보하기 위해서는 3방향 핸드셰이크가 최선의 선택입니다.

세 번째 이유: 자원 낭비 방지
만약 "두 번의 핸드셰이크"만 있다면, 클라이언트의 SYN 요청이 네트워크에서 차단될 경우, 클라이언트는 서버가 보낸 ACK 패킷을 수신할 수 없으므로 SYN 요청을 다시 보내게 됩니다. 하지만 세 번째 핸드셰이크가 없기 때문에 서버는 클라이언트가 연결 설정에 필요한 ACK 응답을 수신했는지 여부를 확인할 수 없습니다. 따라서 서버는 각 SYN 요청을 수신한 후에만 능동적으로 연결을 설정할 수밖에 없습니다. 이는 다음과 같은 문제로 이어집니다.

자원 낭비: 클라이언트의 SYN 요청이 차단되어 여러 개의 SYN 패킷이 반복적으로 전송될 경우, 서버는 요청을 수신한 후 여러 개의 불필요한 유효하지 않은 연결을 설정하게 됩니다. 이는 서버 자원의 불필요한 낭비로 이어집니다.

메시지 보존: 세 번째 핸드셰이크가 없기 때문에 서버는 클라이언트가 연결 설정에 필요한 ACK 응답을 제대로 수신했는지 확인할 방법이 없습니다. 결과적으로 메시지가 네트워크에 갇히게 되면 클라이언트는 SYN 요청을 계속해서 반복적으로 전송하게 되고, 서버는 끊임없이 새로운 연결을 설정해야 합니다. 이는 네트워크 혼잡과 지연을 증가시켜 전반적인 네트워크 성능에 부정적인 영향을 미칩니다.

자원 낭비를 피하세요

따라서 TCP는 네트워크 연결의 안정성과 신뢰성을 보장하기 위해 3방향 핸드셰이크를 사용하여 연결을 설정하고 이러한 문제 발생을 방지합니다.

요약
그만큼네트워크 패킷 브로커TCP 연결 설정은 3방향 핸드셰이크 과정을 통해 이루어집니다. 3방향 핸드셰이크 과정에서 클라이언트는 먼저 서버에 SYN 플래그가 포함된 패킷을 전송하여 연결을 설정하려는 의사를 나타냅니다. 서버는 클라이언트의 요청을 수신한 후, 연결 요청을 수락했음을 알리는 SYN 및 ACK 플래그가 포함된 패킷과 자체 초기 시퀀스 번호를 클라이언트에 회신합니다. 마지막으로 클라이언트는 연결이 성공적으로 설정되었음을 알리는 ACK 플래그가 포함된 패킷을 서버에 회신합니다. 이렇게 해서 양측은 ESTABLISHED 상태가 되며 서로 데이터를 주고받을 수 있게 됩니다.

일반적으로 TCP 연결 설정을 위한 3방향 핸드셰이크 프로세스는 연결의 안정성과 신뢰성을 보장하고, 과거 연결로 인한 혼란과 자원 낭비를 방지하며, 양측이 데이터를 송수신할 수 있도록 설계되었습니다.


게시 시간: 2025년 1월 8일