Dev Tools & Workflow

프로덕션에서 리디렉션과 HTTP 헤더를 디버깅하기 위한 작은 툴킷

클라이언트와 서버 사이에서 실제로 무슨 일이 일어나는지 보여주는 다섯 가지 명령줄 도구와 브라우저 기법

The Wux Webtools Team The Wux Webtools Team 12 읽기 최소 시간 AI 지원, 인간 검토
Split-screen illustration showing terminal with HTTP headers on left and browser network panel on right
목차
  1. 프로덕션에서 HTTP 디버깅이 어려운 이유
  2. curl: 기본 도구
  3. httpie: 더 나은 기본값을 가진 curl
  4. Browser DevTools: Network 탭
  5. mitmproxy: 가로채기 프록시
  6. webpagetest: 프로덕션 관점
  7. 헤더가 거짓말을 할 때
  8. 리디렉션 루프 문제
  9. 먼저 확인할 것
  10. 핵심 요점
  11. FAQ
  12. Sources

프로덕션에서 HTTP 디버깅이 어려운 이유

대부분의 HTTP 문제는 브라우저에서 보이지 않습니다. 리디렉션 체인이 조용히 실패하고, 캐시 헤더는 문자 하나 차이로 잘못되며, CORS 정책은 설명 없이 요청을 차단합니다. 브라우저의 개발자 도구는 대화의 결과를 보여주지만, 문제를 일으킨 원시 교환은 종종 숨깁니다.

이 점은 프로덕션에서 특히 중요합니다. 무엇이 바뀌었는지 확인하려고 로깅을 추가하거나 서비스를 재시작할 수 없기 때문입니다. 필요한 것은 실제 HTTP 대화, 즉 요청 헤더, 응답 헤더, 상태 코드, 리디렉션 대상, 타이밍을 보여주는 도구입니다. 그 일을 안정적으로 해내는 다섯 가지 도구와 이를 보완하는 브라우저 기법을 소개합니다.

curl: 기본 도구

curl은 가장 먼저 사용할 도구입니다. 브라우저의 해석을 거치지 않고 서버가 보낸 내용을 정확히 보여주기 때문입니다.

본문 없이 응답 헤더만 보려면:

curl -I https://example.com

리디렉션을 따라가며 각 단계를 보려면:

curl -L -v https://example.com

-v 플래그(verbose)는 모든 헤더를 포함한 전체 요청과 응답을 보여줍니다. -L 플래그는 리디렉션을 자동으로 따라갑니다. 함께 사용하면 전체 리디렉션 체인을 볼 수 있으며, 대부분의 프로덕션 문제가 바로 여기에 있습니다.

리디렉션 위치만 보려면:

curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" -L https://example.com

전체 헤더의 잡음 없이 리디렉션 체인을 검증해야 할 때 유용합니다. -w 플래그는 출력 형식을 지정해 상태 코드와 체인에서 다음 URL만 보여줍니다.

curl은 사용자 지정 헤더도 보낼 수 있습니다. 이는 CDN 동작, 인증, API 엔드포인트를 테스트할 때 필수적입니다.

curl -H "Authorization: Bearer token" -H "Accept: application/json" https://api.example.com

httpie: 더 나은 기본값을 가진 curl

httpiecurl과 같은 일을 하는 Python 도구이지만, 기억하기 쉬운 문법과 읽기 쉬운 출력을 제공합니다. 대체재는 아닙니다. curl이 더 강력하고 더 널리 설치되어 있습니다. 하지만 빠른 확인에는 httpie가 더 빠릅니다.

헤더를 보려면:

http HEAD https://example.com

리디렉션을 따라가려면:

http --follow --all https://example.com

--all 플래그는 최종 응답뿐 아니라 리디렉션 체인의 모든 응답을 보여줍니다. 이는 curl -L -v에 해당하지만, 출력에 색상이 적용되어 훑어보기 쉽습니다.

JSON을 보내려면:

http POST https://api.example.com name=value

