ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring] Redirect후에도 전송파라미터를 유지할 수 있을까? RedirectAttributes, @RequestParam에 대해
    Spring 2022. 8. 19. 00:41

     

     

    리다이렉트 방식은 페이지를 이동하면 이전 요청은 사라지고 새로운 요청이 발생합니다.

    이과정에서 아무 처리를 해주지 않는다면 전송파라미터를 리다이렉트 후에 가져올 수 없습니다.

     

    정말 흔히 볼 수 있는 게시판을 예로들어 상황을 가정해 보겠습니다.

    보통 작성, 수정, 삭제와 같이 변경이 일어나는 요청은 리다이렉트로 처리합니다.

     

    이에 따라 게시글 수정창에서 post요청으로 수정 처리를 한 후에는 상세페이지 조회 창으로 리다이렉트 처리를 했습니다.

    그러나 리다이렉트로 이동하였기 때문에 이전 요청은 종료되고 새로운 요청이 발생하여 현재 페이지 번호를 나타내주는 currPage파라미터 값을 얻어올 수 없었습니다.

    이 상태에서 페이지 목록으로 되돌아가면 예외가 발생합니다. 

     


     

     

    이 문제를 해결하기 위해 RedirectAttributes 인터페이스를 이용합니다.

     

     

    RedirectAttributes는 Model인터페이스를 상속받고 있고, 속성을 올려둘 수 있는 메소드를 제공하고 있습니다.

    사용방법은 model과 거의 동일합니다.

     

     

     

    @PostMapping("/modify")
    public String modify(
        BoardDTO dto, 
        RedirectAttributes rttrs, 
        int currPage) throws ControllerException {
    
        log.trace("register({}, {}) invoked.", dto, rttrs);
        try {
            if(this.boardService.update(dto)) {
                rttrs.addFlashAttribute("_RESULT_", "SUCCEED");	
                rttrs.addAttribute("currPage", currPage);
            } else {
                rttrs.addFlashAttribute("_RESULT_", "FAILED");
            } // if-else
    
            return "redirect:/board/get?bno=" + dto.getBno();
        } catch(Exception e) {
            throw new ControllerException(e);
        } // try-catch
    
    } // modify

     

    게시글 수정 Post요청을 받는 컨트롤러의 메소드입니다.

    매개변수로 currPage를 추가하면, 자동으로 해당 이름으로 된 전송파라미터를 수집합니다.

    전송파라미터는 모두 String으로 넘어오는데 바로 int로 타입을 지정해도 되는 이유는 서블릿 컨테이너가 자동으로 타입에 맞게 형변환을 해주기 때문입니다.

     

    매개변수로 RedirectAttributes를 추가하고, addAttribute메소드를 이용해 currPage를 등록합니다.

     

    이렇게 하면 리다이렉트 이후에도 해당 전송파라미터가 유지됩니다.

    JSP 또는 자바스크립트에서 el표현식의 내장객체인 param을 이용해 사용할 수 있습니다.

    이 상황에서는 ${ param.currPage } 이렇게 작성하면 됩니다.

     

     


    addFlashAttribute와 addAttribute의 차이점

     

    그렇다면 이 두 개 메소드의 차이는 무엇일까요?

     

     

    addAttribute

    먼저 addAttribute는 등록한 속성들을 전송파라미터로 전달합니다.

    addAttribute를 사용한 후 리다이렉트된 페이지의 url에 쿼리스트링 형식으로 파라미터가 전송됩니다.

     

     

    예를들어 이렇게 추가를 했다면, 

    rttrs.addAttribute("a", 1);
    rttrs.addAttribute("b", 2);

     

     

    이동한 페이지의 url은 이렇게 보여지게 됩니다.

    도메인/매핑한uri?a=1&b=2

     

    또한, addAttribute로 등록된 파라미터들은 지속적으로 유지됩니다. 페이지를 새로고침해도 사용할 수 있습니다.

     

     

    addFlashAttribute

    반면, addFlashAttribute는 flash라는 이름에서 알 수 있듯 1회성입니다.

    저는 반짝!하고 사라지는 속성이라고 생각하고 접근하니 이해가 잘 되었습니다...ㅎㅎ

     

    addFlashAttribute로 등록한 속성들은 파라미터로 전달되는게 아니기 때문에 이동한 페이지의 url에서는 보이지 않습니다.

    1회성이니 당연히 새로고침하면 사라집니다.

     

    또한 2개 이상의 속성을 flashAttribute로 등록할 수 없습니다. 따라서 여러개의 속성을 등록할 땐 맵객체에 담아서 한번에 등록해야 합니다.

     

    그래서 이렇게 getFlashAttributes의 리턴값은 맵으로 지정되어 있습니다.

    맵으로 등록하고, 맵으로 돌려주는 방식입니다. (속성이 하나일 땐 맵 객체로 등록하지 않아도 됩니다.)

     

     


     

    @RequestParam

     

    컨트롤러 메소드에서 전송파라미터를 수집하려할 때, 매개변수의 이름이 전송파라미터와 다를 때는 이 어노테이션을 붙이면 됩니다.

     

    위의 컨트롤러 코드를 다시 예시로 들어, 만약 currPage가 아닌 hehe라는 이름으로 매개변수를 지정하고 싶을 땐 어떻게 하면 될까요?

     

    @PostMapping("/modify")
    public String modify(
        BoardDTO dto, 
        RedirectAttributes rttrs, 
        @RequestParam("currPage") int hehe) throws ControllerException {
        ...

     

    이렇게 어노테이션을 붙여주면 이 hehe매개변수에 currPage 파라미터를 수집할 수 있습니다.

     

    추가로 이 @RequestParam 어노테이션을 필수로 붙여야하는 상황이 있는데,

    같은 이름의 파라미터를 여러개 수집할 때 입니다.

     

    다중체크박스같이 한개의 이름으로 여러개의 값이 전송될 때는 반드시 이 어노테이션을 붙여주어야 컨트롤러에서 수집할 수 있습니다. 타입은 ArrayList<T>나 String[]으로 지정하면 배열로 넘어옵니다.

    댓글

Designed by Tistory.