Spring

Spring - Spring Boot 3.x에서 View 렌더링되지 않는 원인과 해결 방법

Cold Bean 2025. 1. 16. 01:03
728x90

 

배경

Spring Boot 3로 프로젝트를 개발하던 중 에러가 발생했다. 간단한 웹 페이지를 JSP로 구현하고 있었는데, 페이지를 열어보니 JSP 화면 대신 Whitelabel Error Page가 나타났다. 컨트롤러에서 main이라는 뷰 이름을 반환했고, 해당 JSP파일도 정확한 위치에 있었다. 그런데 왜 Spring Boot는 JSP를 찾지 못하고 Whitelabel Error Page를 표시하는걸까? 

build.gradle

dependencies {
    ...

    // JSP
    implementation 'org.apache.tomcat.embed:tomcat-embed-jasper'
    implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl'
}

application.yml

spring:
  mvc:
    view:
      prefix: /WEB-INF/views/
      suffix: .jsp

SecurityConfig

@Configuration
public class SecurityConfig {

    public static final String[] PUBLIC_URLS = {
        "/", "/tools/**", "/login/**", "/error"
    };

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(AbstractHttpConfigurer::disable)
            .headers((headers) -> headers.frameOptions(FrameOptionsConfig::disable))
            .authorizeHttpRequests((authorizeRequests) -> authorizeRequests
                .requestMatchers(PUBLIC_URLS).permitAll()
                .anyRequest().authenticated());

        return http.build();
    }
}

Contorller

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/tools")
public class AIToolController {

    private final AiToolService aiToolService;

    @GetMapping
    public ModelAndView getMainPageInfo() {
        ModelAndView mv = new ModelAndView();
        mv.addObject("mainPageInfo", aiToolService.getMainPageInfo());
        mv.setViewName("main");

        return mv;
    }
}

 

개발 환경

  • Java 17
  • Spring Boot 3.x
  • Spring Security 6
  • Gradle
  • JSP
  • H2
  • IntelliJ

 

원인

If you are using Spring MVC to resolve view names, you will need to permit FORWARD requests. This is because when Spring MVC detects a mapping between view name and the actual views, it will perform a forward to the view. As we saw on the previous section, Spring Security 6.0 will apply authorization to FORWARD requests by default.

스프링 공식문서를 보면 Spring Security 5.8 버전까지는 기본적으로 요청당 한 번만 인증을 수행하기 때문에 이후의 FORWARD, INCLUDE 같은 Dispatcher Type 요청에 대해서는 인증을 수행하지 않았다. 6.0 버전부터는 모든 Dispatcher Type 요청에 대해서도 인증을 수행하도록 변경되었다. 이러한 변경으로 인해 View를 렌더링할 때, 특히 FORWARD 요청을 명시적으로 허용하도록 설정해야 한다.

 

JSP와 FORWARD가 무슨 상관일까?

FORWARD는 RequestDispatcher를 통해 서버 내부에서 다른 리소스로 요청을 전달하는 역할을 한다. DispatcherServlet은 ViewResolver를 통해 View 객체를 반환하는데, JSP를 사용할 경우 InternalResourceViewResolver가 사용한다. 이 과정에서 내부적으로 FORWARD 요청이 된다. Spring Security 6.0에서는 이 FORWARD 요청에 대해서도 인증을 수행하므로, 명시적인 허용 설정이 없으면 에러가 발생하게 된 것이다.

 

해결

Spring Security Config 설정에서 DispatcherType.FORWARD 요청을 허용하도록 추가했다.

@Configuration
public class SecurityConfig {

    public static final String[] PUBLIC_URLS = {
        "/", "/tools/**", "/login/**", "/error"
    };

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(AbstractHttpConfigurer::disable)
            .headers((headers) -> headers.frameOptions(FrameOptionsConfig::disable))
            .authorizeHttpRequests((authorizeRequests) -> authorizeRequests
                .requestMatchers(PUBLIC_URLS).permitAll()
                .dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll()	// 추가
                .anyRequest().authenticated());

        return http.build();
    }
}

화면이 잘 출력되는 것을 확인할 수 있다.

참조

 

Authorization Migrations :: Spring Security

The following steps relate to changes around how authorization is performed.

docs.spring.io

 

Spring Security 6 and JSP view rendering

I'm upgrading an application from Spring Boot 2.7 to Spring Boot 3 which includes updating to Spring Security 6. We have the following properties set: spring.mvc.view.prefix=/WEB-INF/view/ spring.mvc.

stackoverflow.com

 

RequestDispatcher (Java(TM) EE 7 Specification APIs)

Forwards a request from a servlet to another resource (servlet, JSP file, or HTML file) on the server. This method allows one servlet to do preliminary processing of a request and another resource to generate the response. For a RequestDispatcher obtained

docs.oracle.com

 

728x90