앞에서 TCP 연결을 시작할 때 3-Way Handshake를 사용한다고 알아봤다.

그런데 한 가지 궁금한 점이 생긴다.

연결을 시작할 때도 서로 확인하는 과정이 필요하다면, 통신이 끝났을 때는 어떻게 연결을 끊을까?

TCP는 연결을 종료할 때도 그냥 한쪽에서 연결을 끊어버리는 방식으로 끝내지 않는다.

데이터가 아직 남아 있을 수도 있고, 양쪽에서 보내는 작업이 완전히 끝났는지도 확인해야 하기 때문이다.

이때 사용하는 대표적인 과정이 4-Way Handshake다.

TCP 연결을 끊는 이유

TCP는 연결을 만들고 데이터를 주고받는 동안 서로의 상태를 관리한다.

그래서 통신이 끝났다고 해서 갑자기 연결을 없애버리면 문제가 생길 수 있다.

예를 들어 클라이언트가 서버에 데이터를 보내고 있다고 해보자.

Client ───── 데이터 ─────→ Server
Client ───── 데이터 ─────→ Server

클라이언트 입장에서는 보낼 데이터가 모두 끝났더라도 서버에서는 아직 처리해야 할 작업이 남아 있을 수 있다.

또한 TCP에서는 양쪽이 데이터를 보내는 방향이 서로 독립적이다.

즉, 내가 더 이상 보낼 데이터가 없다고 해서 상대방도 데이터를 모두 보냈다는 뜻은 아니다.

그래서 TCP 연결 종료는 시작할 때보다 조금 더 복잡하다.

4-Way Handshake란?

TCP의 일반적인 연결 종료 과정은 다음과 같이 진행된다.

Client                         Server

   FIN ─────────────────────→
   
       ←──────────────── ACK
   
       ←──────────────── FIN
   
   ACK ─────────────────────→

          연결 종료

총 네 번의 메시지가 오가기 때문에 4-Way Handshake라고 부른다.

각 단계가 어떤 의미인지 하나씩 보면 어렵지 않다.

첫 번째는 FIN

먼저 연결을 종료하고 싶은 쪽에서 FIN을 보낸다.

FIN은 Finish를 의미한다.

Client ───── FIN ─────→ Server

쉽게 생각하면 클라이언트가 서버에게

“나는 이제 더 이상 보낼 데이터가 없습니다.”

라고 알려주는 것이다.

여기서 중요한 부분이 있다.

FIN을 보냈다고 해서 상대방과의 통신이 그 순간 완전히 끝나는 것은 아니다.

클라이언트가 보내는 방향만 종료됐다고 보는 것이 더 정확하다.

두 번째는 ACK

서버는 클라이언트가 보낸 FIN을 확인하고 ACK를 보낸다.

Client ←──── ACK ───── Server

이 응답은 클라이언트가 연결 종료 요청을 보낸 것을 서버가 정상적으로 받았다는 의미다.

그렇다고 아직 TCP 연결 전체가 종료된 것은 아니다.

서버 입장에서는 클라이언트에게 아직 보내야 할 데이터가 남아 있을 수도 있기 때문이다.

그래서 서버는 필요한 데이터를 계속 보낼 수 있다.

세 번째는 서버의 FIN

서버가 자신이 보내야 할 데이터를 모두 처리했다면 이제 서버도 FIN을 보낸다.

Client ←──── FIN ───── Server

이제 서버도

“나도 더 이상 보낼 데이터가 없습니다.”

라고 알려주는 것이다.

네 번째는 ACK

마지막으로 클라이언트가 서버의 FIN을 확인하고 ACK를 보낸다.

Client ───── ACK ─────→ Server

이 과정을 끝으로 TCP 연결 종료가 완료된다.

전체 과정을 다시 보면:

① Client → Server : FIN
② Client ← Server : ACK
③ Client ← Server : FIN
④ Client → Server : ACK

이렇게 네 단계가 진행된다.

왜 연결할 때는 3번이고 끊을 때는 4번일까?

처음 보면 이것도 조금 이상하게 느껴진다.

