Redirect 와 Forward
오늘은 가벼운 주제를 다뤄보겠습니다. Redirect와 Forward의 개념과 둘의 차이를 정리하려고합니다. 어렵지 않은 개념이지만 확실하게 정리를 해두지 않으면 자주 혼동하거나 다시 검색하게 되는 개념입니다.
Redirect
Redirect는 Wiki에 다음과 같이 정리되어있습니다.
A redirect is a page which automatically sends visitors to another page, usually an article or section of an article.
Redirect는 방문자를 다른 페이지로 자동으로 보내주는 페이지이다. 그림으로 Redirect의 동작 방식을 표현한다면 다음과 같을 것 입니다.
사용자는 어떤 페이지를 서버에 요청하게되고 서버는 다른 페이지의 url을 Location 헤더에 담아 http status code를 3xx로 설정하여 응답을 줄 것입니다. 그럼 클라이언트는 응답받은 정보를 토대로 다른 url로 다시 요청하게 되는 것 입니다. url의 호스트는 같을 수도 있고 다를 수도 있습니다. 서버의 재량인 것이죠. 그럼 Redirect는 어떨 때 사용 될까요?? 여러 상황에서 사용되겠지만 제가 아는 지식을 바탕으로 다음과 같은 두 가지 예를 소개하려합니다.
- 클라이언트가 요청한 페이지 혹은 리소스가 기존의 장소(url)가 아닌 다른 곳으로 옮겨 졌을 때 해당 리소스로 안내를 하는 것 입니다. 휴대전화를 바꾸면서 번호도 같이 바뀌게 된경우 기존 번호로 전화를 하게 되면 새로운 번호를 알려주는 서비스를 생각해보시면 될 것 입니다.
- OAuth2.0 Spec을 보시면 인증을 제공하는 여러가지 방법 중 대표적으로 Authorization Code Grant 방식이 있습니다. Authorization Code Grant 방식은 사용자의 로그인이 완료되면 Protected Resource에 접근 할 수 있는 AccessToken을 발급 받을 수 있는 code를 기존에 설정해둔 Redirect URL의 query parameter로 전달합니다. query paramter로 전달 받은 code를 이용하여 Access Token을 발급 받을 수 있게 됩니다.
Spring Web MVC를 이용하여 실제 동작을 살펴봅시다. 예제 코드는 다음과 같습니다.
@RestController
@RequiredArgsConstructor
public class RedirectController {
@GetMapping("/redirect/origin")
public ResponseEntity<Object> redirect() throws URISyntaxException {
URI redirectUri = new URI("http://localhost:8090/redirect/target?code=" + UUID.randomUUID());
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setLocation(redirectUri);
return new ResponseEntity<>(httpHeaders, HttpStatus.FOUND);
}
@GetMapping("/redirect/target")
public String target(@RequestParam("code") long code) {
System.out.println(">>> " + code);
return "redirect param :" + code;
}
}
curl을 통하여 요청 해보면 위와 같은 결과를 얻을 수 있습니다. (--location 옵션을 주지않으면 redirect action을 취하지 않습니다.) 9 ~ 10번 째 줄이 처음 요청에 대한 응답 상태코드 302와 함께 Location 헤더에 redirect할 query paramter가 포함된 url을 넘겨주게됩니다. 클라이언트는 이 정보를 가지고 다시 GET요청을 하게 되는 것 입니다. 브라우저를 통해 요청한 결과는 다음과 같습니다.
브라우저를 통해 실행한 결과를 잘 살펴보아야합니다. http://localhost:8090/redirect/origin으로 요청을 하였는데, 결과창에 url이 http://localhost:8090/redirect/target?code=e90c9f15-cb53-44d7-9c7f-17b2c2060bd3로 바뀐 것을 확인할 수 있습니다. forward와의 결정적인 차이임으로 기억해두길 바랍니다.
Forward
forward는 redirect와 비슷하지만 조금은 다른 개념입니다. redirect를 휴대전화를 바꾸면서 번호도 같이 바뀌게 된 경우 기존 번호로 전화를 하게 되면 새로운 번호를 알려주는 서비스에 비유한다면 forward는 휴대전화를 바꾸면서 번호도 같이 바뀌게 된 경우 기존 번호로 전화를 하게 되면 새로운 번호로 연결 시켜주는 서비스에 비유할 수 있습니다. 어떤 차이인지 보이시나요? redirect는 클라이언트가 안내받은 정보로 다시 요청을 보내는 액션을 취해야하지만 forward는 요청이후 새로운 액션을 취할 필요가 없습니다. 따라서 새로운 정보를 알수도 없게됩니다. 다음 그림과 예제 코드로 forward의 동작을 살펴봅시다.
@RestController
@RequiredArgsConstructor
public class ForwardController {
@GetMapping("/forward/origin")
public String forward() throws URISyntaxException {
URI forwardUri = new URI("https://www.daum.net");
RestTemplate restTemplate = new RestTemplate();
return restTemplate.getForObject(forwardUri, String.class);
}
}
위의 코드를 보시면 /forward/origin으로 요청하면 www.daum.net으로 요청하여 받은 응답 값을 그대로 클라이언트에게 내려주고 있습니다. 결과는 다음과 같습니다.
redirect와 차이가 보이시나요?? forward는 요청한 url이 변하지 않습니다. redirect와 forward의 차이를 정리하면 다음과 같습니다.
Redirect | Forward | |
클라이언트의 추가 Action | O | X |
URL 변화 | O | X |