핵심 인사이트 (3줄 요약)

  1. 본질: TCP 킵얼라이브(Keep-Alive) 타이머는 상대방과 TCP 연결(ESTABLISHED)은 맺어놨는데 2시간 동안 아무런 데이터도 오가지 않을 때, "야, 너 아직 안 죽고 살아있냐?"라고 빈 깡통 패킷을 살짝 찔러보아 상대방의 생사(연결 유지)를 확인하는 심장 박동(Heartbeat) 테스트다.
  2. L4 방화벽의 가위질 방어 (주요 목적): 통신사와 기업의 방화벽들은 메모리를 아끼기 위해 "2시간 이상 아무 말 없는 세션은 끊어진 걸로 간주하고 무조건 자른다(Session Timeout)"는 무서운 룰이 있다. 앱이 가만히 숨죽이고 있다가 방화벽한테 모가지를 썰리는 걸 막기 위해, 일부러 5분마다 의미 없는 숨소리(Keep-Alive)를 내서 방화벽이 "아 얘네 아직 통신 중이네" 하고 세션을 살려두게 만드는 꼼수다.
  3. 좀비 커넥션 청소: 반대로, 상대방 PC가 블루스크린으로 뻑이 나가서 나한테 종료(FIN) 인사를 못 하고 강제 종료되었을 때, 내 서버는 상대가 죽은 줄 모르고 영원히 메모리를 낭비하며 기다리게 되는데, 킵얼라이브로 찔러봐서 대답이 없으면 서버가 알아서 그 좀비 커넥션을 빗자루로 쓸어버리는(RST) 청소부 역할도 수행한다.

Ⅰ. 개요 및 필요성 (Context & Necessity)

  • 개념: TCP 연결이 설정된 후, 장기간 데이터 전송이 없는 유휴(Idle) 상태에서 연결의 유효성을 검증하고, 중간 NAT/방화벽의 세션 타임아웃을 방지하기 위해 송신하는 주기적인 Probe(탐침) 패킷 메커니즘 (RFC 1122).

  • 필요성: 클라이언트가 텔넷(원격 접속)으로 내 서버에 붙어 놓고, 밥 먹으러 가서 10시간 동안 키보드를 안 쳤다. 내 서버는 이 클라이언트가 아직 화장실에 있는지, 아니면 아까 컴퓨터 코드를 뽑고 퇴근해 버렸는지 알 방법이 없다. 왜? TCP는 데이터가 날아갈 때만 통신을 하니까! 가만히 있으면 상대가 죽었는지 살았는지 구별이 안 된다. "야! 아무리 할 말이 없어도, 2시간에 한 번씩은 '나 살아있다'고 생존 신고 좀 하자! 대답 없으면 나 그냥 너 버리고 방(소켓) 뺄 거야!!"

  • 💡 비유: Keep-Alive는 요양원의 **"안부 확인 전화"**와 같습니다.

    • 자식(클라이언트)과 부모(서버) 사이에 며칠 동안 아무 대화(데이터)가 없습니다.
    • 부모님이 갑자기 전화를 안 받거나(장애), 전화선이 끊어지면(방화벽 차단) 큰일이 납니다.
    • 그래서 요양원 직원(OS)이 매일 아침 의미 없이 한 번씩 전화를 걸어(Keep-Alive Probe) "여보세요? 잘 계시죠?"라고 묻습니다. "응 잘 있다(ACK)"라는 대답만 들으면 바로 끊고 안심합니다. 대답이 없으면 즉시 호적(소켓)을 정리합니다.

📢 섹션 요약 비유: 킵얼라이브는 방화벽이라는 피도 눈물도 없는 저승사자에게서 살아남기 위한 **"생존 본능의 발버둥"**입니다. 저승사자는 움직임이 없는 시체(Idle 세션)를 귀신같이 찾아내 낫으로 베어버리므로, 살기 위해선 데이터가 없더라도 5분마다 헛기침(Keep-Alive)이라도 내서 자기가 살아있음을 증명해야 합니다.


Ⅱ. Keep-Alive의 동작 파라미터와 실무 적용 (Deep Dive)

1. 언제, 어떻게 찌르는가? (3대 파라미터)

