HTTP 상태 코드 301에서 303을 이용한 Location 헤더의 브라우저 캐시 회피하기
얼마 전, 대상 URL로 리다이렉트 시켜주는 short URL을 만들어야 하는 일이 있었다. 요즘은 프레임워크에서 많은 기능을 지원하기 때문에 비교적 쉽게 개발을 시작했다. 다만, 리다이렉트 관련 HTTP 상태 코드 중 301, 302 어떤 것이 적합한지 고민했다. 최대한 상황에 걸맞은 상태 코드를 선택하기 위해 관련 자료를 조금 찾아봤다.
301, 302?
- 301 : 요청한 URI의 리소스가 영구적으로 변경되었음을 의미
- 302 : 요청한 URI의 리소스가 일시적으로 변경되었음을 의미
쉽게 말해 생성한 short URL이 대상 URL로 영구 변경되면 301, 아니면 302를 선택하면 되는 것이다.
이 외에도 정보를 더 찾아보니 302를 사용하게 되면 검색엔진에서 일시적 변경으로 판단해 SEO에 악영향을 준다는 글도 있고, 특히 bitly 같은 URL Shortener 서비스들이 301을 사용하고 있었다.
301을 이용한 naver 리다이렉션
나는 위와 같은 이유로 301을 선택했고 개발을 시작했다. nestjs를 사용해서 개발했으며 간단하게 구현했다.
코드
@Get("/16rXN3N")
@Redirect("https://www.naver.com", 301)
async redirectToNaver() {
const url = "https://www.naver.com"
return { url }
}
위의 코드는 /16rXN3N를 naver로 리다이렉션한다.
크롬브라우저에서 결과
naver로 잘 이동한다.

하지만 여기서 short URL은 그대로 유지하되, naver가 아닌 daum으로 리다이렉션을 해야 한다면 어떻게 해야 할까? 아래와 같이 바꿔서 원하는대로 동작하는 지 보자.
301을 이용한 daum 리다이렉션
코드
@Get("/16rXN3N")
@Redirect("https://daum.net", 301)
async redirectToDaum() {
const url = "https://daum.net"
return { url }
}
기존의 코드에서 대상 URL만 daum으로 변경한 뒤 브라우저에서 결과를 보면 다음과 같다.
크롬브라우저에서 결과
코드에서 daum으로 대상 URL을 변경했지만, 그림 3을 보면 301에 의해 Location 헤더는 기존 URL로 완전히 옮겨졌기 때문에 naver로 이동한다.


이는 사용자 브라우저의 캐시를 지우기 전에 daum으로 리다이렉션 할 수 없는 것을 의미한다. 그러면 이를 해결할 방법은 없을까?
방법은 있다. HTTP 303 상태 코드 값을 이용하면 된다.
303?
- 303 : 클라이언트가 요청한 리소스를 다른 URI에서 GET 요청을 통해 얻어야 할 때 사용하는 상태 코드
위의 의미와 같이 303을 사용하게 되면 Location 헤더의 브라우저 캐시를 회피할 수 있다. 기존의 short URL에서 대상 URL만 바꿔서 리다이렉션 할 수 있는 것이다.
301, 303을 이용한 naver 리다이렉션
코드
@Get("/15rXN3N")
@Redirect("/16rXN3N", 301)
async redirectToBridge() {
const url = "/16rXN3N"
return { url }
}
@Get("/16rXN3N")
@Redirect("https://www.naver.com", 303)
async redirectToTargetUrl() {
const url = "https://www.naver.com"
return { url }
}
위의 코드는 그림 2과 같이 naver로 리다이렉션하지만 301과 200 사이에 다리 역할을 하는 303이 추가됐다.
크롬 브라우저에서 결과
/15rXN3N의 Location 헤더는 16rXN3N을 가리킨다. 하지만 그림 4, 5를 통해 /16rXN3N의 Location 헤더는 naver를 가리키고 있는 것을 확인할 수 있다.


그럼 이번에도 위와 같이 대상 URL만 daum으로 변경한 뒤 확인해보자.
301, 303을 이용한 daum 리다이렉션
@Get("/15rXN3N")
@Redirect("/16rXN3N", 301)
async redirectToBridge() {
const url = "/16rXN3N"
return { url }
}
@Get("/16rXN3N")
@Redirect("https://www.daum.net", 303)
async redirectToTargetUrl() {
const url = "https://www.daum.net"
return { url }
}
naver로 이동하는 것을 daum으로만 변경했다.
크롬 브라우저에서 결과
여전히 /15rXN3N의 Location 헤더는 16rXN3N을 가리키며, 브라우저 캐시가 존재한다. 하지만 그림 6, 7을 보면 /16rXN3N의 Location 헤더는 daum을 가리키고 있다.


위와 같은 방법으로 301 리다이렉션을 할 때 대상 URL을 바꿔줘야하는 이슈가 있다면 303을 이용해서 원하는 곳으로 리다이렉션 시킬 수 있다.
정리
오늘은 HTTP 301 상태 코드를 사용할 때, 303을 이용해 Location 헤더의 브라우저 캐시를 회피하는 방법에 대해서 알아봤다. 언젠가는 또 사용하지 않을까해서 정리했다.