[Spring] 스프링 컨트롤러에서 쿼리 파라미터가 포함된 페이지 Redirect하기

Bam·2025년 1월 28일
0

Spring

목록 보기
49/49
post-thumbnail

스프링 컨트롤러의 반환 타입

@Controller가 붙은 스프링 컨트롤러는 반환 타입으로 보통 void, String을 갖습니다.

위 두 타입이 대표적일 뿐이고, 스프링 공식 문서에 가보시면 상당히 다양한 타입의 반환 타입을 지원하고 있습니다.

void의 경우에는 리턴값 없음. 즉, 로직(혹은 서비스 호출)만을 수행합니다.

String의 경우에는 문자열을 반환하게 되는데 이때 반환하는 문자열이 View의 이름이 됩니다.

이 과정에서 ViewResolver라는 객체가 뷰를 검색하고 반환하는데 어떤 역할을 하게 되는데요. 이는 추후에 @Controller 동작 원리를 좀 파헤쳐보는 다른 포스트를 작성하려고 예정하고 있기에 지금은 일단 String 반환 타입의 경우 뷰의 이름을 반환한다라는 정도로만 생각하시면 됩니다.

@GetMapping("/account/sign-in")
public String getSignInPage() {
	return "account/signIn";
}

위 코드는 account 디렉토리의 signIn이라는 View 파일명을 찾아서 해당 파일을 반환하게 됩니다. 여기서 반환한다는 것은 브라우저에 해당 웹 페이지를 띄워준다라는 말이 됩니다.

return "redirect:"

String 반환타입에서는 redirect(리디렉션)라는 독특한 동작을 하나 정의할 수 있는데요.

redirectredirect:url과 같이 작성하며 url으로 GET 요청을 보내게 됩니다.

따라서 기존 String 반환에서 View 이름을 적었던 것과 다르게 redirect를 사용할 때는 GET 요청 url을 적어주어야 합니다.

다음 코드는 제가 실제로 프로젝트를 진행하며 redirect를 쓴 예제 코드입니다.

@GetMapping("/account/sign-in")
public String getSignInPage() {
	return "account/signIn";
}

@PostMapping("/account/sign-in")
public String signIn(@ModelAttribute AccountSignInRequest accountSignInRequest,
	HttpSession session, Model model, RedirectAttributes redirectAttributes) {
	ResultStatus signInResult = accountService.signIn(accountSignInRequest);

	if (signInResult == ResultStatus.SUCCESS) {
		//성공 로직 생략
		return JspView.HOME.getView();
	} else if (signInResult == ResultStatus.WRONG_USERNAME) {
		redirectAttributes.addFlashAttribute("failureMessage", "존재하지 않는 계정입니다.");
		return "redirect:/account/sign-in";
	} else if (signInResult == ResultStatus.WRONG_PASSWORD) {
		redirectAttributes.addFlashAttribute("failureMessage", "패스워드가 일치하지 않습니다.");
	return "redirect:/account/sign-in";
	} else {
		return "redirect:/account/sign-in";
	}
}

보시면 redirect 요청에선 signIn 페이지를 띄우는 GET 요청 컨트롤러의 url을 명시하고 있음을 볼 수 있습니다.

그렇다면 여기서 오늘의 주제인 스프링 컨트롤러에서 리디렉션을 수행할 때 "/user/my-page/1?menu=user-info"와 같이 쿼리 파라미터가 포함된 url을 요청하고 싶다면 어떻게 할까요?


방법 1. RedirectAttribute

RedirectAttribute는 리디렉션한 페이지에 데이터를 넘기는데 사용되는 객체입니다. 이 객체를 이용해서 url에 데이터를 바인딩하거나 쿼리 파라미터 형태로 넘길 수 있게 됩니다.

더 자세한 내용은 스프링 API 문서에서 확인하실 수 있습니다.

RedirectAttribute.addAttribute()

다음과 같이 addAttribute()를 사용하면 리디렉션에 바인딩 또는 쿼리 파라미터를 넘길 수 있습니다. 마찬가지로 진행중인 프로젝트에서 코드를 가져와서 조금 변경했습니다.

@PostMapping("/account/change/nickname")
public RedirectView changeNickname(RedirectAttribute redirectAttribute) {
	redirectAttribute.addAttribute("userId", 1);
	redirectAttribute.addAttribute("menu", "user-info");
        
	return "redirect:/account/my-page/{userId}";
}

위 코드의 실행 결과는 /account/my-page/1?menu=user-info라는 url로 리디렉션 하게 됩니다.

RedirectAttribute.addFlashAttribute()

addFlashAttribute()라는 메소드도 있는데요. 이 메소드는 바인딩이나 쿼리 파라미터로 저장하는 것이 아니라 임시로 저장되는 Flash 속성을 데이터가 갖게 합니다.

데이터가 플래시 속성을 가지게 되면 (주로 세션)에 임시 저장되었다가 필요할때 꺼내서 사용된다고 합니다. 플래시 속성을 가진 데이터는 휘발성 데이터가 되기 때문에 새로고침 등의 동작을 하게 되면 데이터가 사라지게 됩니다. 그래서 리디렉션 후 안내 메세지(ex.로그인 실패 등)을 띄울때 사용하게 됩니다.

더 자세한 내용은 스프링 공식 문서에서 확인하실 수 있습니다.

예시로 진행중인 프로젝트에선 로그인 실패 시 alert를 위해 다음과 같이 사용하고 있습니다. 메세지를 jsp 뷰로 넘긴 후 jsp의 스크립트에서 해당 메세지를 받아와 window.alert로 출력하는 형식입니다.

@PostMapping("/account/sign-in")
public String signIn(RedirectAttributes redirectAttributes) {
    (...)

	if (signInResult == ResultStatus.SUCCESS) {
		(...)
	} else if (signInResult == ResultStatus.WRONG_USERNAME) {
		redirectAttributes.addFlashAttribute("failureMessage", "존재하지 않는 계정입니다.");
		return "redirect:/account/sign-in";
	} else if (signInResult == ResultStatus.WRONG_PASSWORD) {
		redirectAttributes.addFlashAttribute("failureMessage", "패스워드가 일치하지 않습니다.");
		return "redirect:/account/sign-in";
	} else { }
}

방법 2. RedirectView

또 다른 방법으로는 RedirectView을 사용하는 방법이 있습니다.

이전의 RedirectAttributeredirect 키워드를 사용하기 때문에 내부에 존재하는 GET 요청으로만 리디렉션을 할 수 있었으나, RedirectView를 사용하면 외부 URL로도 이동이 가능하게 됩니다.

사용법은 간단하게 RedirectView(url)과 같이 사용합니다.

마찬가지로 현재 프로젝트에서 코드를 가져와서 간단하게 변형시켰습니다.

@PostMapping("/account/change/nickname")
public RedirectView changeNickname() {
	String url = "/user/my-page/" + 1 + "?menu=user-info";

	if (changeNicknameResult == ResultStatus.SUCCESS) {
		return new RedirectView(url);
	} else { }
}

위 결과로 /account/my-page/1?menu=user-info로 리디렉션 하게 되는 동일한 결과를 얻을 수 있습니다.

0개의 댓글

관련 채용 정보