클릭한 링크와 실제로 열리는 페이지가 다른 경우는 흔합니다. 그 사이에는 HTTPS 전환, 호스트 변경, 추적 서비스, URL 단축 서비스, 후행 슬래시를 붙이는 CMS 규칙 등이 끼어 있을 수 있으며, 하나하나가 브라우저가 알리지 않고 보내는 별도의 요청입니다.
이 가이드에서는 TrueURL, curl, 브라우저 개발자 도구(DevTools)로 이 단계들을 확인하는 방법, 리디렉션 체인의 각 부분이 뜻하는 내용, 그리고 가장 흔한 문제를 해결하는 방법을 설명합니다.
리디렉션 체인이란
리디렉션은 서버가 HTTP 3xx 상태 코드와 함께 다른 URL을 지정한 Location 헤더로 응답할 때 일어납니다. 그러면 브라우저나 크롤러 같은 클라이언트가 그 URL을 요청하고, 리디렉션이 아닌 응답을 받을 때까지 이 과정을 반복합니다.
요청 하나와 그에 대한 응답이 홉(리디렉션 한 단계) 하나를 이룹니다. 첫 URL부터 최종 응답까지 이어지는 전체 과정이 리디렉션 체인입니다.
# URL Status Location
1 http://example.com/Shoes 301 https://example.com/Shoes
2 https://example.com/Shoes 301 https://www.example.com/Shoes
3 https://www.example.com/Shoes 302 /shoes/
4 https://www.example.com/shoes/ 200페이지 하나에 도달하기 위해 리디렉션 3번, 요청 4번이 필요한 셈입니다. 3번째 홉의 Location은 상대 경로입니다. RFC 9110에 정해진 대로 클라이언트는 이를 방금 요청한 URL을 기준으로 해석하므로, 실제로는 https://www.example.com/shoes/를 뜻합니다. 이상적으로는 이 주소들이 모두 홉 한 번 만에 최종 URL에 도달해야 합니다.
페이지가 200 OK로 응답한 뒤 <meta http-equiv="refresh"> 태그나 JavaScript로 리디렉션하는 경우도 있습니다. 이런 클라이언트 측 리디렉션도 체인의 일부이지만, curl처럼 HTTP 헤더만 읽는 도구는 그 페이지에서 멈춥니다.
리디렉션을 확인해야 하는 이유
SEO: 표준 URL 신호와 크롤링 예산
검색엔진은 리디렉션을 어떤 URL을 색인해야 하는지 알려 주는 표시로 받아들입니다. Google은 영구 리디렉션(301, 308)을 대상 URL이 표준 URL이어야 한다는 강력한 신호로 취급하고, 임시 리디렉션(302, 303, 307)은 약한 신호로 취급합니다. 따라서 완전히 옮긴 페이지를 302로 리디렉션하면 검색결과에 예전 URL이 계속 남을 수 있습니다.
체인의 길이도 중요합니다. Googlebot은 리디렉션 홉을 최대 10개까지 따라가며, 그때까지 콘텐츠를 받지 못하면 Search Console에 리디렉션 오류가 보고됩니다. Google의 크롤링 예산(crawl budget) 가이드도 긴 리디렉션 체인은 크롤링에 부정적인 영향을 준다며 피하라고 권장합니다.
페이지 속도
마지막 리디렉션에 대한 응답이 와야 최종 페이지를 불러오기 시작할 수 있습니다. 홉마다 네트워크 왕복이 한 번씩 필요하고, 새 호스트로 가는 홉에는 DNS 조회와 새 연결, HTTPS라면 TLS 핸드셰이크까지 더해집니다. 모바일 환경에서는 리디렉션 3~4번만으로도 실제 페이지의 첫 바이트가 도착하기까지 수백 밀리초가 늘어날 수 있습니다. 리디렉션 지연 시간 측정 도구로 홉마다 걸리는 시간을 확인할 수 있습니다.
단축 링크와 낯선 링크의 보안
단축 링크와 이메일에 담긴 상당수의 추적 링크는 목적지를 숨깁니다. 피싱 공격은 잘 알려진 도메인의 오픈 리디렉션도 악용하므로, 신뢰할 수 있는 사이트에서 시작한 링크가 전혀 다른 곳에서 끝날 수도 있습니다. 단축 URL 원본 확인 도구를 사용하면 클릭하기 전에 거쳐 가는 모든 도메인과, HTTPS에서 일반 HTTP로 떨어지는 홉이 있는지 확인할 수 있습니다.
제휴 링크와 추적 링크
마케팅 링크는 랜딩 페이지에 도착하기 전에 여러 서비스를 거치는 경우가 많습니다. 각 서비스가 쿼리 문자열을 그대로 넘겨 주지 않으면 UTM 매개변수, 클릭 ID, 제휴 태그가 소리 없이 사라집니다. 최종 URL을 보면 이 값들이 살아남았는지, 링크가 여전히 의도한 페이지로 이어지는지 알 수 있습니다.
사이트 이전, HTTPS, 표준 호스트
사이트 개편, 도메인 이전, HTTPS 전환 후에는 모든 예전 URL이 영구 리디렉션 한 번으로 그에 대응하는 새 URL에 도달해야 합니다. 사이트의 기본 주소 4가지(http://와 https:// 각각에 www가 있는 주소와 없는 주소)도 모두 하나의 표준 주소로 이어져야 합니다. 이런 규칙은 소리 없이 깨집니다. 새 CDN 규칙, 플러그인 업데이트, 서버 이전만으로도 아무도 모르는 사이에 홉이나 루프가 추가될 수 있습니다.
TrueURL로 리디렉션 확인하는 방법
TrueURL은 모든 검사를 Cloudflare 엣지 네트워크에서 실행하므로, 믿기 어려운 링크도 브라우저로 열지 않고 살펴볼 수 있습니다. 홈페이지의 URL 리디렉션 검사 도구는 URL 하나를 검사하며, 리디렉션 체인 검사를 비롯한 다른 전용 도구들도 같은 엔진을 사용합니다.
1단계: URL 입력
URL을 붙여 넣고 검사를 실행하세요. 스킴을 생략하면 https://로 간주하므로, 일반 HTTP를 테스트하려면 http://를 직접 입력하세요.
2단계: 필요하면 고급 설정 조정
검사기는 기본적으로 최신 데스크톱 Chrome의 User-Agent(사용자 에이전트)로, 쿠키 없이, 리디렉션을 최대 20회까지 따라가는 GET 요청을 보냅니다. 고급 설정에서 이를 바꿀 수 있습니다.
- HTTP 메서드: GET, HEAD, POST 중에서 고릅니다. HEAD는 더 가볍지만 일부 서버는 HEAD에 다르게 응답하며, 본문이 없으므로 클라이언트 측 리디렉션을 감지할 수 없습니다. POST는 입력한 요청 본문을 보내므로 폼 처리기나 API를 테스트할 때 사용합니다. 이후 홉은 브라우저 규칙을 따릅니다. POST 이후 301이나 302는 GET으로 이어지고, 303은 언제나 GET으로 이어지며, 307과 308은 메서드와 본문을 그대로 유지합니다.
- 최대 홉 수: 따라갈 리디렉션 수로, 1~50 사이에서 정합니다. 기본값 20은 Fetch Standard와 Chrome, Firefox의 제한과 같습니다. 체인이 Googlebot의 제한 안에 드는지 보려면 10으로 설정하세요.
- 사용자 지정 User-Agent: 비워 두면 데스크톱 Chrome으로 요청합니다. 프리셋으로 iPhone Safari, Android Chrome, Googlebot(스마트폰·데스크톱), Bingbot, Facebook과 X의 링크 미리보기 봇, curl이 있습니다.
- 사용자 지정 요청 헤더: 모든 홉에 함께 보내는 추가 헤더입니다. 예를 들어 언어별 리디렉션을 일으키려면
Accept-Language: fr-FR을 넣습니다. - 쿠키:
name=value; other=value형식으로 입력하면 로그인, 동의, 지역 설정 상태를 재현할 수 있습니다. 체인 도중에 설정된 쿠키는 브라우저와 마찬가지로 이후 홉에서도 유지됩니다. - 클라이언트 측 리디렉션: meta refresh 태그와 간단한 JavaScript 리디렉션을 따라갈지, 감지해서 표시만 할지 선택합니다.
- SSL 오류 무시: Cloudflare 엣지는 항상 인증서를 검증하므로 이 옵션으로 문제가 있는 인증서를 건너뛸 수는 없습니다. TLS 오류는 오류가 발생한 홉에 표시됩니다.
3단계: 결과 읽기
결과 맨 위에는 최종 URL과 그 상태 코드가 표시됩니다. 그 아래 체인에는 홉마다 한 행씩 다음 정보가 나옵니다.
- 요청한 URL과 사용한 HTTP 메서드
- 상태 코드와 사유 구절(HTTP 상태 코드 정리에서 각 코드를 설명합니다)
- 요청을 보낸 시점부터 헤더가 도착할 때까지 걸린 응답 시간(DNS 조회와 연결 설정 시간 포함)
- 이 홉이 가리키는
Location - 응답 헤더와 이 홉에서 설정한 쿠키의 이름
각 리디렉션에는 발생 방식이 표시됩니다. HTTP 상태 코드, meta refresh(초 단위 지연 시간 포함), JavaScript 중 하나입니다. 감지했지만 따라가지 않은 클라이언트 측 리디렉션도 함께 표시됩니다. 검사가 어떻게 끝났는지도 그만큼 중요합니다.
| 결과 | 의미 |
|---|---|
| 최종 응답 | 체인이 200 OK나 404 Not Found처럼 리디렉션이 아닌 응답에 도달했습니다. |
| 리디렉션 루프 | 다음 요청이 앞선 요청(URL, 메서드, 쿠키가 모두 같은 요청)을 되풀이하게 됩니다. 결과에 루프를 닫는 홉이 표시됩니다. |
| 최대 홉 수 도달 | 제한에 이르렀을 때도 체인이 계속 리디렉션되고 있었습니다. 다음 대상은 표시되지만 요청하지는 않습니다. |
| 오류 | DNS, 연결, TLS, 시간 초과 등으로 홉이 실패했거나, 리디렉션 대상이 유효하지 않거나 허용되지 않는 URL이었습니다. |
경고는 체인 안의 임시 리디렉션, HTTPS에서 HTTP로의 다운그레이드, 3회를 넘는 리디렉션, 다른 도메인에 있는 최종 URL, 클라이언트 측 리디렉션, 페이지 본문을 읽지 못한 HEAD 요청을 알려 줍니다.
이 중 주의해서 볼 경고가 하나 있습니다. 일부 사이트는 자동화된 트래픽이나 데이터 센터에서 오는 트래픽에 Cloudflare의 “Just a moment...” 페이지 같은 봇 확인(챌린지) 페이지를 보여 줍니다. TrueURL은 이런 페이지로 보이는 응답을 따로 표시합니다. 검사가 목적지가 아니라 사이트의 보호 계층에 도달했기 때문입니다. 실제 방문자는 다른 곳에 도착할 수도 있습니다.
명령줄에서 리디렉션 확인하는 방법
curl은 macOS, Windows 10·11, 대부분의 Linux 배포판에 기본으로 설치되어 있으며, 브라우저 캐시의 영향 없이 서버가 보내는 내용을 그대로 보여 줍니다. 아래 예시는 Unix 셸 기준입니다. Windows PowerShell 5.1에서는 curl이 Invoke-WebRequest의 별칭이므로 curl.exe라고 입력하고, /dev/null 대신 NUL을 쓰세요.
홉 하나 살펴보기
curl -I https://example.com/old-page-I는 HEAD 요청을 보내고 상태 줄과 Location을 포함한 응답 헤더를 출력합니다. curl은 따로 지정하지 않으면 리디렉션을 따라가지 않습니다. 일부 서버는 HEAD를 다르게 처리하므로 결과가 이상해 보이면 GET으로 다시 확인하세요. -o /dev/null은 본문을 버리고 -D -는 헤더를 출력합니다.
curl -sS -o /dev/null -D - https://example.com/old-page전체 체인 따라가기
-L을 붙이면 리디렉션을 따라가며, -I나 -D -와 함께 쓰면 모든 홉의 헤더를 출력합니다. grep으로 걸러 내면 간결하게 볼 수 있습니다.
curl -sIL http://example.com/Shoes | grep -iE '^(HTTP/|location:)'HTTP/1.1 301 Moved Permanently
Location: https://example.com/Shoes
HTTP/2 301
location: https://www.example.com/Shoes
HTTP/2 302
location: /shoes/
HTTP/2 200curl은 기본적으로 리디렉션을 최대 50번까지 따라갑니다. --max-redirs 10을 지정하면 Googlebot과 같은 제한을 적용할 수 있습니다.
최종 URL만 출력하기
-w(write-out) 옵션은 전송이 끝난 뒤 세부 정보를 출력하므로, curl을 간단한 단축 URL 풀기 도구처럼 쓸 수 있습니다.
curl -sSL -o /dev/null -w '%{http_code} %{num_redirects} %{url_effective}\n' https://example.com/go%{url_effective}는 마지막으로 가져온 URL, %{num_redirects}는 따라간 리디렉션 수, %{http_code}는 최종 상태 코드입니다. %{time_redirect}는 최종 요청 전까지 리디렉션에 쓴 시간을 초 단위로 알려 줍니다. -L 없이 실행하면 %{redirect_url}에 첫 번째 리디렉션이 향할 주소가 표시됩니다.
POST 요청 테스트하기
-d는 본문을 보내면서 요청을 POST로 만듭니다. 이때 curl은 리디렉션을 따라가면서 브라우저처럼 동작합니다. 301, 302, 303 이후에는 GET으로 바꾸고, 307이나 308 이후에는 POST와 본문을 다시 보냅니다.
curl -sSL -o /dev/null -D - -d 'email=test%40example.com' https://example.com/subscribe-X POST와 -L을 함께 쓰지 마세요. -X는 모든 요청에 메서드를 강제하므로, 브라우저라면 GET으로 바꿀 301, 302, 303 이후에도 curl은 계속 POST를 보냅니다. 결국 실제 클라이언트에서는 생기지 않는 체인을 테스트하게 됩니다.
User-Agent, 헤더, 쿠키 바꾸기
# 스마트폰 User-Agent
curl -sIL -A 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1' https://example.com/
# 추가 요청 헤더
curl -sIL -H 'Accept-Language: de-DE,de;q=0.9' https://example.com/
# 쿠키를 보내고, 체인 도중에 설정된 쿠키를 유지
curl -sSL -o /dev/null -D - -b 'consent=yes' -c cookies.txt https://example.com/-A는 User-Agent를 지정하고, -H는 헤더를 추가하며, -b는 쿠키를 보냅니다. -c는 받은 쿠키를 파일에 저장하면서 curl의 쿠키 엔진을 켜므로, 한 홉에서 설정된 쿠키가 다음 홉에 전송됩니다.
curl은 JavaScript를 실행하지 않고 meta refresh 태그도 처리하지 않습니다. curl의 마지막 응답은 200 OK HTML 페이지인데 브라우저는 다른 곳에 도착한다면, 리디렉션이 클라이언트 측에서 일어나는 것입니다.
브라우저 개발자 도구에서 리디렉션 확인하는 방법
DevTools는 실제로 사용하는 브라우저가 보는 그대로, 즉 그 브라우저의 쿠키, 확장 프로그램, 위치가 반영된 체인을 보여 줍니다.
- DevTools를 열고(F12, Mac에서는 Cmd+Option+I) Network(네트워크) 탭을 선택하세요.
- Chrome과 Edge에서는 Preserve log(로그 보존)를, Firefox에서는 네트워크 설정 메뉴의 Persist Logs를 켜세요. 그러지 않으면 페이지를 불러올 때마다 목록이 지워져 클라이언트 측 리디렉션이 보이지 않게 됩니다.
- Disable cache(캐시 사용 중지)를 켜서 캐시된 리디렉션 때문에 지금 서버가 보내는 응답이 가려지지 않게 하세요.
- 주소 표시줄에 URL을 입력하세요.
각 홉은 3xx 상태와 함께 별도의 행으로 표시됩니다. 행을 선택하고 Headers(헤더) 탭을 열면 location 응답 헤더를 볼 수 있습니다. Chrome의 Size(크기) 열에 “(disk cache)”나 “(memory cache)”가 보이면 그 리디렉션은 서버가 아니라 캐시에서 온 것입니다.
Chrome에는 http://에서 https://로 가는 307 Internal Redirect가 표시되기도 합니다. 이는 서버가 보낸 응답이 아닙니다. 대개 해당 사이트의 HSTS(Strict-Transport-Security) 정책을 저장해 두었기 때문에 브라우저가 스스로 요청을 업그레이드한 것입니다. 서버가 일반 HTTP 요청을 어떻게 처리하는지 보려면 curl이나 TrueURL을 사용하세요.
흔한 리디렉션 문제와 해결 방법
홉이 2개 이상인 체인
체인은 층층이 쌓이며 길어집니다. 예전 마이그레이션에서 만든 규칙이 가리키는 URL을 나중 마이그레이션에서 다시 리디렉션하는 식입니다. 모든 규칙이 최종 목적지를 바로 가리키게 하고, 내부 링크, canonical 태그, hreflang 주석, 사이트맵을 업데이트해 자기 사이트에서는 리디렉션이 일어나지 않게 하세요. 리디렉션 일괄 검사 도구를 사용하면 아직 홉이 2개 이상 필요한 예전 URL을 찾을 수 있습니다.
리디렉션 루프
Chrome은 루프가 생기면 “example.com에서 리디렉션한 횟수가 너무 많습니다.”(ERR_TOO_MANY_REDIRECTS)라는 오류를 표시하고, Firefox는 “The page isn't redirecting properly”라고 표시합니다. 흔한 원인은 다음과 같습니다.
- 프록시나 CDN 뒤의 HTTPS. 원본 서버는 HTTP를 HTTPS로 리디렉션하는데 프록시는 원본 서버에 일반 HTTP로 접속합니다. 그러면 원본 서버는 HTTPS 요청을 한 번도 받지 못해 끝없이 리디렉션합니다. Cloudflare에서는 Flexible SSL/TLS 모드를 쓸 때 생기는 전형적인 문제입니다. Full (strict) 모드를 사용하거나, 원본 서버가
X-Forwarded-Proto를 확인하게 하세요. - 서로 충돌하는 두 계층. CDN 규칙은
www를 제거하는데 서버는 이를 다시 추가하거나, 프레임워크가 붙인 후행 슬래시를 CDN이 떼어 내는 경우입니다. - 쿠키에 의존하는 리디렉션. 로그인 페이지나 동의 페이지가 방문자를 원래 URL로 돌려보내는데, 쿠키가 저장되지 않아 원래 URL이 다시 로그인 페이지로 리디렉션합니다.
리디렉션 루프 검사 도구로 어느 홉에서 루프가 닫히는지 확인하세요. 그런 다음 규칙마다 담당 계층을 하나로 정하세요.
한 체인에 섞인 301과 302
301, 302, 200 순서로 이어지는 체인은 영구 이전 중간에 임시 단계가 끼어 있는 셈입니다. 대개 기본값 때문에 생깁니다. Express의 res.redirect()와 PHP의 header('Location: ...')는 따로 지정하지 않으면 모두 302를 보냅니다. 모든 홉에 영구 리디렉션 코드를 사용하고 301 리디렉션 검사 도구로 확인하세요. 각 코드가 어떤 상황에 맞는지는 HTTP 리디렉션 상태 코드 가이드에서 설명합니다.
HTTP에서 HTTPS, 다시 www로 가는 이중 홉
아주 흔한 체인으로 http://example.com → https://example.com → https://www.example.com이 있습니다. 한 번이면 될 홉을 두 번 거치는 것입니다. 표준이 아닌 주소는 모두 최종 HTTPS URL로 바로 리디렉션하고, HTTPS 리디렉션 검사 도구로 4가지 주소를 모두 테스트하세요.
단, 의도적인 예외가 하나 있습니다. 표준 호스트가 www인데 도메인을 HSTS 프리로드 목록에 등록한다면, hstspreload.org는 http://example.com이 먼저 https://example.com으로 리디렉션되어야 한다고 요구합니다. 그래야 브라우저가 www가 없는 도메인의 HSTS 정책을 기록할 수 있기 때문입니다.
후행 슬래시 불일치
/pricing과 /pricing/은 서로 다른 URL입니다. 둘 다 200 OK를 반환하면 중복 콘텐츠가 되고, 두 계층이 각각 반대 형식으로 리디렉션하면 루프가 생깁니다. 한 가지 형식을 정해 다른 형식은 301 한 번으로 그쪽으로 리디렉션하고, 링크도 일관되게 거세요. 후행 슬래시 검사 도구는 두 형식을 한 번에 테스트합니다.
모바일에서만 일어나는 리디렉션
별도의 모바일 사이트, 앱 설치 유도 화면, 기기 감지 로직 때문에 휴대폰이 다른 곳으로, 흔히 대응하는 페이지가 아니라 모바일 홈페이지로 보내지기도 합니다. Google은 모바일 중심 색인 생성에 따라 주로 스마트폰 크롤러로 크롤링하므로, 색인에는 모바일 체인이 가장 중요합니다. 모바일·데스크톱 리디렉션 비교 도구로 두 체인을 비교하세요.
사이트맵 속 리디렉션
사이트맵에는 검색결과에 노출하려는 표준 URL을 나열해야 하며, 이런 URL은 200 OK를 반환합니다. 리디렉션되는 항목은 크롤링 요청을 낭비하고 서로 충돌하는 표준 URL 신호를 보냅니다. 마이그레이션 후에는 매번 사이트맵 리디렉션 검사를 실행해 리디렉션되는 항목을 모두 최종 URL로 바꾸세요.
JavaScript와 meta refresh 리디렉션
Google은 즉시 실행되는 meta refresh를 영구 리디렉션으로, 지연된 meta refresh는 임시 리디렉션으로 취급합니다. JavaScript 리디렉션은 페이지를 렌더링한 뒤에야 인식하는데, 렌더링은 크롤링 다음 단계이며 실패할 수도 있습니다. 다른 크롤러, 링크 미리보기 봇, 명령줄 도구 중에는 JavaScript를 전혀 실행하지 않는 것이 많고, meta refresh까지 무시하는 것도 있습니다. 서버를 직접 관리할 수 있다면 언제나 서버 측 리디렉션을 사용하고, 클라이언트 측 리디렉션은 Meta Refresh 검사 도구로 찾으세요.
리디렉션 체크리스트
마이그레이션이나 CDN 변경 후, 또는 캠페인을 시작하기 전에 다음 목록을 점검하세요.
- 모든 예전 URL이 홉 한 번 만에 최종 목적지에 도달합니다.
- 영구 이전은 모든 홉에서 301이나 308을 사용합니다.
- 프로토콜과 호스트 조합 4가지가 모두 표준 HTTPS URL에서 끝납니다.
- HTTPS에서 HTTP로 가는 홉이 없습니다.
- UTM 매개변수와 제휴 ID를 포함한 쿼리 문자열이 체인을 거친 뒤에도 남아 있습니다.
- URL마다 후행 슬래시 형식이 하나로 정해져 있고, 다른 형식은 그쪽으로 리디렉션됩니다.
- 데스크톱, 스마트폰, Googlebot 요청이 모두 같은 내용의 페이지에서 끝납니다.
- 가능한 모든 곳에서 meta refresh와 JavaScript 대신 서버 측 리디렉션을 사용합니다.
- 내부 링크, canonical 태그, hreflang, 사이트맵이 최종 URL을 가리킵니다.
- 대체할 페이지 없이 삭제한 페이지는 홈페이지로 리디렉션하지 않고 404나 410을 반환합니다.
- 사이트 이전에 사용한 리디렉션은 계속 유지합니다. Google은 최소 1년간 유지할 것을 권장합니다.