We will find a way, we always have.

-interstellar

Computer Science/네트워크

[네트워크] 3xx 리다이렉트 (feat: ERR_TOO_MANY_REDIRECTS)

Redddy 2024. 9. 12. 12:57

서론

우테코 레벨 2 미션을 하면서 생성 요청이 왔을 때 응답으로 201 Created를 반환하고 Location을 내리라는 요구사항이 있었다. 

 

요구사항

 

그래서 코드 구현도 UriComponentsBuilder를 사용해서 URI를 만들고 Location 필드에 넣어주었다. 

 

구현코드

 

하지만 이렇게 구현을 해도 Post 요청이 왔을 때, Location으로 리다이렉트 하지 않는다. 왜냐 2xx에선 Location에 값이 있어도 그쪽으로 자동 리다이렉트하지 않는다. 레벨 2 당시에는 놓쳤던 부분이지만 이번 레벨 4 미션을 하면서 왜 201 Created에 Location을 말아 넣는지 알았다. 오다 주웠기 때문이다. 

 

 

 

리다이렉션

웹 서버는 종종 성공 메시지 대신 리다이렉션 응답을 반환한다. HTTP 헤더에서 Location 응답 헤더에 콘텐츠의 새로운 혹은 선호하는 위치에 대한 URI를 포함시키면 브라우저가 다른 곳으로 가도록 리다이렉트할 수 있다.

 

리다이렉트는 다음과 같은 경우에 유용하다. 

 

  • 영구히 리소스가 옮겨진 경우
    • 리소스는 새 URL이 부여되어 새로운 위치로 옮겨졌거나 이름이 바뀌었을 수도 있다.
    • 301 Moved Permanently는 이런 종류의 리다이렉트를 위해 사용한다.

 

  • 임시로 리소스가 옮겨진 경우
    • 만약 리소스가 임시로 옮겨지거나 이름이 변경된 경우, 서버는 클라이언트를 새 위치로 리다이렉트하길 원할 것이다. 
    • 303 See Other, 307 Temporary Redirect를 사용한다. 

 

  • URL 증강
    • 서버는 종종 컨텍스트 정보를 포함시키기 위해 재 작성된 URL로 리다이렉트한다. 
    • 요청이 도착했을 때, 서버는 상태 정보를 내포한 새 URL을 생성하고 사용자를 이 새 URL로 리다이렉트한다. 
    • 클라이언트는 이 리다이렉트로 따라가, 이번엔 상태정보가 추가된 완전한 URL을 포함한 요청을 다시 보낸다. 
    • 이는 트랜잭션 간 상태를 유지하는 유용한 방법이다.
    • 303 See Other, 307 Temporary Redirect를 사용한다.

 

  • 부하 균형
    • 과부화된 서버에 요청이 온 경우, 상대적으로 부하가 덜 걸린 서버로 클라이언트를 리다이렉트할 수 있다.
    • 303 See Other, 307 Temporary Redirect를 사용한다. 

 

  • 디렉터리 이름 정규화
    • 클라이언트가 디렉터리 이름에 대한 URI를 요청하는데 끝에 빗금(/)을 빠뜨렸다면, 대부분의 웹 서버는 상대경로가 정상적으로 동작할 수 있도록 클라이언트를 슬래시를 추가한 URI로 리다이렉트한다. 

 

트러블 슈팅

이 글을 쓰게 된 이유는, 로그인 성공시 index.html로 리다이렉트하라는 요구사항이 있어 구현하는 와중에 HTTP 상태코드가 3xx가 아닌 2xx에 Location을 말아 넣었을 때 자동으로 리다이렉트가 되지 않음을 깨닫고 작성하기 시작했다. 

 

그래서 몇가지 실험을 하다가 재밌는 것을 발견했다. GET 요청으로 상태코드는 3xx로 Location에 경로를 말아넣으면 304를 제외한 나머지 상태코드들은 명시한 경로로 자동 리다이렉트 해주었다. 하지만 POST 요청으로 상태코드는 308일 때 Location 필드에 index.html을 말아넣으면 ERR_TOO_MANY_REDIRECTS를 발생시켰다.  

 

POST 308 with Location

 

 

 

이런 에러가 발생한 원인을 파악해보자. 

리다이렉션에도 영구 리다이렉션, 일시 리다이렉션, 특수 리다이렉션이 있다. 영구 리다이렉션은 원래의 URL이 더 이상 사용되지 않아야 하며 새로운 URL을 사용해야 한다는 것을 나타내고, 일시 리다이렉션은 요청된 리소스의 URL이 일시적으로 이동됐음을 의미한다. 그리고 특수 리다이렉션 중 304는 로컬에 캐시된 복사본으로 페이지를 리다이렉트 시킨다. 

 

308은 301과 같이 영구 리다이렉션이다. Location으로 자동 리다이렉트 해준다는 점은 동일하지만 301과 308의 차이점은 301은 요청 메서드가 GET으로 변경되고 본문은 제거될 수 있다. 반면 308은 요청 메서드와 본문을 변경하지 않고 유지 시킨다. 요청 메서드와 본문을 변경하지 않는 308의 특징 때문에 ERR_TOO_MANY_REDIRECTS가 발생했던 것이다. 

 

index.html에 POST 요청을 보냈더니 Location: index.html을 가르킨다. 상태코드가 308이였기 때문에 메서드와 본문을 유지한채 다시 index.html을 간 것이였고, 20번째에서 ERR_TOO_MANY_REDIRECTS를 뱉어냈다. (재귀호출)

 

 

에러를 마주한 덕분에 깊이 파고 들 수 있었다 👍

 

참고

 

HTTP 완벽 가이드

 

모질라 httpstatus redirection 문서

모질라 HTTP 리다이렉트 문서

 

미션코드가 궁금하다면,,,

레벨 2 미션코드

레벨 4 미션코드

 

'Computer Science > 네트워크' 카테고리의 다른 글

[네트워크] DNS(Domain Name System) 1편  (18) 2024.07.29
[네트워크] HTTP 응답코드  (0) 2023.07.19
[네트워크] TCP와 UDP  (0) 2023.06.29
[네트워크] 네트워크 구성  (0) 2022.10.14
[네트워크] What is Network?  (0) 2022.10.14