Handler Method : @RequestAttribute

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

@RequestAttribute 어노테이션은 HTTP 요청(Request)에서 미리 설정된 속성(attribute)에 접근하는 데 사용됩니다. 이 속성은 필터(Filter)나 인터셉터(HandlerInterceptor) 같은 다른 컴포넌트에서 설정된 값일 수 있으며, 컨트롤러에서 해당 값을 아규먼트로 받아 처리할 수 있습니다.

HttpServletRequest

기본 개념

  • @RequestAttributeHTTP 요청의 속성에 접근하기 위한 어노테이션입니다.
  • 요청 속성은 일반적으로 서블릿 필터(Servlet Filter)핸들러 인터셉터(HandlerInterceptor)에서 설정되며, 이러한 속성을 컨트롤러에서 직접 사용할 수 있습니다.
  • 이 어노테이션을 사용하면, 요청(Request) 범위 내에서 유지되는 데이터를 다른 메서드나 필터에서 추가적으로 활용할 수 있습니다.

예시 상황:

예를 들어, 클라이언트 정보를 추출하는 서블릿 필터가 있다고 가정합시다. 이 필터는 요청이 처리되는 동안 Client 객체를 요청 속성으로 설정합니다. 그런 다음, 해당 Client 객체를 컨트롤러 메서드에서 사용하려면 @RequestAttribute 어노테이션을 통해 접근할 수 있습니다.

예시 코드 (Java)

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

@Controller
public class ClientController {

    @GetMapping("/client")
    public String handle(@RequestAttribute("client") Client client) {
        System.out.println("Client ID: " + client.getId());
        return "clientDetails";
    }
}

코드 설명:

  • @RequestAttribute("client"): 이 어노테이션은 HTTP 요청 속성에서 client라는 이름으로 저장된 객체를 가져와 아규먼트로 전달받습니다.
  • 이 예제에서 Client 객체는 미리 필터나 인터셉터에서 요청 속성으로 설정된 후, 컨트롤러에서 해당 값을 받아 사용합니다.
  • 컨트롤러 메서드는 Client 객체의 ID를 출력하거나 다른 로직에서 사용할 수 있습니다.

필터 또는 인터셉터에서 속성 설정

@RequestAttribute를 사용하려면 먼저 서블릿 필터 또는 인터셉터에서 요청 속성을 설정해야 합니다. 아래는 필터에서 속성을 설정하는 예시입니다.

필터에서 요청 속성 설정 (Java)

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;

public class ClientFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        Client client = new Client(1, "John Doe");  // 가상의 Client 객체 생성
        httpRequest.setAttribute("client", client);  // 요청 속성에 Client 객체 저장

        chain.doFilter(request, response);  // 필터 체인 실행
    }

    @Override
    public void destroy() {}
}

코드 설명:

  • httpRequest.setAttribute("client", client): 이 부분에서 필터는 Client 객체를 client라는 이름으로 HTTP 요청 속성에 저장합니다.
  • 이후 요청이 컨트롤러로 넘어가면, 컨트롤러는 @RequestAttribute를 사용해 이 값을 접근할 수 있습니다.

주의사항

  • @RequestAttributeHTTP 요청에서 속성을 읽어오는 것이며, 요청 범위 내에서만 유효합니다. 이는 세션에서 속성을 가져오는 @SessionAttribute와는 다릅니다. 즉, 요청이 끝나면 속성도 사라집니다.
  • 만약 해당 속성이 요청에 존재하지 않으면 기본적으로 예외가 발생합니다. 이러한 상황을 피하려면 속성이 있을 수도 없을 수도 있는 상황을 처리해야 합니다.

예외 처리 예시

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

@Controller
public class ClientController {

    @GetMapping("/client")
    public String handle(@RequestAttribute(value = "client", required = false) Client client) {
        if (client == null) {
            return "redirect:/error";  // 요청에 client 속성이 없으면 에러 페이지로 리다이렉트
        }
        return "clientDetails";
    }
}

코드 설명:

  • required = false: 요청 속성이 존재하지 않더라도 예외가 발생하지 않고 null이 반환되도록 설정합니다.
  • 속성이 없을 경우 조건에 따라 다른 처리를 할 수 있습니다.

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

Spring WebFlux에서는 @RequestAttribute 어노테이션이 지원되지 않습니다. 대신, WebFlux에서는 요청 속성을 다루기 위해 ServerWebExchange 객체를 사용합니다. 이 객체는 요청과 응답을 다루는 핵심 요소로, 요청 속성에 접근하거나 설정할 수 있습니다.

WebFlux 예시 코드

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

@RestController
public class ReactiveClientController {

    @GetMapping("/client")
    public Mono<String> handle(ServerWebExchange exchange) {
        Client client = exchange.getAttribute("client");  // 요청 속성에서 client 가져오기
        if (client != null) {
            return Mono.just("Client ID: " + client.getId());
        } else {
            return Mono.just("No client in request.");
        }
    }
}

코드 설명:

  • ServerWebExchange: WebFlux에서 요청과 응답을 처리하는 객체로, 요청 속성에 접근할 수 있습니다.
  • exchange.getAttribute("client"): 요청 속성에서 client 객체를 가져옵니다.

요약

  • @RequestAttribute는 HTTP 요청 속성에 접근할 수 있는 어노테이션으로, 필터나 인터셉터에서 미리 설정된 속성을 컨트롤러 메서드의 아규먼트로 받아 처리할 수 있습니다.
  • WebFlux에서는 @RequestAttribute가 지원되지 않으며, 대신 ServerWebExchange를 사용하여 요청 속성에 접근합니다.

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