🌸개요🌸
SpringBoot version up (1.3.X -> 3.2.1) 과정에서 migration하는 중 타임리프 역시 2 -> 3 버전으로 올라가는 상황이였습니다.이때 thymeleaf에서 #httpServletRequest 기본 기능을 더이상 지원하지 않는 것을 확인했습니다.
https://www.thymeleaf.org/doc/articles/thymeleaf31whatsnew.html
Thymeleaf 3.1: What’s new and how to migrate - Thymeleaf
Thymeleaf 3.1: What’s new and how to migrate Latest version is Thymeleaf 3.1.3.RELEASE.What’s newSupport for Servlet API 5.0 and the jakarta.* class namespaceThymeleaf 3.1 adds support for the new jakarta.* class namespace in the Servlet API since vers
www.thymeleaf.org
As explained in the “What’s new” section, expression utility objects #request, #response, #session and #servletContext are no longer available from expressions in templates.
‼️문제점
기존에는 Spring Boot에서 Thymeleaf를 사용해 웹 애플리케이션을 개발하는 경우, 이전 버전에서는 #httpServletRequest를 통해 현재 요청 정보를 쉽게 가져올 수 있었습니다.
<!-- Thymeleaf 2.x에서 사용 가능 -->
<p th:text="${#httpServletRequest.requestURI}"></p>
그러나 Thymeleaf 3.x부터 #httpServletRequest가 제거되었기 때문에, 이 코드는 더 이상 동작하지 않습니다.
#httpServletRequest.requestURI의 경우 공통 html에서 사용 중이므로 #httpServletRequest가 더이상 지원되지 않는 경우면 Controller에 modelAttribute에 해당 값을 넣어줘야되는 상황이 발생했었습니다.
(물론 이외에도 변경사항 및 미지원 기능이 존재했지만 httpServletRequest 기능 미지원에 대한 문제점에 대한 부분만 작성하였습니다.)
🤔 고민
모든 Controller에 modelAttribute 값을 추가해주는 노가다를 하는 것이 맞을까?
이 것은 Controller가 너무 많아 노가다를 해주는 것이 바람직하지는 않다고 생각했습니다. 그래서 전역 설정해줄 수 있는 2가지 방법에 대해서 생각해봤습니다.
생각 1 : @ControllerAdvice 사용한 전역 설정
@ControllerAdvice
public class ControllerHandler{
@ModelAttribute
public void handleRequest(HttpServletRequest request, Model model) {
String requestURI = request.getRequestURI();
// requestURI 값 공통적으로 model에 add
model.addAttribute("requestURI", requestURI);
}
}
생각 2 : Interceptor를 활용한 전역 설정
- global Interceptor 생성
@Component
public class GlobalRequestAttributeInterceptor implements HandlerInterceptor {
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
if (modelAndView != null) {
String requestUri = request.getRequestURI();
modelAndView.addObject("requestUri", requestUri);
}
}
}
- interceptor 등록
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private GlobalRequestAttributeInterceptor globalRequestAttributeInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(globalRequestAttributeInterceptor);
}
}
🔥 결론: 어느 방법이 더 좋을까?
비교 항목 | @ControllerAdvice (@ModelAttribute) | Interceptor (HandlerInterceptor) |
적용 대상 | Spring MVC (Thymeleaf 뷰) | 모든 요청 (Thymeleaf, REST API 등) |
적용 범위 | Model이 있는 모든 요청 | postHandle 이후 ModelAndView 응답이 있는 요청 |
예외 처리 | @ExceptionHandler에서 별도 추가 필요 | 예외 발생 시 호출되지 않음 |
데이터 처리 시점 | 컨트롤러 실행 전에 Model에 추가 | 컨트롤러 실행 후 ModelAndView에 추가 |
REST API 적용 가능 여부 | ❌ (불가능) | ✅ (가능) |
우선 Interceptor의 경우 모든 요청(Thymeleaf + REST API)에서 사용 가능하므로 모든 요청에 대해서 처리 할 수 있었습니다. 하지만 이 경우에는 Thymeleaf에서만 처리해주면 되기 때문에 Interceptor까지는 필요하지 않다고 생각하였습니다.
Thymeleaf 위한 처리 면 @ControllerAdvice + @ModelAttribute 활용한 처리 방식이 더 옳다고 생각해 해당 방식을 적용하였습니다 🚀
'Spring' 카테고리의 다른 글
[SpringCamp] SpringCamp 2025 10주년 기념 방문 후기 (0) | 2025.07.06 |
---|---|
spring.profiles.active vs spring.config.activate.on-profile? (0) | 2024.10.08 |
쿠폰발급 서비스 동시성 처리하기3 - (3/3) (feat.Redis) (0) | 2024.02.13 |
쿠폰 발급 서비스 동시성 처리하기 2 - (2/3) (feat. Database Lock) (1) | 2024.01.30 |
쿠폰 발급 서비스 동시성 처리하기 1 - (1/3) (feat. synchronized) (0) | 2024.01.15 |