OneWebDesk

301 vs 302 vs 307/308: 올바른 리다이렉트

리다이렉트 상태코드의 차이와 SEO·메서드 보존 관점에서 올바르게 고르는 법.

리다이렉트는 “이 주소는 다른 곳으로 옮겨졌다”고 브라우저와 검색엔진에 알리는 HTTP 응답이다. 응답 코드는 모두 3xx로 시작하고 새 위치는 Location 헤더에 담긴다. 겉보기에는 다 똑같이 “다른 페이지로 보내기”처럼 보이지만, 코드마다 (1) 이동이 영구인지 일시인지, (2) 원래 요청 메서드를 그대로 유지하는지, (3) 브라우저가 캐시해도 되는지가 다르다. 잘못 고르면 SEO 순위 신호가 새 주소로 넘어가지 않거나, POST 폼 전송이 조용히 GET으로 바뀌어 데이터가 사라지는 사고가 난다.

이 가이드는 5가지 리다이렉트 코드(301, 302, 303, 307, 308)의 차이를 표로 정리하고, SEO 관점의 301 vs 302, 메서드를 보존하는 307/308, 그리고 가장 흔한 실수(영구 이전에 302를 쓰는 것)를 실제 사례로 짚는다. 실제 서버가 어떤 코드를 돌려주는지 확인하려면 HTTP 상태 코드 확인 도구로 응답을 직접 찍어보면 된다.

5가지 리다이렉트 코드 한눈에 비교

핵심은 “메서드 보존”과 “영구/일시”의 조합이다. 아래 표에서 “메서드 유지”가 아니오인 코드는 비-GET 요청(주로 POST)을 자동으로 GET으로 바꿀 수 있다는 뜻이다.

코드의미메서드 유지기본 캐시주 용도(SEO)
301영구 이동아니오(GET으로 변환 허용)도메인·URL 영구 변경, 순위 신호 이전
302발견됨(일시)아니오(GET으로 변환 허용)아니오점검·A/B·임시 이동(원본 색인 유지)
303기타(See Other)아니오(항상 GET으로)아니오POST 처리 후 결과 페이지로(PRG 패턴)
307임시 리다이렉트예(메서드·본문 보존)아니오일시 이동인데 POST를 그대로 보내야 할 때
308영구 리다이렉트예(메서드·본문 보존)영구 이동인데 API·POST를 보존해야 할 때

301 vs 302: SEO에서 무엇이 다른가

가장 자주 헷갈리는 쌍이다. 둘 다 “다른 주소로 보내기”지만 검색엔진이 해석하는 방식이 정반대다.

  • 301(영구): “이 URL은 영원히 새 주소로 바뀌었다.” 검색엔진은 색인을 새 URL로 갱신하고, 기존 페이지가 쌓아온 링크·순위 신호를 새 URL로 전달한다. 도메인 변경, httphttps, www 통일, 옛 글 URL 정리에는 301이 정답이다.
  • 302(일시): “원본은 그대로 있고 지금만 잠깐 다른 데로 보낸다.” 검색엔진은 원래 URL을 색인에 유지하려 한다. 점검 페이지, 지역·언어별 임시 우회, 단기 캠페인 페이지에 적합하다.

실무 규칙은 간단하다. 되돌릴 계획이 없으면 301/308, 곧 원래대로 돌릴 거면 302/307. 옮긴 뒤에는 응답 코드와 Location 헤더가 의도대로 나오는지 HTTP 헤더 확인 도구로 검증하자.

307·308이 필요한 이유: 메서드 보존

역사적으로 많은 브라우저가 301·302를 받으면 POSTGET으로 바꾸고 요청 본문을 버렸다. 폼이나 API 호출이 리다이렉트를 만나면 데이터가 사라지는 것이다. 이 모호함을 없애기 위해 나온 게 307·308이다.

  • 307 = 302의 “메서드 보존” 버전(임시). POSTPOST로, 본문은 그대로 새 URL에 다시 보낸다.
  • 308 = 301의 “메서드 보존” 버전(영구). 영구 이동이면서 메서드·본문을 유지한다. API 엔드포인트 영구 이전에 특히 안전하다.
  • 303은 반대로 “무조건 GET으로 바꿔라”를 명시한다. POST로 데이터를 처리한 뒤 결과 페이지를 GET으로 보여주는 PRG(Post/Redirect/Get) 패턴에서 새로고침 중복 제출을 막는 용도다.