연결할 때는 3-Way Handshake인데 왜 종료할 때는 4-Way Handshake를 사용할까?

가장 큰 이유는 TCP 통신이 양방향으로 이루어지기 때문이다.

클라이언트가 데이터를 보내는 방향과 서버가 데이터를 보내는 방향은 각각 따로 종료할 수 있다.

예를 들어 클라이언트가 더 이상 보낼 데이터가 없어서 FIN을 보냈다고 하자.

그렇다고 서버가 클라이언트에게 보내고 있던 데이터까지 당장 중단해야 하는 것은 아니다.

Client → Server
   FIN

Client ← Server
   아직 데이터 전송 가능

그래서 서버는 먼저 ACK를 보내고, 자신이 보낼 데이터가 모두 끝난 뒤에 FIN을 보내게 된다.

이 때문에 일반적인 경우에는 네 번의 메시지가 필요하다.

연결 종료와 데이터 전송은 동시에 일어날 수 있다

TCP에서 재미있는 부분이 이 부분이다.

FIN을 보냈다고 해서 해당 TCP 연결이 양쪽 모두 즉시 끊기는 것은 아니다.

TCP는 각각의 데이터 전송 방향을 독립적으로 종료할 수 있다.

그래서 한쪽에서 FIN을 보낸 뒤에도 반대쪽에서 데이터를 보내는 상황이 가능하다.

Client ───── FIN ─────→ Server

Client ←──── 데이터 ─── Server

이런 상태를 TCP의 Half-Close라고 한다.

한쪽 방향의 데이터 전송은 끝났지만 다른 방향은 아직 열려 있는 상태다.

일반적인 웹 통신에서는 이런 과정을 직접 볼 일이 많지는 않지만, TCP를 제대로 이해하려면 알아둘 만한 개념이다.

연결을 끊었다고 바로 끝나는 것도 아니다

TCP 연결을 종료하는 과정에서 TIME_WAIT라는 상태도 나온다.

특히 연결을 먼저 종료한 쪽에서 이 상태가 나타날 수 있다.

처음 보면

“연결을 다 끊었는데 왜 또 기다리지?”

라는 생각이 들 수 있다.

이것은 네트워크에 남아 있을 수 있는 이전 TCP 패킷 때문에 문제가 발생하는 것을 방지하고, 마지막 ACK가 제대로 전달되지 않았을 경우에 대응하기 위한 목적 등이 있다.

TIME_WAIT 상태는 일정 시간 동안 연결 정보를 유지한 뒤 사라진다.

운영체제나 상황에 따라 세부 동작에는 차이가 있지만, TCP 연결 종료를 이해할 때 상당히 자주 등장하는 상태다.

웹사이트를 닫으면 항상 4-Way Handshake가 발생할까?

꼭 그렇다고 볼 수는 없다.

TCP 연결 종료는 일반적인 흐름을 설명하면 4-Way Handshake지만, 실제 네트워크에서는 연결 상태나 애플리케이션의 동작에 따라 조금씩 달라질 수 있다.

예를 들어 FIN과 ACK가 하나의 세그먼트에 함께 들어가는 경우도 있다.

또한 정상적인 연결 종료가 아니라 오류가 발생해서 **RST(Reset)**가 사용되는 경우도 있다.

그래서 패킷을 직접 캡처했을 때 항상 똑같은 네 개의 패킷만 보인다고 생각하면 안 된다.

RST는 FIN과 어떻게 다를까?

TCP에서 FIN과 함께 자주 보게 되는 것이 RST다.

FIN이 정상적으로 연결을 종료하기 위한 과정이라면 RST는 연결을 즉시 끊거나 비정상적인 상황을 알릴 때 사용된다.

예를 들어 존재하지 않는 포트에 TCP 연결을 요청하거나 이미 종료된 연결에 예상하지 못한 데이터가 들어오는 경우 RST가 발생할 수 있다.

간단하게 생각하면:

FIN
→ 정상적인 연결 종료

RST
→ 연결을 즉시 끊거나 비정상적인 상태를 알림

