도도한 개발자
[@MVC 미션] @Controller(value) vs @RequestMapping(value) 본문
본 게시물은 우아한테크코스 미션을 하면서 작성한 글입니다.
🐈⬛ @RequestMapping을 사용하면서...
MVC 미션 코드리뷰 하면서 헷갈리는 개념을 발견했습니다.
HandlerKey를 만들 때 생성자에 RequestMapping 어노테이션의 value와 http method를 인자로 넘겨줘야 하는데 이때 value는 요청이 처리되는 url 경로입니다.
public static List<HandlerKey> keysByAnnotation(RequestMapping annotation) {
List<HandlerKey> handlerKeys = new ArrayList<>();
String value = annotation.value(); // 여기
RequestMethod[] requestMethods = annotation.method();
for (RequestMethod requestMethod : requestMethods) {
handlerKeys.add(new HandlerKey(value, requestMethod));
}
return handlerKeys;
}
“여기”를 보시면 annotation의 value를 가져옵니다. 어떤 값이 들어있을까요?
@Controller
public class MyController {
@RequestMapping(value = "/request-url", method = RequestMethod.GET)
public String sayHello() {
return "hello";
}
}
임시로 만든 컨트롤러 클래스입니다. 여기서 value와 method는 @RequestMapping 옆에 있는 속성 값인 것을 확인할 수 있습니다.
그러면 value가 “/request-url”이 되겠죠.
🐾 만약 컨트롤러 클래스가 다음과 같이 생겼으면 어떨까요?
@Controller("test")
@RequestMapping("/test")
public class MyController {
@RequestMapping(value = "/request-url", method = RequestMethod.GET)
public String sayHello() {
return "hello";
}
}
@Controller 어노테이션에 value의 값으로 "test"를 지정했고 (@Controller 어노테이션엔 value 속성밖에 없습니다.)
바로 밑에 @RequestMapping 어노테이션의 value 값으로 “/test”를 지정했습니다.(속성이 하나면 value가 디폴트 속성이 됩니다.)
🐾이때 매핑 url을 /test/request-url로 지정하고 싶으면 어떻게 해야 할까요?
@Controller의 속성이 사용될까요 아님 @RequestMapping의 속성이 사용될까요?
이를 알기 위해선 이 둘의 value 속성이 어떤 역할을 하는지 알아야 할 필요가 있어보입니다.
스프링 프레임워크에서 @Controller의 value와 @RequestMapping의 value는 서로 다른 목적을 가지고 있습니다.
🐾@Controller의 value
@Controller은 클래스 레벨에서 사용되며, 해당 클래스가 컨트롤러 클래스임을 나타냅니다. 이 어노테이션은 일반적으로 패키지 스캔 및 컴포넌트 스캔을 통해 스프링 애플리케이션 컨텍스트에 빈으로 등록되어 관리됩니다. @Controller의 value 속성은 해당 컨트롤러 빈의 이름을 지정할 때 사용됩니다.
예를 들어, 위의 컨트롤러 클래스에서 "test"는 MyController 클래스의 빈 이름으로 사용됩니다. 이것은 주로 빈의 이름을 명시적으로 설정하고 싶을 때 사용됩니다. 만약 value 속성을 지정하지 않으면 스프링은 기본적으로 클래스 이름의 첫 글자를 소문자로 바꾼 이름을 사용합니다.
🐾 @RequestMapping의 value:
@RequestMapping은 메서드 레벨에서 사용되며, 해당 메서드가 요청을 처리하는 URL 경로를 지정합니다. @Controller 클래스 내부의 메서드에 적용되며, 해당 메서드가 어떤 URL 경로에 대한 요청을 처리할지를 정의합니다. @RequestMapping의 value 속성은 요청을 어떤 경로에 매핑할 것인지를 지정하며, 클라이언트가 해당 경로로 요청을 보낼 때 이 메서드가 호출됩니다.
예를 들어, 위의 코드에서 @RequestMapping("/test")는 /test 경로에 대한 요청을 처리하고, @RequestMapping("/request-url")은 /request-url 경로에 대한 요청을 처리합니다.
그래서 이 둘의 경로를 더한 /test/request-url을 경로로 요청하고 싶다면 다음과 같이 클래스를 찾아내 그 클래스 단의 @RequestMapping의 value값을 추출하고, 메소드 단의 @ReqeustMapping의 value값을 추출해 합치면 됩니다.
private void initHandlerExecutions() {
Reflections reflections = new Reflections(basePackage);
Set<Class<?>> typesAnnotatedWith = reflections.getTypesAnnotatedWith(Controller.class);
for (Class<?> aClass : typesAnnotatedWith) {
String rootUrl = aClass.getAnnotation(RequestMapping.class).value();
for (Method method : aClass.getDeclaredMethods()) {
String url = method.getAnnotation(RequestMapping.class).value();
String requestUrl = rootUrl + url;
}
}
}
(위 코드는 이해를 돕기 위해 메서드 분리를 하지 않았습니다.)
🐈⬛ 요약하면
@Controller 어노테이션의 **value**는 컨트롤러 빈의 이름을 지정하고, @RequestMapping 어노테이션의 **value**는 메서드가 처리할 URL 경로를 지정합니다.
그런데 1단계 미션에선 컨트롤러 클래스에 rootUrl을 지정해주는 @RequestMapping이 없어서 쓸 일이 아직은 없는 것 같네요. 감사합니다.
'우아한테크코스' 카테고리의 다른 글
[카페인] Repository 테스트 격리가 안돼요(이제 돼요) (3) | 2023.09.01 |
---|---|
[우아한테크코스] 레벨3 레벨 인터뷰 회고 (1) | 2023.08.30 |
누가 도메인 테스트에서 Fixture를 사용하였는가 (0) | 2023.08.12 |