배포가 성공적으로 끝났다는 CI 로그만으로는 실제 사용자가 페이지를 볼 수 있는지 알 수 없다. 캐시가 이전 버전을 물고 있거나, 정적 파일 하나가 누락되거나, 헬스체크 엔드포인트는 살아있는데 실제 콘텐츠는 깨진 경우가 흔하다. 이 글은 curl 하나로 HTTP 상태 코드와 페이지 핵심 콘텐츠를 동시에 검증하는 스모크 테스트 스크립트를 구성하는 방법을 정리한다.
스모크 테스트가 헬스체크와 다른 이유
/healthz 같은 헬스체크 엔드포인트는 대개 “프로세스가 떠 있다”만 확인한다. 반면 스모크 테스트는 배포 직후 실제 라우트가 기대한 응답을 주는지, 페이지 안에 있어야 할 문자열이 실제로 있는지까지 본다. 배포 파이프라인에서 흔히 발생하는 실패 유형은 다음과 같다.
- 리버스 프록시나 CDN이 이전 버전을 캐싱해 새 배포가 반영되지 않음.
- 정적 자산 경로가 바뀌어 200은 오지만 CSS/JS가 깨짐.
- 환경 변수 누락으로 특정 페이지만 500을 반환.
- 리다이렉트 체인이 예상과 달라 최종 목적지가 틀림.
이런 문제는 상태 코드만 봐서는 못 잡는 경우가 많다. 실제로 배포 직후 확인이 “성공 응답을 그대로 믿지 않는” 습관으로 굳어지는 과정은 발행 성공 응답은 공개 관측이 아니다 글에서 다룬 것과 같은 원리다 — API가 200을 반환했다는 것과 실제로 공개된 것은 별개다.
curl로 상태 코드 검증하기
curl 공식 매뉴얼에 따르면 -w/--write-out 옵션으로 응답 본문과 별개로 상태 코드·타이밍 정보를 원하는 포맷으로 뽑아낼 수 있다. -o /dev/null로 본문을 버리고 상태 코드만 받으면 스크립트에서 다루기 쉽다.
status=$(curl -s -o /dev/null -w "%{http_code}" "https://example.com/")
if [ "$status" != "200" ]; then
echo "FAIL: expected 200, got $status"
exit 1
fi
echo "OK: $status"리다이렉트를 따라가야 하는 페이지라면 -L을, 최종 도달 URL까지 확인하려면 -w "%{url_effective}"를 추가한다. 인증이 필요한 관리자 페이지는 -H "Authorization: Bearer ..."로 토큰을 실어 보내되, 토큰 값은 스크립트에 하드코딩하지 말고 환경 변수나 시크릿 저장소에서 주입한다.
핵심 콘텐츠까지 확인하기
상태 코드가 200이어도 본문이 깨졌을 수 있다. MDN HTTP 상태 코드 문서가 설명하듯 200은 “요청이 성공했고 본문이 전달됐다”는 뜻일 뿐, 그 본문의 내용까지 보장하지 않는다. 그래서 배포 직후 확인해야 할 페이지마다 반드시 있어야 할 고유 문자열(타이틀, 버전 마커, 특정 컴포넌트의 텍스트)을 grep으로 검증하는 단계를 추가한다.
#!/usr/bin/env bash
set -euo pipefail
check() {
local url="$1" expect="$2"
local body status
body=$(curl -s -w "\n%{http_code}" "$url")
status=$(echo "$body" | tail -n1)
body=$(echo "$body" | sed '$d')
if [ "$status" != "200" ]; then
echo "FAIL [$url]: HTTP $status"
return 1
fi
if ! echo "$body" | grep -q "$expect"; then
echo "FAIL [$url]: missing marker '$expect'"
return 1
fi
echo "OK [$url]"
}
check "https://example.com/" "