웹사이트 주소를 개편하거나 도메인을 변경할 때 301 또는 302 리다이렉트를 설정해본 경험이 있을 것이다.
다만 주소가 여러 번 연속해서 꺾이는 리다이렉트 체인이 발생해 검색엔진 색인이 누락되거나 SEO 점수가 깎이는 원인을 정확히 모르는 경우가 많다.
이번에는 리다이렉트 체인이 정확히 무엇인지, 왜 크롤링 예산에 치명적인지, 그리고 Nginx와 PHP 환경에서 올바르게 301 리다이렉트를 구축하는 법을 완벽하게 정리해서 소개하겠다.
리다이렉트 체인(Redirect Chain)은 클라이언트가 요청한 URL이 최종 목적지 페이지에 도착하기까지 2회 이상의 리다이렉트를 거치는 현상을 말한다.
예를 들어 http://example.com 요청이 https://example.com으로 이동하고, 다시 https://www.example.com으로 이동한 뒤 최종적으로 https://www.example.com/home으로 연결되는 형태다.
대부분의 개발자들은 도메인 변경이나 HTTP/HTTPS 전환, Trailing Slash(끝 슬래시) 처리 등의 로직을 개별적으로 작성하면서 이런 체인이 생성된다는 사실을 인지하지 못한다.
구글과 같은 검색엔진 크롤러는 한 사이트에 할당된 크롤링 예산(Crawling Budget)이 한정되어 있다.
리다이렉트 단계를 거칠 때마다 네트워크 왕복 시간이 늘어나고, 크롤러는 불필요한 요청에 크롤링 예산을 소비하게 된다.
체인이 4~5단계 이상 길어지면 구글봇은 크롤링을 중단하고 해당 페이지의 색인 생성을 포기해버린다.
또한 과거 페이지가 보유하고 있던 백링크의 페이지랭크(SEO 점수)가 완벽히 전달되지 않고 누수되는 문제가 발생한다.
| 구분 | HTTP 상태 코드 | SEO 점수 전달 | 검색엔진 처리 방식 |
|---|---|---|---|
| 301 Permanent Redirect | 301 Moved Permanently | 약 90~99% 전달 | 새 URL로 색인을 영구 이전하고 기존 URL 삭제 |
| 302 Temporary Redirect | 302 Found | 전달 안 됨 (제한적) | 기존 URL 색인 유지, 원본 페이지를 우선 추적 |
| 리다이렉트 체인 | 복수의 301/302 중첩 | 단계마다 점수 누수 발생 | 크롤링 중단 및 색인 생성 실패 위험 증가 |
리다이렉트 체인을 최적화하는 핵심 원칙은 매우 단순하다. 중간 단계를 모두 제거하고 최초 요청에서 최종 목적지 URL로 단 1회의 301 리다이렉트만 수행하도록 웹서버나 백엔드 로직을 통합하는 것이다.
- HTTP/HTTPS 및 non-WWW/WWW 통합: 도메인 접속 규칙을 개별 규칙으로 분리하지 않고 Nginx나 Apache 서버 블록에서 한 번에 301 처리한다.
- 과거 주소 개편 이력 단권화: 1차 개편 주소(A -> B)와 2차 개편 주소(B -> C)가 누적되어 있다면 A -> C로 직접 연결하도록 DB 및 서버 설정을 주기적으로 업데이트한다.
- Trailing Slash 정규화: 슬래시 유무에 따른 리다이렉트 역시 최종 주소 규칙에 맞춰 한 번에 처리되도록 작성한다.
실무에서 자주 사용되는 Nginx 웹서버 설정과 PHP 백엔드 코드의 올바른 리다이렉트 구현 방식을 살펴보자.
HTTP 요청, non-WWW 요청을 최종 보안 프로토콜과 정규 도메인으로 한 번에 보내는 설정이다.
✗ 잘못된 Nginx 설정 (2단계 리다이렉트 체인 발생)
# HTTP를 HTTPS로 전환 (1차 301)
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
# HTTPS 접속 후 non-WWW를 WWW로 전환 (2차 301)
server {
listen 443 ssl;
server_name example.com;
return 301 https://www.example.com$request_uri;
}설명: http://example.com으로 접속 시 https://example.com을 거쳐 https://www.example.com으로 2번 꺾이게 된다.
✓ 올바른 Nginx 설정 (단 1회의 301 리다이렉트로 통합)
# HTTP 및 HTTP WWW 요청을 HTTPS WWW로 직접 전환
server {
listen 80;
server_name example.com www.example.com;
return 301 https://www.example.com$request_uri;
}
# HTTPS non-WWW 요청을 HTTPS WWW로 직접 전환
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert.crt;
ssl_certificate_key /path/to/key.key;
return 301 https://www.example.com$request_uri;
}출력 결과: http://example.com 또는 http://www.example.com 호출 시 중간 과정 없이 바로 HTTP 301 응답과 함께 https://www.example.com으로 이동한다.
라우터나 컨트롤러 레벨에서 구 주소를 신규 주소로 이전할 때의 구현 코드다.
✗ 잘못된 PHP 코드 (기본 header() 사용 시 302 응답 발송)
<?php
// 상태 코드를 지정하지 않으면 302 Temporary 리다이렉트로 동작함
header('Location: https://www.example.com/new-page');
exit;
?>설명: 상태 코드를 명시하지 않으면 기본적으로 302가 전송되어 검색엔진이 기존 페이지 색인을 삭제하지 않고 영구 이전으로 인식하지 못한다.
✓ 올바른 PHP 코드 (301 상태 코드 명시)
<?php
$destinationUrl = 'https://www.example.com/new-page';
// 301 Moved Permanently 상태 코드 명시
header('Location: ' . $destinationUrl, true, 301);
exit;
?>출력 결과:
HTTP/1.1 301 Moved Permanently
Location: https://www.example.com/new-page
리다이렉트를 구축할 때 개발자들이 흔히 저지르는 3가지 실수를 정리했다.
✗ 잘못된 접근: 무한 리다이렉트 고리(Redirect Loop) 방치
A 페이지가 B를 바라보고, B 페이지가 다시 A를 바라보게 설정하면 브라우저에 ERR_TOO_MANY_REDIRECTS 에러가 발생하며 크롤러가 즉시 이탈한다.
✓ 올바른 접근: 리다이렉트 최종 주소는 반드시 200 OK 상태 코드를 반환하는 정적/동적 실체 페이지여야 한다.
✗ 잘못된 접근: 자바스크립트(window.location.href) 기반 리다이렉트 남발
서버 응답 헤더가 아닌 클라이언트 사이드 스크립트로 이동시키면 검색엔진 크롤러가 이를 리다이렉트로 인지하지 못하거나 색인 반영에 오랜 시간이 걸린다.
✓ 올바른 접근: SEO 목적의 이전 처리는 항상 HTTP Response Header의 301 상태 코드를 사용한다.
✗ 잘못된 접근: Canonical 태그와 301 리다이렉트의 충돌
301 리다이렉트를 설정한 목적지 페이지의 Canonical 태그가 다시 이전 주소를 가리키면 검색엔진에 혼선을 준다.
✓ 올바른 접근: 리다이렉트 목적지 페이지의 Canonical 태그는 자기 자신의 최종 URL을 가리키도록 설정한다.
리다이렉트 최적화는 웹사이트의 SEO 점수를 온전히 보전하고 검색엔진 크롤링 효율을 높이는 필수 작업이다. 작은 리다이렉트 구조 최적화 습관이 모여서 검색 순위 상승이라는 큰 효과를 만든다는 점을 잊지 말자. 이 글의 Nginx 설정 및 PHP 헤더 처리 방법을 참고해 기존 리다이렉트 경로를 점검하면, 크롤링 예산 낭비를 막고 검색 노출 성과를 안정적으로 거둘 수 있을 것이다.