정도로 구분해두면 처음 공부할 때는 충분하다.

패킷을 직접 확인해보면

67번에서 이야기했던 3-Way Handshake와 마찬가지로 Wireshark 같은 패킷 분석 프로그램을 사용하면 TCP 연결 종료 과정도 직접 확인할 수 있다.

패킷 목록에서 TCP를 찾아보면 FIN, ACK, RST 등의 플래그를 확인할 수 있다.

예를 들어 정상적으로 연결이 종료되는 상황이라면 대략 이런 흐름을 볼 수 있다.

FIN
ACK
FIN
ACK

패킷을 하나씩 따라가 보면 책에서 봤던 내용이 실제 네트워크에서 어떻게 나타나는지 확인할 수 있다.

TCP 연결 종료를 정리해보면

TCP는 데이터를 모두 주고받았다고 해서 연결을 갑자기 끊는 방식으로 동작하지 않는다.

일반적인 종료 과정에서는 먼저 한쪽이 FIN을 보내고, 상대방이 ACK를 보낸다.

그 다음 상대방도 자신이 보낼 데이터를 모두 처리한 뒤 FIN을 보내고, 처음 종료를 요청했던 쪽에서 마지막 ACK를 보내면서 연결이 종료된다.

① FIN
② ACK
③ FIN
④ ACK

그래서 TCP 연결 종료 = 4-Way Handshake라고 기억해두면 된다.

처음 연결할 때는 서로 통신할 준비가 됐는지를 확인하고, 연결을 끊을 때는 양쪽에서 보낼 데이터가 모두 끝났는지를 확인한다는 차이가 있다.

이렇게 보면 TCP가 단순히 “데이터를 보내는 프로토콜”이라기보다는 연결 상태와 데이터의 흐름을 상당히 꼼꼼하게 관리하는 프로토콜이라는 것도 조금씩 보인다.

다음에 TCP의 재전송이나 ACK, 시퀀스 번호를 같이 보면 왜 이런 복잡한 과정이 필요한지도 자연스럽게 연결된다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

글쓴이

rjsan46@koreabites.com

관련 게시물

웹 브라우저에 주소를 입력하면 일어나는 일

웹 브라우저 주소창에 웹사이트 주소를 입력하고 엔터를 누르면 바로 화면이 나타나는 것처럼 보인다. 하지만 실제로는 그 짧은 순간에 꽤 많은 일이 일어난다....

모두 읽어보기

소켓이란 무엇일까? 프로그램과 네트워크를 연결하는 통로

네트워크를 공부하다 보면 IP 주소와 포트 번호라는 말을 계속 만나게 된다. IP 주소는 어떤 컴퓨터와 통신할 것인지 구분하고, 포트 번호는 그 컴퓨터에서...

모두 읽어보기

쿠키와 세션은 어떻게 다를까?

웹사이트를 이용하다 보면 한 번 로그인한 뒤 다른 페이지로 이동해도 로그인 상태가 계속 유지되는 것을 볼 수 있다. 예를 들어 쇼핑몰에 로그인한...

모두 읽어보기

SSL과 TLS는 어떤 역할을 할까?

앞에서 HTTPS가 HTTP보다 안전한 이유를 살펴봤다. HTTPS는 단순히 HTTP 자체가 더 안전하게 만들어진 프로토콜이 아니라, HTTP 통신에 TLS라는 보안 계층을 적용한 것이라고...

모두 읽어보기

포트 번호로 네트워크 서비스를 구분하는 방법

컴퓨터가 네트워크를 통해 다른 컴퓨터와 통신할 때 가장 먼저 떠오르는 것이 IP 주소다. 예를 들어 어떤 서버의 IP 주소가 192.168.0.10이라고 해보자. 그런데...

모두 읽어보기

HTTPS는 HTTP보다 무엇이 안전할까?

인터넷에서 웹사이트에 접속하다 보면 주소창에 http://가 붙어 있는 경우도 있고 https://가 붙어 있는 경우도 있다. 요즘은 대부분의 웹사이트가 HTTPS를 사용하기 때문에 사실상...

모두 읽어보기