흔한 실수와 점검 방법

  1. 영구 이전에 302 사용: 가장 흔한 사고. 검색엔진이 옛 URL을 계속 색인하고 순위 신호가 새 URL로 넘어가지 않아 트래픽이 정체된다. 영구 이동이면 반드시 301(또는 308).
  2. 리다이렉트 체인·루프: A → B → C처럼 여러 단계를 거치면 신호가 희석되고 속도가 느려진다. A → A로 자기 자신을 가리키면 무한 루프가 난다. 항상 최종 목적지로 한 번에 보내자.
  3. http→https에서 메서드 손실: API가 평문 http 엔드포인트에 POST를 보냈는데 301로 https로 보내면 일부 클라이언트에서 본문이 사라진다. 308을 쓰면 안전하다.

체인을 추적하려면 한 단계씩 따라가며 각 응답의 코드와 Location을 확인해야 한다. HTTP 상태 코드 확인으로 최종 코드를, HTTP 헤더 확인으로 Location과 캐시 헤더를 함께 보면 어디서 의도가 어긋났는지 바로 드러난다.

실전 예시: POST가 302에서 깨지고 308에서 살아남는 과정

결제 API //pay.example.com/charge//api.example.com/v2/charge로 옮겨졌다고 하자. 클라이언트는 카드 정보가 담긴 본문과 함께 POST를 보낸다.

302로 옮긴 경우(깨짐):

  • 클라이언트: POST /charge + 본문(카드/금액)
  • 서버: 302 Found, Location: //api.example.com/v2/charge
  • 클라이언트(많은 구현): 메서드를 GET으로 바꾸고 본문을 버림 → GET /v2/charge
  • 새 엔드포인트: 본문 없는 GET 수신 → 400 Bad Request 또는 빈 결제. 데이터 유실.

308로 옮긴 경우(보존):

  • 클라이언트: POST /charge + 본문(카드/금액)
  • 서버: 308 Permanent Redirect, Location: //api.example.com/v2/charge
  • 클라이언트: 메서드와 본문을 그대로 유지 → POST /v2/charge + 동일 본문
  • 새 엔드포인트: 정상 결제 처리 → 200 OK. 데이터 보존.

교훈: 비-GET 요청을 받는 엔드포인트의 영구 이전에는 301이 아니라 308을, 임시 우회에는 302가 아니라 307을 써야 한다. 적용 후에는 실제 응답이 308/307로 나오는지 HTTP 상태 코드 확인으로 꼭 확인하자.

자주 묻는 질문

301과 302 중 SEO에는 무엇을 써야 하나요?
영구 이동이면 301입니다. 301은 검색엔진이 색인을 새 URL로 갱신하고 기존 링크·순위 신호를 새 URL로 전달합니다. 302는 일시 이동으로, 검색엔진이 원래 URL을 색인에 유지하려 하므로 영구 이전에 쓰면 순위가 넘어가지 않습니다.
307과 308은 301·302와 무엇이 다른가요?
307·308은 요청 메서드와 본문을 그대로 보존합니다. 301·302는 많은 클라이언트에서 POST를 GET으로 바꿔 본문을 버릴 수 있지만, 307(임시)·308(영구)은 POST를 POST로, 본문을 그대로 새 URL에 다시 보냅니다. API나 폼 전송 경로에 안전합니다.
302를 영구 이전에 쓰면 어떤 문제가 생기나요?
검색엔진이 옛 URL을 계속 색인하고 새 URL로 순위 신호를 넘기지 않아 검색 순위가 정체되거나 떨어집니다. 또 사용자 북마크·링크가 옛 주소를 가리킨 채로 남습니다. 되돌릴 계획이 없는 이전이라면 301(또는 메서드 보존이 필요하면 308)을 쓰세요.
리다이렉트 체인은 어떻게 확인하나요?
각 단계를 따라가며 응답 코드와 Location 헤더를 차례로 확인하면 됩니다. HTTP 상태 코드 확인 도구로 최종 코드를, HTTP 헤더 확인 도구로 Location과 캐시 헤더를 보면 어느 단계에서 의도가 어긋났는지 알 수 있습니다. 가능하면 중간 단계를 없애고 최종 목적지로 한 번에 보내세요.
303 See Other는 언제 쓰나요?
POST로 데이터를 처리한 뒤 결과 페이지를 GET으로 보여주는 PRG(Post/Redirect/Get) 패턴에 씁니다. 303은 항상 GET으로 전환하므로, 사용자가 결과 페이지에서 새로고침해도 폼이 중복 제출되지 않습니다.

이 가이드와 함께 쓰면 좋은 도구