Handler Method : @SessionAttribute

2024. 10. 9. 12:27Spring Framework/Web on Servlet Stack

@SessionAttribute 어노테이션은 HTTP 세션에서 미리 존재하는 세션 속성을 컨트롤러 메서드의 아규먼트로 가져오는 데 사용됩니다. 이는 세션에 저장된 특정 데이터를 컨트롤러에서 바로 사용할 수 있도록 해줍니다. @SessionAttribute세션에 이미 존재하는 속성에 접근할 때 유용하며, 새로운 값을 세션에 저장하거나 관리하는 것이 아닌, 세션에 저장된 값을 읽어오는 역할을 합니다.

기본 개념

  • @SessionAttribute는 주로 글로벌하게 관리되는 세션 속성에 접근하는 데 사용됩니다. 예를 들어, 세션에 이미 저장된 사용자 정보나 인증 정보를 가져올 때 유용합니다.
  • 이 어노테이션을 사용하면, 컨트롤러 메서드에서 미리 존재하는 세션 속성을 직접 아규먼트로 받을 수 있습니다.
  • 만약 세션에 해당 속성이 없을 경우, 기본적으로 예외가 발생합니다. 따라서 해당 속성이 세션에 존재할 수 있거나 없을 수 있는 경우, 이를 선택적으로 처리할 필요가 있습니다.

예시 상황:

사용자가 로그인했을 때 세션에 사용자 정보가 저장되어 있다고 가정해봅시다. 이 정보를 세션에서 가져와 컨트롤러에서 처리하고자 할 때 @SessionAttribute를 사용하여 세션에 저장된 User 객체를 바로 아규먼트로 받을 수 있습니다.

예시 코드 (Java)

import org.springframework.web.bind.annotation.SessionAttribute;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.stereotype.Controller;

@Controller
public class HomeController {

    @GetMapping("/")
    public String handle(@SessionAttribute("user") User user) {
        System.out.println("User name: " + user.getName());
        return "home";
    }
}

코드 설명:

  • @SessionAttribute("user"): 세션에 저장된 user라는 이름의 속성을 가져와 아규먼트로 사용합니다. 이 user 객체는 미리 세션에 저장되어 있어야 하며, 컨트롤러 메서드에서 이를 바로 활용할 수 있습니다.
  • 세션에서 가져온 User 객체의 이름을 출력하는 예시로, 이 값은 세션을 통해 유지되고 전달된 정보입니다.

세션 속성 관리

@SessionAttribute는 세션에 이미 존재하는 값에만 접근하는 기능을 제공합니다. 따라서 세션에 속성을 추가하거나 제거하는 기능이 필요할 때는 다른 방법을 사용해야 합니다.

예시 코드 (세션 추가 및 삭제)

세션에 속성을 추가하거나 삭제하려면 HttpSession 또는 WebRequest 객체를 사용하여 세션을 직접 조작할 수 있습니다.

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.servlet.http.HttpSession;

@RestController
@RequestMapping("/session")
public class SessionController {

    // 세션에 값 추가
    @GetMapping("/add")
    public String addToSession(HttpSession session) {
        User user = new User("John Doe");
        session.setAttribute("user", user);  // 세션에 "user" 저장
        return "User added to session.";
    }

    // 세션에서 값 가져오기
    @GetMapping("/get")
    public String getSessionValue(@SessionAttribute("user") User user) {
        return "User from session: " + user.getName();
    }

    // 세션에서 값 삭제
    @GetMapping("/remove")
    public String removeFromSession(HttpSession session) {
        session.removeAttribute("user");  // 세션에서 "user" 삭제
        return "User removed from session.";
    }
}

코드 설명:

  • 세션에 값 추가: HttpSession을 사용해 세션에 user 속성을 추가합니다.
  • 세션에서 값 가져오기: @SessionAttribute("user")를 사용해 세션에 저장된 user 객체를 가져와 출력합니다.
  • 세션에서 값 삭제: HttpSession.removeAttribute() 메서드를 통해 세션에서 user 속성을 제거합니다.

주의사항

  • @SessionAttribute이미 세션에 존재하는 값을 읽어오는 데 사용되므로, 세션에 해당 속성이 없으면 예외가 발생할 수 있습니다. 세션에 값이 있을 수 있고 없을 수도 있는 상황에서는 예외 처리 또는 기본값을 설정하는 방법을 고려해야 합니다.

예외 처리 예시

import org.springframework.web.bind.annotation.SessionAttribute;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.stereotype.Controller;
import java.util.Optional;

@Controller
public class HomeController {

    @GetMapping("/")
    public String handle(@SessionAttribute(value = "user", required = false) User user) {
        if (user == null) {
            return "redirect:/login";  // 세션에 사용자 정보가 없으면 로그인 페이지로 리다이렉트
        }
        return "home";
    }
}

코드 설명:

  • required = false: 세션에 해당 속성이 없어도 예외가 발생하지 않으며, 이 경우 null 값이 아규먼트로 전달됩니다. 이로 인해 세션에 user 속성이 없으면 조건에 따라 다른 처리를 할 수 있습니다.

Reactive 스택에서의 사용 (Spring WebFlux)

Spring WebFlux에서는 @SessionAttribute 어노테이션이 지원되지 않습니다. WebFlux는 비동기적으로 동작하며 HTTP 세션을 처리하기 위해 WebSession을 사용합니다. 이를 통해 세션 데이터에 비동기적으로 접근하고, 필요한 데이터를 처리할 수 있습니다.

WebFlux 예시 코드

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.WebSession;
import reactor.core.publisher.Mono;

@RestController
public class ReactiveSessionController {

    @GetMapping("/session/get")
    public Mono<String> getSessionValue(WebSession session) {
        return session.getAttribute("user")
                .map(user -> "User from session: " + user.toString())
                .defaultIfEmpty("No user in session.");
    }
}

코드 설명:

  • WebSession: WebFlux에서는 WebSession 객체를 사용해 세션 데이터를 비동기적으로 관리합니다.
  • 세션에서 user 속성을 가져오고, 속성이 없으면 기본 메시지를 반환하는 방식입니다.

요약

  • @SessionAttribute는 세션에 이미 저장된 속성을 컨트롤러에서 직접 아규먼트로 받아오는 어노테이션입니다.
  • 세션 속성 추가/삭제는 HttpSession이나 WebRequest를 통해 관리할 수 있습니다.
  • WebFlux에서는 @SessionAttribute 대신 WebSession을 사용하여 비동기적으로 세션을 처리합니다.

참고: https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/sessionattribute.html