httpie는 기본적으로 JSON을 가정하므로 API를 테스트할 때 입력을 줄일 수 있습니다. 또한 응답을 보기 좋게 출력하므로 잘못된 형식의 헤더나 예상치 못한 값을 더 쉽게 찾을 수 있습니다.

Browser DevTools: Network 탭

문제가 브라우저에서만 발생한다면 브라우저의 Network 탭에서 시작해야 합니다. 이 탭은 curl과 같은 정보를 보여주지만, 브라우저의 해석도 함께 보여줍니다. 요청을 차단했는지, 캐싱을 어떻게 처리했는지, 쿠키를 보냈는지 등을 확인할 수 있습니다.

전체 요청 및 응답 헤더를 보려면 Network 탭에서 아무 요청이나 클릭한 다음 Headers 섹션을 확인합니다. "Raw" 보기는 헤더를 전송된 그대로, 형식 변경 없이 보여줍니다.

리디렉션 체인을 보려면 3xx 상태 코드를 가진 요청을 찾습니다. 브라우저는 이를 최종 요청 아래에 묶지만, 확장하면 각 단계를 볼 수 있습니다. 여기에서 리디렉션 루프, 누락된 Location 헤더, 잘못된 도메인을 가리키는 리디렉션을 찾을 수 있습니다.

타이밍을 보려면 아무 요청에서든 Timing 탭을 확인합니다. 브라우저가 DNS 조회, TCP 연결, TLS 핸드셰이크, 서버 응답 대기에 얼마나 시간을 썼는지 보여줍니다. 리디렉션이 느리다면 Timing 탭이 문제가 네트워크 지연인지 서버 처리인지 알려줍니다.

한 가지 제한이 있습니다. 브라우저는 보안상의 이유로 일부 헤더를 숨깁니다. Set-Cookie 헤더는 보이지만 실제 쿠키 값은 가려집니다. Authorization 헤더는 때때로 완전히 숨겨집니다. 이를 확인해야 한다면 curl을 사용하세요.

mitmproxy: 가로채기 프록시

mitmproxy는 브라우저와 서버 사이에 위치해 모든 요청과 응답을 실시간으로 보여주는 Python 도구입니다. curl보다 복잡하지만, 브라우저가 자동으로 추가하는 헤더를 포함해 브라우저가 실제로 보내는 내용을 보여주는 유일한 도구입니다.

시작하려면:

mitmproxy

그런 다음 브라우저가 HTTP 프록시로 localhost:8080을 사용하도록 설정합니다. mitmproxy는 터미널 인터페이스에서 모든 요청을 보여줍니다. 헤더를 검사하고, 전송 전에 요청을 수정하거나, 다른 매개변수로 요청을 다시 실행할 수 있습니다.

이는 브라우저에서만 발생하는 문제를 디버깅할 때 유용합니다. CORS preflight 요청, 쿠키 처리, 특정 헤더가 있을 때 실패하는 요청 등이 여기에 해당합니다. 또한 mitmproxy가 해당 환경을 시뮬레이션할 수 있으므로, 회사 프록시나 VPN 뒤에서 사이트가 어떻게 동작하는지 테스트할 때도 유용합니다.

단점은 설정이 복잡하다는 점입니다. mitmproxy가 HTTPS 트래픽을 가로챌 수 있도록 루트 인증서를 설치해야 하며, 브라우저가 프록시를 사용하도록 설정해야 합니다. 빠른 확인에는 curl이 더 빠릅니다. 깊이 있는 디버깅에는 mitmproxy가 설정 시간을 들일 가치가 있습니다.

webpagetest: 프로덕션 관점

WebPageTest는 여러 위치의 실제 브라우저에서 페이지를 로드하고 전체 HTTP 대화를 보여주는 무료 서비스입니다. curl보다 느리지만 CDN 동작, DNS 해석, TLS 협상을 포함해 실제 사용자가 경험하는 것을 보여줍니다.

"Request Headers"와 "Response Headers" 보기는 브라우저가 정확히 무엇을 보내고 받았는지 보여줍니다. "Waterfall" 보기는 리디렉션을 포함한 모든 요청의 타이밍을 보여줍니다. 특정 지역이나 특정 네트워크에서만 발생하는 문제를 여기에서 찾을 수 있습니다.

