본문 바로가기
Back-End/Spring

[디버깅] Maven으로 빌드한 스프링부트 프로젝트에서 템플릿 파일 인식

by blackjack_96 2024. 7. 18.

 

현재 Spring Security를 이용하여 로그인 기능을 구현하고 있습니다.

스프링부트 프로젝트에서, Spring Security가 의존성으로 사용이 되는 상태에서 아무런 설정을 하지 않을 경우,

/login으로 접속 하면,

Spring Security에서 제공하는 기본 로그인 폼이 나오게 됩니다.

 

스프링 시큐리티에서 제공하는 디폴트 로그인 창

 

하지만 저는,

/login이라는 url로 접속을 하면
다음과 같이 제가 직접 정의한 로그인 폼이 나오도록 하고 싶습니다.

 

내가 만든 로그인 창

 

그래서 다음과 같이, 

DefaultSecurityFilterChain을 정의하고 Bean으로 등록을 하였습니다.

    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {

        .. 나머지 부분 생략 ..
        http.authorizeHttpRequests(
                // 인증이 필요한 url, 인증 없이도 접근 가능한 url 을 설정하는 부분이다.
                (requests) -> requests.
                        requestMatchers(urlsToBeAuthenticated).authenticated().
                        requestMatchers(urlsToBePermittedAll).permitAll()).
                // 사용자가 web browser 를 통해 접근하려고 하면 폼 로그인 기반의 인증이 적용.
                formLogin(formLogin -> formLogin
                        .loginPage("/login")
                        .usernameParameter("username") // 입력된 아이디는 username 이라는 이름의 파라미터로 넘어가서 처리되도록
                        .passwordParameter("password") // 입력된 비밀번호는 password 이라는 이름의 파라미터로 넘어가서 처리되도록
                        .successHandler(customAuthenticationSuccessHandler) // 로그인 성공 시 동작하는 로직을 정의하고 리다이렉션하는 부분
                        .failureHandler(customAuthenticationFailureHandler) // 로그인 실패 시 동작하는 로직을 정의하고 리다이렉션하는 부분
                        .permitAll())
        
        .. 나머지 부분 생략 ..

        return http.build();
    }

 

위에서 formLogin설정 부분만을 보시면 됩니다.

formLogin설정을 통해서,

스프링 시큐리티의 로그인 기능이 invoke될 시에,

"/login"페이지로 리다이렉션이 되도록 하였습니다.

 

그리고 다음과 같이 LoginController를 정의하였습니다.

 

@Controller
@RequiredArgsConstructor
@Slf4j
public class LoginController {

    private final CustomerRepository customerRepository;
    private final PasswordEncoder passwordEncoder;

    @GetMapping("/login")
    public String loginForm(
            @RequestParam(value = "error", required = false) String error,
            @RequestParam(value = "logout", required = false) String logout,
            Model model) {

        log.info("login controller invoked!");
        return "form/login";
    }

 

즉 /login이라는 요청이 들어올 시,

resources/templates/form/login.html이라는 리소스가 서버쪽에서 렌더링이 되어서,

클라이언트에게 전달이 되도록 코드를 구현한 것입니다.

 

하지만 이렇게 하니

resources/templates/form/login.html 라는 자원을 찾지 못했다는,

Not Found Static File 에러가 발생하며

자꾸만 /error페이지로 리다이렉션이 되었습니다.

 

이 에러가 왜 발생하는가 하면,

Maven으로 빌드한 스프링 부트 프로젝트에서

정적 파일의 위치를 알아내기 위해서는 몇 가지 설정을 해줘야하는데, 그걸 생략했기 때문입니다.

 

Gradle로 스프링부트 프로젝트를 빌드하면

별다른 설정을 하지 않아도 resources/templates경로에 있는 정적인 리소스에 대한 접근이 가능하지만,

Maven에서는 이 정적 자원을 스프링부트 프로젝트에서 인식할 수 있도록 하기 위해 몇가지 단계를 거쳐야 합니다.

 

단계 1. pom.xml에 thymeleaf 의존성, 그리고 정적 자원 리소스 위치를 추가하기

 

// Thymeleaf의존성 추가

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
   // 정적 자원의 리소스 위치 식별할 수 있게 하기
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
    </build>

 

단계2. 타임리프 사용을 위한 타임리프 설정 객체를 Bean으로 등록

 

Configuration클래스에 다음과 같은 빈을 정의해 두어서 

애플리케이션 시작 시에 스프링 컨테이너에서 Bean으로 관리되도록 하였습니다.

    @Bean
    public SpringResourceTemplateResolver templateResolver() {
        SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
        resolver.setPrefix("classpath:/templates/");
        resolver.setSuffix(".html");
        return resolver;
    }

 

이렇게 두 단계만 거치면, Maven을 통해 빌드한 스프링부트 프로젝트에서

resources/templates에 위치한 정적 파일들을 인식할 수 있게 됩니다.

 

그래서, 특정한 static 파일을 찾지 못해서 /error로 리다이렉션 되는 오류를 더이상 접하지 않을 것입니다.