리눅스 서버 커널을 만지는 백엔드 엔지니어라면 무조건 외우고 있는 설정값이다. OS는 아무 때나 찌르지 않고 3가지 초시계 룰을 따른다.

  1. tcp_keepalive_time (대기 시간): 기본값 무려 2시간(7200초). 마지막 데이터를 주고받은 뒤 2시간 동안 아무 말이 없으면, 그제야 최초의 생존 확인 깡통 패킷 1개를 훅 던져본다.
  2. tcp_keepalive_intvl (재시도 간격): 던졌는데 대답이 안 온다? 기본값 75초마다 한 번씩 계속 찔러본다. "야, 죽었냐? 야, 진짜 죽었어?"
  3. tcp_keepalive_probes (포기 횟수): 기본값 9번. 75초 간격으로 9번이나 찔렀는데(약 11분 소요) 끝끝내 대답이 없으면, "아 이 새끼 진짜 죽었구나!" 하고 RST 패킷을 내부적으로 날려버리고 점유하던 소켓(포트)을 영구 삭제해 버린다.

2. 가짜 패킷(Probe)의 정체

  • 킵얼라이브 패킷은 와이어샤크(Wireshark)에서 보면 아주 기괴하게 생겼다.
  • 데이터 알맹이는 0바이트이거나 쓰레기 1바이트다.
  • 그리고 시퀀스 넘버(Seq)를 현재 진짜 번호보다 1 뺀 번호(-1)로 고의로 틀리게 적어서 날린다.
  • 상대방 컴퓨터는 "어? 너 아까 1000번까지 불렀잖아. 왜 갑자기 지나간 999번을 부르고 지랄이야? 1000번 내놔 임마!"라며 화가 나서 즉각 ACK 1000 (나 살아있음!) 영수증을 반사적으로 쏘게 된다. 이 꼼수를 이용해 데이터 송수신 없이 상대방의 생사만 귀신같이 캐내는 것이다.
 ┌─────────────────────────────────────────────────────────────┐
 │                AWS/클라우드 환경에서의 Keep-Alive 실무 튜닝        │
 ├─────────────────────────────────────────────────────────────┤
 │                                                             │
 │   [ 상황: AWS 클라우드의 로드밸런서(ELB)를 거치는 웬앱 ]             │
 │                                                             │
 │   * 아마존 ELB(로드밸런서)의 가차 없는 룰:                          │
 │     "내 앞을 지나는 놈들, 60초(Idle Timeout) 동안 대화 없으면 무조건 컷!" │
 │                                                             │
 │   * 리눅스 기본 설정(2시간)의 대참사:                             │
 │     웹서버 왈: "난 2시간 동안 입 닫고 기다릴게~"                    │
 │     ELB 왈: "60초 지났네? 너네 접속 끊어버려! (세션 강제 종료)"         │
 │     웹서버: "어? 왜 갑자기 연결이 끊겼지?? (연결 끊김 장애 폭주)"       │
 │                                                             │
 │   ▶ "이 장애를 막기 위해, 리눅스 커널의 keepalive_time 값을 2시간에서  │
 │      강제로 40초나 50초로 대폭 줄여서(Tuning), ELB가 썰어버리기 전에   │
 │      미리 헛기침(Keep-alive)을 하도록 무조건 멱살을 잡아야 한다!"     │
 └─────────────────────────────────────────────────────────────┘

3. 애플리케이션 계층(L7)의 Keep-Alive

  • 주의: HTTP/1.1 헤더에 붙어있는 Connection: keep-alive 와 방금 배운 TCP 계층(L4)의 Keep-Alive는 이름만 똑같지 완전히 다른 기술이다.
  • TCP 킵얼라이브는 상대방이 살아있는지 찔러보는 생사(Zombie) 확인용 깡통 패킷이고, HTTP 킵얼라이브는 웹페이지 사진 10장 받을 때마다 3-Way Handshake 10번 하지 말고 "우리 한 번 맺은 연결(터널) 끊지 말고 계속 사진이나 넘기자!"라며 터널 자체를 안 끊고 유지(재활용)하는 목적으로 쓰인다.

📢 섹션 요약 비유: TCP Keep-Alive는 줌(Zoom) 화상회의 중에 상대방 화면이 가만히 멈춰있을 때, 이게 상대가 생각 중인 건지 아니면 인터넷이 끊긴 건지 알 수 없어서 **"저기요, 제 말 들리세요?"**라고 마이크로 툭 찔러보는 안부 확인 기능과 완벽히 일치합니다.