WebPageTest는 메인 문서의 리디렉션 체인도 보여줍니다. 대부분의 리디렉션 문제가 바로 여기에 있습니다. 사이트가 http://에서 https://로, 다시 www.에서 non-www.로, 다시 /에서 /en/으로 리디렉션된다면 WebPageTest는 세 단계를 모두 보여주고 각 단계에 걸린 시간도 알려줍니다.

이러한 HTTP 기본 요소를 검증하고 최적화하는 데 도움이 되는 도구가 필요하다면 Wux Webtools는 여러 유틸리티를 제공합니다. 헤더 분석기와 리디렉션 검사기를 포함해 모두 브라우저에서만 실행되며, 모든 처리를 클라이언트 측에서 수행해 개인정보를 보호합니다.

헤더가 거짓말을 할 때

가장 어려운 HTTP 문제는 서버가 모순된 헤더를 보낼 때 발생합니다. Cache-Control 헤더는 no-cache라고 말하지만 Expires 헤더는 리소스가 1년 동안 유효하다고 말할 수 있습니다. Location 헤더는 상대 URL을 가리키지만 Content-Location 헤더는 다른 곳을 가리킬 수 있습니다. 브라우저는 어느 쪽을 신뢰할지 추측해야 하며, 브라우저마다 다르게 추측합니다.

이런 일이 발생하면 서버가 보낸 순서대로 원시 헤더를 확인해야 합니다. curl -v가 이를 해냅니다. mitmproxy도 마찬가지입니다. 브라우저의 DevTools는 가독성을 위해 헤더 순서를 재정렬하는 경우가 있어 문제를 숨길 수 있습니다.

또 다른 흔한 문제는 애플리케이션이 아니라 CDN이나 로드 밸런서가 추가한 헤더입니다. 캐싱 문제를 디버깅한다면 Cache-Control 헤더가 앱에서 온 것인지 CDN에서 온 것인지 알아야 합니다. curl은 최종 결과를 보여주지만 각 헤더가 어디에서 왔는지는 알려주지 않습니다. 이를 확인하려면 CDN을 우회해 원본 서버를 직접 호출하고 헤더를 비교해야 합니다.

리디렉션 루프 문제

리디렉션 루프는 프로덕션에서 가장 흔한 HTTP 문제입니다. 두 서버가 URL이 어디를 가리켜야 하는지에 대해 서로 다를 때 발생합니다. CDN은 원본으로 리디렉션하고, 원본은 다시 CDN으로 리디렉션합니다. 또는 로드 밸런서는 HTTP를 HTTPS로 리디렉션하지만, 앱은 X-Forwarded-Proto 헤더를 보지 못해 HTTPS를 다시 HTTP로 리디렉션합니다.

이를 디버깅하려면 각 단계의 Location 헤더를 포함해 전체 리디렉션 체인을 확인해야 합니다. curl -L -v가 이를 해내지만, 무한 루프를 막기 위해 50번의 리디렉션 후 중단합니다. 이 제한에 도달했다면 리디렉션 루프가 있는 것입니다.

해결책은 대개 설정 변경입니다. 앱이 X-Forwarded-Proto 헤더를 신뢰하도록 하거나, 이미 HTTPS인 요청을 CDN이 더 이상 리디렉션하지 않도록 설정합니다. 하지만 루프를 보기 전에는 고칠 수 없습니다. 브라우저는 포기하기 전에 몇 개 이상의 리디렉션을 보여주지 않습니다.

먼저 확인할 것

