본문 바로가기

개발/Spring

[스프링] @Controller - 세션 관리@SessionAttributes

출처: 엄마가공부하래

서블릿은 기본적으로 상태를 유지하지 않는다. 상태를 유지해줘야 하는 경우에 사용한다. 

도메인 중심 프로그래밍 모델과 상태 유지를 위한 세션 도입의 필요성
ex) 수정 페이지의 처리 방법
  1. hidden 필드 사용시 단점
    • 데이타 보안의 문제.
    • 사용자 정보에 새로운 필드가 추가되거나 수정되었을 때 실수 우려.
  2. DB 재조회
    • 자원 낭비
    • 복잡한 코드
  3. 계층 사이의 강한 결합
    • 각 계층이 도메인 모델을 따라 만든 도메인 오브젝트에만 의존하도록 만들면 각 계층 사이에 의존성과 결합도를 대폭 줄일 수 있다.
    • 모든 계층의 코드가 서로 영향을 주지 않고 독립적으로 확장하거나 변경할 수 있고, 여러 개의 로직에서 공유할 수 있다.
    • 수정할 필요가 있는 필드가 어떤 것인지 모든 계층의 메소드가 다 알고 있게 하는 방식이다. 하지만 다음과 같은 단점이 존재한다. 
      • 애플리케이션이 복잡해질 경우 코드의 중복이 늘어난다.
      • 한쪽을 수정하면 연관된 코드도 다 함께 수정해줘야 한다.
      • 테스트가 힘들어 지고 테스트 코드에도 중복이 일어난다.

==> 그래서 해결책은 ???

[해결책]

@SessionAttributes

  1. 컨트롤러 메소드가 생성하는 모델 정보 중에서 @SessionAttributes에 지정한 이름과 동일한 것이 있다면 이를 세션에 저장해준다.
    • ==> 뷰가 이 모델을 참조해서 기존 사용자 정보를 폼에 뿌려줄 수 있게 하기 위함.
  2. @ModelAttribute가 지정된 파라미터가 있을 때 이 파라미터에 전달해줄 오브젝트를 세션에서 가져온다.
    • ==> 파라미터에 @ModelAttribute가 있으면 해당 타입의 새 오브젝트를 생성한 후에 요청 파라미터 값을 프로퍼티에 바인딩해준다.
    • ==> 하지만 @SeesionAttributes에 선언된 이름과 @ModelAttribute의 모델 이름이 동일하면,
      1. 세션에 같은 이름의 오브젝트가 존재하는지 확인
      2. 존재한다면 세션에 있는 오브젝트를 가져와 @ModelAttribute파라미터로 전달해줄 오브젝트로 사용한다
      3. 존재하지 않는 다면 오브젝트를 새로 만들어서 오브젝트로 사용한다.

@Controller
@SessionAttributes("user")
public class UserController {
            ...
@RequestMapping(value="/user/edit", method=RequestMethod.GET)
    public String form(@RequestParam int id, Model model) {
        model.addAttribute("user", userService.getUser(id));
        return "user/edit";
    }

    @RequestMapping(value="/user/edit", method=RequestMethod.POST)
    public String submit(@ModelAttribute User user) { ... }
}

a. form() : DB에서 user 오브젝트를 생성해서 폼으로 넘긴다. 
b. 폼에서는 user 오브젝트를 참조해서 정보를 뿌려준다.
c. 폼에서 사용자 입력 값을 submit() 으로 전송한다. 
d. submit() : 폼에서 전송해준 파라미터만 바인딩한 뒤에 컨트롤러의 user 파라미터로 넘겨
e. 만약 검증 오류가 발생하면 다시 사용자 폼을 띄워준다. 
  • 하나 이상의 모델을 세션에 저장하도록 지정할 수 있다.
  • @SessionAttributes의 설정은 클래스의 모든 메소드에 적용된다.
  • 컨트롤러 메소드에 의해 생성되는 모든 종류의 모델 오브젝트는 @SessionAttributes에 저장될 이름을 갖고 있는지 확인된다.
  • 여러대로 구성된 서버의 경우는 어떻게 처리해야 하나?????

SessionStatus

  • @SessionAttributes를 사용할 때는 더 이상 필요 없는 세션 애트리뷰트를 코드로 제거해줘야 한다.
  • SessionStatus는 컨트롤러 메소드의 파라미터로 사용할 수 있는 스프링 내장 타입이다.

@RequestMapping(value="/user/edit", method=RequestMethod.POST)
public String submit(@ModelAttribute User user, SessionStatus sessionStatus) { 
    this.userService.updateUser(user);    
    sessionStatus.setComplet();    // 세센에 저장된 정보를 모두 제거한다. 
    return "user/editsuccess";
}

등록 폼을 위한 @SessionAttributes 사용

  • 등록 폼에서도 @SessionAttributes를 사용하자.
  • 더 강력한 상태유지 방식의 애플리케이션을 만들려면 스프링의 포트폴리오 프로젝트인 SWF(Spring Web Flow)를 검토해 보자.

스프링 목 오부젝트와 AbstractDispacherServletTest를 이용해 세션 테스트 만들기
준비중