macOS TCP 버그를 보며 든 생각: Mac도 오래 켜둘 거면 서버처럼 운영해야 한다
최근 본 macOS 커널 버그 이야기 중에서 특히 인상적이었던 건, 정확히 약 49일 17시간 정도 연속 가동한 뒤 새 TCP 연결이 더 이상 열리지 않는 문제였다. ping은 되는데 새 연결은 안 열리고, 기존 연결은 살아 있고, 결국 재부팅 전에는 복구가 안 된다는 설명을 보면 꽤 섬뜩하다.
표면적으로는 32비트 카운터 오버플로우 버그다. 그런데 이 이야기가 더 흥미로운 이유는 단순히 “옛날식 정수 오버플로우가 아직도 있네” 수준이 아니라, Mac을 오래 켜 두는 환경이 이미 생각보다 많아졌다는 점 때문이다.
이건 개인용 노트북 얘기보다 운영 환경 얘기에 가깝다
대부분의 일반 사용자 Mac은 49일 넘게 안 끄고 버티는 경우가 드물다. OS 업데이트도 하고, 잠깐씩 재시작도 하고, 절전도 걸고, 이동도 한다. 그래서 이런 버그는 실제 체감이 거의 없을 수 있다.
문제는 다른 쪽이다.
- Mac mini 빌드팜
- macOS CI 러너
- iOS/macOS 앱 빌드 서버
- 원격 코로케이션 Mac
- 장시간 렌더링/컴파일 워크스테이션
- 무중단 모니터링/자동화 머신
이런 환경에서는 Mac이 더 이상 “데스크톱”이 아니다. 사실상 서버다. 그런데 운영 습관은 여전히 데스크톱처럼 가져가는 경우가 많다. 바로 그 틈에서 이런 문제가 크게 보이기 시작한다.
왜 이 버그가 더 무서워 보이냐
이 사례가 무서운 건 장애 증상이 아주 직관적이지 않기 때문이다.
- 머신은 살아 있음
- ping도 됨
- 기존 TCP 연결도 유지됨
- 그런데 새 TCP 연결만 안 열림
이러면 처음엔 네트워크 전체가 죽은 것처럼 보이지 않는다. 방화벽 문제인가, 특정 서비스 문제인가, DNS 문제인가, 커널 소켓 자원 문제인가 하면서 원인을 엉뚱한 데서 찾기 쉽다.
운영자 입장에서는 이런 종류의 장애가 제일 피곤하다. 완전히 죽어버리면 오히려 빨리 재부팅하거나 failover를 걸면 되는데, 이렇게 부분적으로만 망가지는 장애는 진단 시간을 길게 끈다.
결국 핵심은 tcp_now가 멈춘다는 점이다
기술적으로 보면 포인트는 비교적 단순하다. 부팅 이후 경과 시간을 밀리초 단위로 세는 32비트 카운터가 오버플로우 지점에서 감기고, 그 뒤 시계가 뒤로 가지 않게 하려던 보호 로직 때문에 값이 갱신되지 못한 채 멈춘다.
시계가 멈추면 TCP가 내부적으로 기대하는 시간 기반 정리 작업들이 같이 꼬인다. 특히 TIME_WAIT 회수가 안 되기 시작하면, 시간이 갈수록 소켓 상태가 쌓이고, 결국 새 연결을 열 수 없는 방향으로 간다.
설명 자체는 전형적인 오버플로우 버그 같지만, 실서비스에서는 결과가 꽤 현실적이다.
- 처음엔 조용함
- 새 연결 실패가 늘어남
- TIME_WAIT가 줄지 않음
- SYN_SENT 같은 상태도 쌓임
- 로드가 올라감
- 결국 재부팅하기 전엔 정상 회복이 어려움
즉, 오류 하나가 네트워크 스택 내부에서 천천히 시스템을 질식시키는 패턴에 가깝다.
Mac 인프라가 늘수록 이런 버그는 더 중요해진다
예전엔 macOS 커널 버그가 나와도 꽤 많은 사람에게는 “특수한 경우”로 보였을 수 있다. 그런데 지금은 다르다.
애플 플랫폼 개발을 하는 팀은 점점 더 많이 아래 환경을 갖고 있다.
- 셀프호스트 macOS 러너
- Xcode 빌드 머신
- 테스트 자동화 Mac
- 서명/배포 전용 Mac
- iOS 디바이스 팜과 연결된 제어용 Mac
즉 macOS는 점점 더 운영 인프라 안으로 들어오고 있다. 이 흐름에서는 커널 네트워크 버그가 더 이상 희귀한 데스크톱 에피소드가 아니라, 실제 배포 파이프라인 리스크가 된다.
여기서 얻는 교훈은 의외로 단순하다
이 사례를 보면 교훈은 생각보다 소박하다.
1. macOS 머신도 uptime을 봐야 한다
Linux 서버만 uptime을 보는 게 아니다. Mac mini 빌드 서버도 uptime이 길어지면 리스크가 된다.
2. 재부팅은 실패가 아니라 운영 작업이다
특히 장시간 무중단이 필요한 것처럼 보여도, 일정 주기 재부팅이 더 안전할 수 있다. “계속 안 꺼지는 것”이 좋은 운영은 아니다.
3. 부분 장애를 감지하는 체크가 필요하다
ping만 보면 놓친다. 새 TCP 연결이 실제로 열리는지, 특정 외부 대상에 소켓을 만들 수 있는지, TIME_WAIT나 SYN_SENT가 이상하게 쌓이지 않는지 보는 체크가 더 중요하다.
4. Mac도 서버처럼 장애 모델을 가져야 한다
- 재시작 스케줄
- 롤링 교체
- 헬스체크
- 장애 재현 기록
- 빌드팜 단위 대응
이런 관점이 점점 필요해진다.
OpenClaw나 자동화 머신에도 남 일은 아니다
이걸 읽으면서 든 생각 중 하나는, 이런 이슈가 꼭 Xcode 빌드팜에만 해당하는 건 아니라는 점이다. Mac 위에서 자동화 허브나 봇, 에이전트, 메시지 브리지, 장시간 돌아가는 작업기를 운영한다면 똑같이 영향을 받을 수 있다.
특히 아래 같은 구성은 생각보다 위험할 수 있다.
- 장시간 켜 둔 Mac mini
- 외부 API와 계속 TCP 연결을 여는 자동화 워커
- 여러 채널과 통신하는 메시지 허브
- 실패 복구보다 장시간 연속 가동에 기대는 운영
이럴수록 “Mac이니까 대충 괜찮겠지”보다, 이것도 결국 네트워크 의존 서버 프로세스라는 감각이 더 중요해진다.
지금 당장 현실적인 대응은 별로 화려하지 않다
이런 버그에 대한 대응은 대개 멋있지 않다.
- 일정 주기 재부팅
- uptime 기반 알림
- 새 TCP 연결 헬스체크 추가
- 장시간 미재부팅 머신 목록 추적
- 장애 시 빠르게 교체/재시작할 운영 절차 준비
화려한 해결책보다 이런 기본 운영이 실제로 더 중요하다. 특히 공식 패치가 나오기 전에는 더 그렇다.
결국 이건 버그 이야기이면서 운영 이야기다
겉으로 보면 32비트 오버플로우 버그 사례다. 하지만 내가 보기엔 더 중요한 메시지가 있다.
macOS도 이제는 꽤 자주 서버처럼 운영된다.
그러면 자연히 따라오는 질문도 바뀐다.
- 이 머신은 얼마나 오래 켜져 있었나
- 재부팅 정책은 있나
- 부분 네트워크 장애를 잡아낼 수 있나
- 빌드/자동화 파이프라인이 한 대의 Mac uptime에 과도하게 의존하고 있진 않나
이 질문을 하지 않으면, 이런 버그는 단순한 커널 이슈가 아니라 운영 사고로 이어지기 쉽다.
마무리
macOS 49일 TCP 버그 이야기를 보면서 든 생각은 단순하다. 이제 Mac을 오래 켜 둘 거라면, 특히 빌드 서버나 자동화 머신으로 쓸 거라면 데스크톱처럼 다루면 안 된다는 것이다.
정리하면 이렇다.
- 이 버그는 32비트 오버플로우지만, 영향은 실운영 장애로 이어진다
- 특히 새 TCP 연결만 죽는 부분 장애라 진단이 더 어렵다
- Mac mini 빌드팜, CI 러너, 자동화 머신은 이미 서버 성격이 강하다
- 그래서 macOS도 uptime, 재부팅, 헬스체크 관점으로 운영해야 한다
- 결국 중요한 건 패치만 기다리는 게 아니라 운영 습관을 바꾸는 일이다
이런 사례를 보면 결국 시스템의 성격은 OS 이름이 아니라 어떻게 쓰고 있느냐가 결정하는 것 같다는 생각이 든다. Mac도 오래, 반복적으로, 네트워크 중심으로 돌리기 시작하면 이미 서버다.
댓글남기기