정리정리

스프링6 @RequestMapping Handler 등록 방식 변화 (feat. @Controller) 본문

Spring

스프링6 @RequestMapping Handler 등록 방식 변화 (feat. @Controller)

wlsh 2023. 11. 16. 19:51

최근에 인프런의 스프링 강의 예제를 스프링 부트 3.1로 따라 치다가 겪은 문제점과 알게 된 점이 있어 정리해 보고자 글을 작성합니다.

문제 상황

우선 문제를 겪은 예제 코드는 다음과 같았습니다.

@RequestMapping
@ResponseBody
public interface OrderControllerV1 {

    @GetMapping("/v1/request")
    String request(@RequestParam("itemId") String itemId);

}

public class OrderControllerV1Impl implements OrderControllerV1 {

    @Override
    public String request(String itemId) {
        return "ok";
    }
}

AOP를 적용하기 전의 과정을 보여주기 위한 예제이기 때문에 따로 @Component가 포함된 @Controller 어노테이션을 사용하지 않고  직접 controller 계층에도 인터페이스를 구현하는 예제였습니다.

하지만 이상하게 간단한 예제였음에도 불구하고 예제를 잘 따라치고 있는지 확인해 보니 404 예외가 발생하였습니다.

강의에서 제공한 코드에서는 잘 작동해서 스프링 버전의 차이에 따른 문제가 있을거라 생각해 2.7 버전으로 내린 후 다시 실행을 해보니 잘 작동을 하였습니다.

//스프링은 @Controller 또는 @RequestMapping 이 있어야 스프링 컨트롤러로 인식

정확히 어떤 차이가 있는지 고민을 하다가 다운받은 예제 코드에 위처럼 적혀있는 부분이 보여서 이에 대한 차이가 생겼다고 판단해 해당 키워드를 기반으로 검색을 하다가 관련된 이슈를 찾게 되었습니다.

결론은 스프링 6부터는 @Controller 없이는 @RequestMapping이 붙은 클래스는 handler로 등록이 되지 않습니다.

그래서 스프링 6을 사용하는 스프링 부트 3에서는 처음에 봤던 예시가 동작하지 않았던 것을 알 수 있었습니다.

디버깅

실제로 어떻게 구현이 바뀌었는지 보고싶어 디버깅을 했고 생각보다 쉽게 찾을 수 있었습니다.

handler를 관리하는 AbstractHandlerMethodMapping 클래스의 processCandidateBean 메서드입니다.

여기서 isHandler라는 추상 메서드를 사용하는데, 해당 메서드를 구현한 RequestHandlerMethodMapping 클래스를 확인해 보면 

스프링 5

스프링 5에서는 위와 같이 구현이 되어있는 것을 볼 수 있지만, 스프링 6에서는 @RequestMapping이 제거가 되어 있는 것을 볼 수 있었습니다.

스프링 6

결론

스프링6, 스프링 부트 3부터는 @RequestMapping은 @Controller나 @RestController 없이는 handler 등록이 되지 않는다.

 

참고

https://github.com/spring-projects/spring-framework/issues/22154

Comments