프로덕션에서 무언가 깨졌다면 다음 순서로 확인하세요.

  1. 상태 코드: 예상한 값인가요? 301은 영구, 302는 임시, 307은 HTTP 메서드를 보존합니다. 잘못된 코드를 보고 있다면 문제는 리디렉션 설정에 있습니다.
  1. Location 헤더: 올바른 곳을 가리키나요? 절대 URL인가요, 상대 URL인가요? 상대 URL은 현재 URL을 기준으로 해석되므로, 기준 URL이 생각한 것과 다르면 예상치 못한 결과가 나올 수 있습니다.
  1. 캐시 헤더: 브라우저가 리디렉션을 캐싱하고 있나요? 301 리디렉션은 기본적으로 캐시됩니다. 즉 잘못 설정된 리디렉션은 수정한 뒤에도 몇 시간 동안 사이트를 깨뜨릴 수 있습니다. Cache-ControlExpires 헤더를 확인해 브라우저가 리디렉션을 얼마나 오래 기억할지 확인하세요.
  1. CORS 헤더: 요청이 교차 출처라면 서버가 올바른 Access-Control-Allow-Origin 헤더를 보내나요? 그렇지 않으면 브라우저가 요청을 차단하고 콘솔에 CORS 오류가 표시됩니다. 이를 고칠 수 있는 곳은 서버의 응답 헤더뿐입니다. 브라우저에서 우회할 수는 없습니다.
  1. 타이밍: 요청에 얼마나 걸렸나요? 느리다면 네트워크 지연인가요, 서버 처리인가요? 브라우저의 DevTools와 WebPageTest는 모두 시간이 어디에 쓰였는지 알려주는 타이밍 분석을 보여줍니다.

개인정보 보호와 헤더를 둘러싼 브라우저 동작이 어떻게 바뀌었는지 더 깊이 살펴보려면 2026년에 쿠키에 무엇이 바뀌었고 어떻게 대응해야 하는지를 참고하세요. 최근 브라우저 업데이트가 헤더와 동의에 미친 영향을 다룹니다.

핵심 요점

  • curl -L -v는 브라우저의 해석 없이 전체 리디렉션 체인과 모든 헤더를 보여줍니다
  • 브라우저의 Network 탭은 캐싱 및 CORS 판단을 포함해 브라우저가 응답으로 무엇을 했는지 보여줍니다
  • mitmproxy는 브라우저가 자동으로 추가하는 헤더를 포함해 브라우저가 무엇을 보냈는지 보여줍니다
  • WebPageTest는 CDN 동작과 지역별 차이를 포함해 실제 사용자가 경험하는 것을 보여줍니다
  • 리디렉션 루프와 모순된 헤더는 가장 흔한 프로덕션 문제이며, 원시 HTTP 검사 없이는 보이지 않습니다

FAQ

Q: curl이 브라우저와 다른 헤더를 보여주는 이유는 무엇인가요?

A: 브라우저가 헤더(User-Agent, Accept, Cookie)를 자동으로 추가하고 캐싱과 CORS에 대해 자체 규칙을 따르기 때문입니다. curl은 사용자가 보내라고 지정한 것만 보냅니다. 브라우저가 실제로 보내는 것을 보려면 mitmproxy나 브라우저의 DevTools를 사용하세요.

Q: 일부 사용자에게만 발생하는 리디렉션은 어떻게 디버깅하나요?

A: 리디렉션이 사용자가 보내는 헤더에 의존하는지 확인하세요. 예를 들어 User-Agent, Accept-Language, Cookie, 또는 IP 주소(X-Forwarded-For를 통해)가 있습니다. curl로 사용자가 보낸 것과 같은 헤더를 보내거나, WebPageTest를 사용해 사용자의 위치에서 페이지를 로드하세요.

Q: 301과 302 리디렉션의 차이는 무엇인가요?

A: 301은 영구적이며 브라우저에 리디렉션을 캐시하라고 알립니다(때로는 영원히). 302는 임시적이며 브라우저에 캐시하지 말라고 알립니다. 무엇을 써야 할지 확실하지 않다면 302를 사용하세요. 나중에 언제든 301로 바꿀 수 있습니다.

Q: curl에서는 리디렉션이 동작하는데 브라우저에서는 동작하지 않는 이유는 무엇인가요?

