책의 예제에서 발견한 세션 중복 문제?

maketheworldwise·2022년 4월 3일
0


이 글의 목적?

책의 게시판 예제 속에서 세션을 처리하는 부분이 기억에 남아 최대한 간략하게 어떤 문제가 있었는지, 어떻게 해결했는지 정리해보고자 한다.

세션 처리?

간략하게 책에서 어떻게 세션을 처리했는지 정리해보자.

  • @SessionAttributes를 사용하면 @ModelAttribute 또는 model.addAttribute()를 이용하여 객체를 저장할 경우 세션에 저장이 되도록 지정할 수 있다. 세션이 파괴되거나 SessionStatus 객체를 이용하여 명시적으로 지울 때까지 동일한 세션에서는 계속 사용할 수 있다.

  • @ModelAttribute을 이용하여 HttpServletRequest를 이용하여 자동으로 바인딩된다. @SessionAttributes에 이미 객체가 지정된 경우 세션에 의한 바인딩이 먼저 실행되고 그 후 HttpServletRequest로 갱신된다.

  • 세션은 서버의 메모리 자원이기 때문에 더 이상 사용하지 않을 경우에는 SessionStatussetComplete() 메서드를 이용하여 세션을 종료해준다.

@Controller
@SessionAttributes("boardVO") 
public class BoardController {

	// 생략
    
    @RequestMapping(value = "/board/read/{seq}")
    public String read(Model model, @PathVariable int seq) {
    	model.addAttribute("boardVO", boardService.read(seq));
        return "/board/read";
    }
    
    // GET 요청
    @RequestMapping(value = "/board/write", method = RequestMethod.GET)
    public String write(Model model) {
    	model.addAttribute("boardVO", new BoardVO());
        return "/board/write";
    }
    
    // POST 요청
    @RequestMapping(value = "/board/write", method = RequestMethod.POST)
    public String write(@Valid BoardVO boardVO, BindingResult bindingResult) {
    	if(result.hasErrors()) {
        	return "/board/write";
        } else {
        	boardService.write(boardVO);
            sessionStatus.setComplete();
            return "redirect:/board/list";
        }
    }
    
    // GET 요청
    @RequestMapping(value = "/board/edit/{seq}", method = RequestMethod.GET)
    public String edit(@PathVariable int seq, Model model) {
    	BoardVO boardVO = boardService.read(seq);
        model.addAttribute("boardVO", boardVO);
        return "/board/edit";
    }
    
    // POST 요청
    @RequestMapping(value = "/board/edit/{seq}", method = RequestMethod.POST)
    public String edit(@Valid @ModelAttribute BoardVO boardVO,
    				   BindingResult result, int pwd,
                       SessionStatus sessionStatus, Model model) {
		if(result.hasErrors()) {
        	return "/board/edit";
        } else {
        	if(boardVO.getPassword() == pwd) {
            	boardService.edit(boardVO);
                sessionStatus.setComplete();
                return "redirect:/board/list";
            }
        }
        
        model.addAttribute("msg", "비밀번호가 일치하지 않습니다.");
        return "/board/edit";
	}
}

세션 중복 문제 및 해결

위의 코드 기반으로 책에서 이야기하는 문제점은 간단하다. 바로 수정을 한다고 했을 때, 항상 "/board/read" 요청이 선행된다는 것이다. 즉, read() 메서드에서 model.addAttribute("boardVO", boardService.read(seq)); 코드가 먼저 수행이 되어 GET 요청으로 edit() 메서드가 실행되기 전에 세션에 객체가 이미 저장되어있게 된다는 의미다.

해결 방법은 간단하다. GET 요청을 처리하는 edit() 메서드에서 세션에 객체를 추가하는 로직을 삭제해주기만 하면 된다.

// GET 요청
@RequestMapping(value = "/board/edit/{seq}", method = RequestMethod.GET)
public String edit(@PathVariable int seq, Model model) {
    BoardVO boardVO = boardService.read(seq);
    return "/board/edit";
}

이 글을 왜 남기려고 하는가?

해결 방법은 굉장히 단순한데 굳이 이 내용을 글로 남겨두는 이유는, 내가 평상시에 보지 못하는 영역이기 때문이다. 아마 기존의 나였다면 중복으로 객체가 추가되는 부분을 놓쳤을 거라고 생각한다. 그저 세션의 사용 목적과 사용 방법만을 아는 것이 아닌, 코드상에서 문제가 발생할 수 있는 지점을 찾아내는 능력을 키울 필요성이 있다는 것을 잊지 않기 위해 글로 정리해보았다.

이 글의 레퍼런스

  • 스프링 입문을 위한 자바 객체 지향의 원리와 이해
profile
세상을 현명하게 이끌어갈 나의 성장 일기 📓

0개의 댓글