핵심 인사이트 (3줄 요약)
- 본질: TCP 4-Way Handshake는 클라이언트와 서버가 서로 볼일이 다 끝났을 때, 갑자기 전화를 확 끊어버려서 상대방이 마지막으로 하려던 말을 못 듣는 참사를 막기 위해, 서로 4번에 걸쳐 "나 할 말 다 했어(FIN)", "응 알았어(ACK)"를 아주 정중하게 교환하며 세션을 우아하게 닫는 종료 의식이다.
- 반쪽짜리 닫힘 (Half-Close): 클라이언트가 먼저 "나 끊을게(FIN)"라고 해도, 서버는 "어 그래? 난 아직 너한테 보내줄 파일이 좀 남았는데? 이거 마저 다 보내고 끊을게!"라며 한쪽 방향은 닫혔지만 반대쪽 방향은 살아있는 '반쪽짜리 통신' 상태를 허용하는 것이 가장 큰 특징이다.
- 서버의 최종 FIN: 서버마저 남은 찌꺼기 파일을 다 보내고 나면, 비로소 자기도 "나도 이제 진짜 다 보냈어 끊자!(FIN)"라고 선언하고 클라이언트의 마지막 응답(ACK)을 받아야만 통신이 100% 영구적으로 소멸한다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
-
개념: TCP 세션(연결)을 정상적으로 해제하기 위해, 양 종단 간에
FIN과ACK제어 플래그를 4단계에 걸쳐 교환하여, 상호 간에 송신할 데이터가 없음을 확인하는 과정 (Graceful Teardown). -
필요성: 나쁜 이별(RST 패킷)은 그냥 멱살 잡고 "다 꺼져!" 하고 스위치를 뽑아버리면 끝난다. 하지만 좋은 이별은 준비가 필요하다. 내 PC는 카카오톡 사진 전송을 다 끝내서 끊고 싶은데, 카카오 서버는 나한테 줄 메시지 3개가 큐(대기열)에 남아 있을 수 있다. 만약 내가 3번 악수(3-Way)처럼
[FIN]쏘고 서버가[FIN+ACK]쏘고 끝내버리면, 서버에 남아있던 메시지 3개는 영원히 증발해 버린다. **"내가 먼저 끊자고 해도, 혹시 상대방이 나한테 덜 준 데이터가 있으면 그거 다 받을 때까지 얌전히 기다려 주자!"**라는 예의 바른 설계가 4번의 악수를 만들어냈다. -
💡 비유: 4-Way Handshake는 예의 바른 사람들의 **"전화 끊기 과정"**과 완벽히 일치합니다.
- A: "나 할 말 다 했어. 이제 전화 끊자~ (FIN)"
- B: "어 알았어, 끊자! (ACK) ... 근데 잠깐만!! 아까 말 안 한 게 있는데~~ 쏼라쏼라~~ (남은 데이터 전송)"
- A: "아 그래? (가만히 다 들어줌 = Half-Close 상태)"
- B: "응 이제 나도 진짜 할 말 다 끝났어. 찐으로 끊자~ (FIN)"
- A: "오케이~ 진짜 끊는다 뚝! (ACK)"
📢 섹션 요약 비유: 4단계 종료 과정은 뷔페 식당의 **"영업 종료 안내"**입니다. 지배인이 "영업 끝났습니다(FIN)"라고 안내해도, 손님 입의 음식을 뺏진 않습니다. 손님은 "네 알겠습니다(ACK)"라고 한 뒤, 접시에 남은 고기(남은 데이터)를 천천히 다 먹고 나서야 "잘 먹고 갑니다(FIN)"라고 인사하고, 지배인이 "안녕히 가세요(ACK)" 해야 비로소 문이 닫힙니다.
Ⅱ. 4단계 동작 메커니즘과 상태 변화 (Deep Dive)
이 4단계를 외우지 못하면 네트워크 면접에서 광탈한다. 누가 먼저 끊자고(Active Close) 제안했는지 클라이언트 입장에서 따라가 보자.
1단계: 클라이언트의 이별 통보 (FIN)
- 클라이언트는 더 보낼 게 없다.
- 패킷 헤더에
FIN불을 켜서 서버로 날린다. - 상태 변화: 클라이언트는
FIN_WAIT_1상태로 진입하여 상대방의 첫 대답을 기다린다.
2단계: 서버의 일단 수긍 (ACK)
- 서버가
FIN을 받았다. "오케이 네가 끊고 싶은 건 알겠어." - 서버는 일단
ACK불을 켜서 대답만 먼저 해준다. - 상태 변화:
- 서버는
CLOSE_WAIT상태가 된다. (이게 핵심이다! "어? 나 얘한테 보낼 데이터 램에 좀 남아있는데? 프로세스(앱)야, 빨리 남은 데이터 다 뿜어내서 정리해 줘!"라며 앱의 종료를 기다리는 상태다). - 클라이언트는 ACK를 받고
FIN_WAIT_2상태가 되어 서버의 진짜 마지막 인사를 기다린다. (이때 클라이언트의 쏘는 입은 닫혔지만, 서버가 보내는 패킷을 '듣는 귀'는 활짝 열려 있다 = Half-Close).
- 서버는
3단계: 서버의 찐막 인사 (FIN)
- 서버 측 앱이 남은 데이터를 싹 다 보냈다. "나도 이제 진짜 끝!"
- 서버는 자기 패킷 헤더에
FIN불을 켜서 클라이언트로 쏜다. - 상태 변화: 서버는
LAST_ACK상태가 되어 클라이언트의 마지막 영수증만 기다린다.
4단계: 클라이언트의 최종 수신 확인 (ACK)
- 클라이언트가 서버의 찐막
FIN을 받았다. - 클라이언트는 "그래 수고했어!"라며
ACK불을 켜서 서버로 쏜다. - 상태 변화 (매우 중요):
- 서버는 이 ACK를 받으면 미련 없이 소켓 메모리를 삭제하고
CLOSED(완전 소멸) 된다. - 클라이언트는 이 ACK를 쏘고 나서 바로 꺼지지 않는다! **
TIME_WAIT**라는 특수 상태에 빠져서 허공을 멍하니 1분 이상 쳐다보며 대기한다. (왜 대기하는지는 다음 장에서 배운다).
- 서버는 이 ACK를 받으면 미련 없이 소켓 메모리를 삭제하고
┌─────────────────────────────────────────────────────────────┐
│ TCP 4-Way Handshake 상태 변화 흐름도 │
├─────────────────────────────────────────────────────────────┤
│ │
│ [ 클라이언트 (Active Close) ] [ 서버 (Passive Close) ]│
│ (ESTABLISHED) (ESTABLISHED) │
│ │ │ │
│ │ 1. [FIN] "나 끊을게" │ │
│ ├───────────────────────────────────────▶ │ │
│ (FIN_WAIT_1) (CLOSE_WAIT) │
│ │ 2. [ACK] "어 알았어 (근데 남은 거 줌)" │ │
│ ◀───────────────────────────────────────┤ │
│ (FIN_WAIT_2) │ │
│ │ ... (남은 데이터 찌꺼기 전송) ... │ │
│ │ │ │
│ │ 3. [FIN] "나도 다 줬다 찐막 끊자!" │ │
│ ◀───────────────────────────────────────┤ │
│ (TIME_WAIT) (LAST_ACK) │
│ │ 4. [ACK] "잘 가~!" │ │
│ ├───────────────────────────────────────▶ │ │
│ │ (CLOSED) │
│ (2MSL 대기 후 CLOSED) │
└─────────────────────────────────────────────────────────────┘
📢 섹션 요약 비유: 4-Way Handshake는 무전기 통신의 **"오버 앤 아웃"**입니다. 내가 "할 말 다 했음, 오버(FIN)"라고 하면 상대는 "알겠음, 근데 내 할 말은 어쩌고 저쩌고~ 끝, 오버(FIN)"라고 합니다. 마지막으로 내가 "다 잘 들었음, 통신 끝 아웃!(ACK)"이라고 해야 비로소 무전기의 전원이 완전히 꺼집니다.