리눅스 네트워크 진단 · HTTP 진단 · 이론
curl 은 구간을 나눠서 알려 준다
한 줄 요약
curl -w 의 타이밍 변수를 쓰면 한 번의 요청으로 이름 해석 / 연결 / TLS / 서버 처리 중 어디가 느린지 갈라낼 수 있다. 이 한 줄이 "네트워크 탓이냐 애플리케이션 탓이냐" 논쟁을 끝낸다.
왜 이게 필요했나
배포 직후 응답이 느려졌다. 인프라 팀은 애플리케이션 문제라 하고, 개발 팀은 네트워크 문제라 한다. 양쪽 다 자기 대시보드에서는 정상으로 보인다.
이 상황에서 필요한 것은 더 많은 대시보드가 아니라 한 요청의 시간을 구간별로 쪼개 보는 것이다.
curl -sS -o /dev/null -w 'dns:%{time_namelookup} conn:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer} total:%{time_total}\n' https://api.example.com/health각 값은 요청 시작부터의 누적 시간이라 차이를 보면 각 구간의 소요가 나온다. 해석 규칙은 명확하다.
| 어디가 크나 | 결론 |
| --- | --- |
| time_namelookup | 이름 해석 문제. DNS 구간으로 |
| time_connect - time_namelookup | TCP 연결. 경로나 방화벽 |
| time_appconnect - time_connect | TLS 핸드셰이크. 인증서 체인, 프로토콜 협상 |
| time_starttransfer - time_appconnect | 서버가 첫 바이트를 만드는 시간. 애플리케이션 |
| time_total - time_starttransfer | 본문 전송. 크기나 대역폭 |
time_connect 까지 정상인데 time_starttransfer 만 크면 네트워크는 무고하다. 그 자리에서 논쟁이 끝난다.
어떻게 동작하나
상태코드만 뽑기. curl -s -o /dev/null -w '%{http_code}' URL 은 본문을 버리고 상태코드만 출력한다. 헬스체크 스크립트의 기본형이다. 연결 자체가 실패하면 000 이 나온다 - 이 값을 별도로 처리해야 "서버가 5xx 를 냈다"와 "서버에 닿지 못했다"를 구분할 수 있다.
헤더만 받기. curl -sI URL 은 HEAD 요청을 보내 헤더만 받는다. Content-Length 가 기대와 다르면 캐시나 프록시가 끼어 있을 수 있다.
리다이렉트. curl 은 기본적으로 리다이렉트를 따라가지 않는다. -L 을 붙여야 따라간다. 그래서 같은 URL 에 대해 -L 없이는 301, 붙이면 200 이 나오는 것이 정상이다. 헬스체크에서 이걸 모르면 "왜 301 이 나오지"로 시간을 쓴다.
타임아웃은 선택이 아니다. --max-time 없이 헬스체크를 돌리면 상대가 응답하지 않을 때 그 스크립트가 영원히 멈춘다. 크론이 5분마다 이런 스크립트를 띄우면 프로세스가 쌓인다. 헬스체크에는 반드시 최대 대기 시간을 건다.
현장에서 만나는 모습
로컬에서 재현하기. 네트워크가 막힌 환경에서도 python3 -m http.server 하나면 HTTP 동작 대부분을 재현할 수 있다. 상태코드, 헤더, 리다이렉트, 미구현 메서드 응답까지 실제 그대로다. 실습이 이 방식을 쓰는 이유이기도 하고, 실무에서도 클라이언트 코드를 검증할 때 자주 쓴다.
JSON 응답은 jq 로 자른다. curl -s URL | jq -r '.items | length' 처럼 파이프로 이으면 스크립트에서 값을 바로 꺼낼 수 있다. 다만 curl 이 실패했을 때 jq 가 빈 입력을 받아 조용히 넘어가는 함정이 있으므로, 스크립트에서는 set -o pipefail 이 필요하다.
헬스체크 스크립트의 계약. 좋은 헬스체크는 세 가지를 구분해서 알려 준다 - 정상(2xx), 응답은 왔지만 비정상(4xx/5xx), 아예 닿지 못함(연결 실패). 셋을 하나의 실패로 뭉치면 알람을 받고도 어디부터 봐야 할지 모른다.
다음 실습에서 할 것
로컬에 HTTP 서버를 띄우고 상태코드·헤더·타이밍·JSON 을 각각 뽑아 본다. 리다이렉트를 따라갈 때와 아닐 때의 차이, 미구현 메서드의 응답을 직접 확인하고, 마지막에는 세 가지 상황을 구분해 보고하는 헬스체크 스크립트를 만든다.