A: 아마도 브라우저가 오래된 리디렉션을 캐싱하고 있거나, CORS 또는 혼합 콘텐츠 규칙 때문에 브라우저가 리디렉션을 차단하고 있기 때문일 수 있습니다. 브라우저의 DevTools 콘솔에서 오류를 확인하고, Cache-Control 헤더를 확인해 브라우저가 캐시된 응답을 사용하는지 살펴보세요.

Q: CDN이 추가하는 헤더는 어떻게 확인하나요?

A: curl로 CDN URL을 호출한 다음, 다시 curl로 원본 서버를 직접 호출합니다(CDN 우회). 헤더를 비교하세요. 첫 번째 응답에만 나타나는 헤더가 CDN에서 온 것입니다.

<!-- tool-cta:start -->

💡 사용해 보세요: 리디렉션 문제를 추적할 때 Redirect Checker는 전체 체인을 추적하고 각 홉의 상태 코드와 헤더를 표시합니다.

<!-- tool-cta:end -->

Sources

Decision tree for choosing curl, httpie, DevTools, mitmproxy, or WebPageTest based on the HTTP debugging problem
InfographicChoose the right HTTP debugging tool — A quick route from the symptom to the tool most likely to expose the raw HTTP conversation
Comparison table showing five HTTP debugging tools, what each is best for, and its main tradeoff
InfographicHTTP debugging tools compared — Each tool exposes a different layer of the request, from raw headers to real-user timing
Diagram of a redirect loop where a CDN redirects to the origin and the origin redirects back to the CDN
InfographicAnatomy of a redirect loop — Redirect loops usually come from two layers disagreeing about the canonical URL

자주 묻는 질문

curl이 브라우저와 다른 헤더를 보여주는 이유는 무엇인가요?
브라우저가 헤더(`User-Agent`, `Accept`, `Cookie`)를 자동으로 추가하고 캐싱과 CORS에 대해 자체 규칙을 따르기 때문입니다. `curl`은 사용자가 보내라고 지정한 것만 보냅니다. 브라우저가 실제로 보내는 것을 보려면 `mitmproxy`나 브라우저의 DevTools를 사용하세요.
일부 사용자에게만 발생하는 리디렉션은 어떻게 디버깅하나요?
리디렉션이 사용자가 보내는 헤더에 의존하는지 확인하세요. 예를 들어 `User-Agent`, `Accept-Language`, `Cookie`, 또는 IP 주소(`X-Forwarded-For`를 통해)가 있습니다. `curl`로 사용자가 보낸 것과 같은 헤더를 보내거나, WebPageTest를 사용해 사용자의 위치에서 페이지를 로드하세요.
301과 302 리디렉션의 차이는 무엇인가요?
301은 영구적이며 브라우저에 리디렉션을 캐시하라고 알립니다(때로는 영원히). 302는 임시적이며 브라우저에 캐시하지 말라고 알립니다. 무엇을 써야 할지 확실하지 않다면 302를 사용하세요. 나중에 언제든 301로 바꿀 수 있습니다.
curl에서는 리디렉션이 동작하는데 브라우저에서는 동작하지 않는 이유는 무엇인가요?
아마도 브라우저가 오래된 리디렉션을 캐싱하고 있거나, CORS 또는 혼합 콘텐츠 규칙 때문에 브라우저가 리디렉션을 차단하고 있기 때문일 수 있습니다. 브라우저의 DevTools 콘솔에서 오류를 확인하고, `Cache-Control` 헤더를 확인해 브라우저가 캐시된 응답을 사용하는지 살펴보세요.
CDN이 추가하는 헤더는 어떻게 확인하나요?
`curl`로 CDN URL을 호출한 다음, 다시 `curl`로 원본 서버를 직접 호출합니다(CDN 우회). 헤더를 비교하세요. 첫 번째 응답에만 나타나는 헤더가 CDN에서 온 것입니다.

출처 및 추가 읽기

  1. curl documentation
  2. HTTPie documentation
  3. MDN Web Docs: HTTP redirections
  4. WebPageTest documentation
저자에 대하여
The Wux Webtools Team

마지막 업데이트:

계속 읽기