리다이렉트 방식 5가지 비교 - 301, 302, meta refresh, 자바스크립트, 프레임
"주소를 바꿨으니 예전 주소로 들어오면 새 주소로 보내야지."
방법이 여럿인데 겉으로는 다 똑같아 보입니다. 브라우저에서는 전부 새 페이지로 넘어가니까요.
그런데 검색엔진이 받아들이는 방식은 전혀 다릅니다.
결론부터
| 방식 | 응답 | 검색엔진 | 주소 표시줄 | 쓸 곳 |
|---|---|---|---|---|
| 301 | HTTP 301 | 색인 이전 | 새 주소 | 영구 이전 |
| 302 | HTTP 302 | 기존 주소 유지 | 새 주소 | 임시 점검·A/B |
| 308 / 307 | HTTP 308/307 | 301/302와 유사 | 새 주소 | POST 유지해야 할 때 |
| meta refresh | HTTP 200 | 취급이 불확실 | 새 주소 | 권장하지 않음 |
| 프레임(마스킹) | HTTP 200 | 이전 안 됨 | 옛 주소 그대로 | 피할 것 |
주소를 영구히 옮겼다면 301입니다. 나머지는 목적이 다릅니다.
301과 302의 차이
| 301 Moved Permanently | 302 Found | |
|---|---|---|
| 뜻 | "여기 영구히 옮겼다" | "지금만 저기로 가라" |
| 검색엔진 | 새 주소로 색인을 옮긴다 | 옛 주소를 계속 색인한다 |
| 브라우저 캐시 | 강하게 캐시된다 | 덜 캐시된다 |
주의할 점이 하나 있습니다. 301은 브라우저가 강하게 캐시합니다.
잘못 걸어두면 설정을 고쳐도 내 브라우저에서는 계속 옛 규칙대로 동작합니다.
확실히 보려면 시크릿 창이나 curl로 확인하세요.
307 / 308은 301·302와 비슷하지만 요청 메서드를 바꾸지 않습니다.
301·302는 POST 요청이 GET으로 바뀌는 경우가 있어서, 폼 전송을 유지해야 하면 307/308을 씁니다.
일반 블로그 주소 이전에는 301이면 충분합니다.
meta refresh — 겉보기만 같고 속은 다릅니다
<meta http-equiv="refresh" content="0;url=https://example.com">
이건 HTTP 리다이렉트가 아닙니다. 서버는 200 OK와 함께 HTML을 주고,
그 HTML을 읽은 브라우저가 스스로 이동합니다.
서버 응답만 보면 "정상 페이지"입니다.
curl -sI https://example.com/ | head -3
# HTTP/2 200 ← 301이 아니다
# location 헤더 없음
왜 문제인가
- 검색엔진이 리다이렉트로 취급할지 불확실합니다
- 콘텐츠 없이 이동만 하는 페이지가 하나 생깁니다
- 이동 대상이 고정이면 경로가 유지되지 않습니다 (
/글주소로 들어와도 첫 페이지로)
일부 등록기관의 도메인 포워딩이 이 방식입니다. 실제로 받아본 응답입니다.
<script>if(top!=self) top.location=this.location;</script>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>도메인이름</title>
<meta http-equiv="refresh" content="0;url=https://이동할주소">
"301 리다이렉트를 걸었다"고 생각했는데 실제로는 이것일 수 있습니다.
저는 등록기관 포워딩을 걸어놓고 "301을 걸었다"고 생각하고 있었습니다.
설정 화면에 "유동 포워딩"이라고 적혀 있었고, 브라우저로 접속하면 목적지로 잘 넘어갔습니다. 그런데 실제 응답을 확인해보니 HTTP 200에 meta refresh 였습니다. 301이 아니었습니다.
더 문제는 경로가 유지되지 않는다는 점이었습니다. "유동"이라는 이름 때문에 당연히 경로가 따라가는 줄 알았는데, /entry/글주소로 들어가면 404가 나고 첫 페이지로만 보냈습니다. 그대로 뒀다면 기존 글 링크가 전부 죽었을 겁니다.
설정 이름만 믿지 말고 curl -sI로 확인해야 한다는 걸 그때 배웠습니다.
프레임 마스킹 — 가장 나쁩니다
일부 포워딩 서비스에 "마스킹" 옵션이 있습니다. 켜면 주소 표시줄이 옛 주소 그대로 남습니다.
대상 사이트를 프레임 안에 넣어 보여주기 때문입니다.
| 문제 | 내용 |
|---|---|
| 주소가 안 바뀐다 | 개별 글 주소를 공유할 수 없다 |
| 검색엔진 | 내용이 프레임 안에 있어 제대로 인식되지 않는다 |
| HTTPS | 프레임 안팎의 보안 설정이 충돌할 수 있다 |
SEO를 생각한다면 쓰지 마세요.
실제로 뭘 쓰고 있는지 확인하는 법
# ① 헤더 확인 — 301/302면 여기 나온다
curl -sI https://example.com/ | head -5
# ② 리다이렉트 횟수 — 0인데 화면이 넘어가면 HTTP 방식이 아니다
curl -s -o /dev/null -L -w '홉=%{num_redirects} 최종=%{url_effective}\n' https://example.com/
# ③ 본문 확인 — meta refresh나 JS가 보이면 그거다
curl -s https://example.com/ | head -20
| 결과 | 판정 |
|---|---|
HTTP/2 301 + location: |
✅ 301 리다이렉트 |
HTTP/2 200 + 홉 0 + 본문에 refresh |
meta refresh |
HTTP/2 200 + 본문에 <iframe·<frameset |
마스킹 |
경로 유지도 확인하세요
주소를 옮길 때 개별 글 주소가 살아있는지가 중요합니다.
curl -sI https://example.com/entry/어떤글 | grep -i location
location: https://새주소/entry/어떤글→ ✅ 경로 유지location: https://새주소/→ ❌ 전부 첫 페이지로. 기존 링크가 전부 죽는다
정리
- 영구 이전이면 301. 302는 옛 주소를 계속 색인합니다
- meta refresh는 HTTP 200입니다. 리다이렉트가 아니고, 취급도 불확실합니다
- 마스킹은 쓰지 마세요. 주소가 안 바뀌고 색인도 제대로 안 됩니다
- 설정했다고 믿지 말고
curl -sI로 확인하세요. 생각과 다른 방식일 수 있습니다 - 경로가 유지되는지 개별 주소로 꼭 시험해 보세요