이번엔 Spring MVC에서 C를 담당하고 있는 Controller Component에 대해 알아 볼 것이다.
이때 Component란?
구성요소라는 뜻으로 독립적인 단위 모듈을 뜻한다.
스프링 부트에선 IoC 컨테이너에 등록된 클래스를 뜻한다.
@Component 어노테이션을 사용해 직접 작성한 클래스를 IoC 컨테이너에 등록 할 수 있다.
추가적으로 이때 IoC 컨테이너에 등록된 객체를 Bean이라고 한다.
이제 Controller Component에 대해 알아보겠다.
Controller Component란?
Client의 요청을 직접적으로 받는 Component이다.
Cleint가 url을 통한 요청을 보내면 해당 url에 매칭되는 Controller가
해당 요청을 handle한다.
소스코드에서 Controller Component는 @Controller 어노테이션을 달고 있다.
이처럼 Controller Component는 클래스 선언부에 @Controller 어노테이션을 달고 있다. (제일 잘 보인다)
@Controller 어노테이션을 통해 IoC 컨테이너에 Bean으로 등록한 것이다.
또한 Presentation Layer에서 사용할 Controller임을 명시한다.
해당 클래스의 내부를 보면 getIndex 메소드 하나 밖에 없다.
그런데 getIndex 메소드가 실질적인 url에 대한 GET 요청을 handle한다.
getIndex()
어노테이션은 잠시만 나중에 보기로 하고 메소드 자체를 보겠다.
우선 getIndex 메소드를 살펴보면 인자로 아무것도 받지 않고 그냥 "index"를 반환하는 메소드이다.
약간 getter처럼 생겼다.
그런데 getIndex 메소드가 url의 GET 요청을 handle한다고 했다.
이때 @GetMapping 어노테이션의 역할이 크다.
@GetMapping
우선 @GetMapping은 @RequestMapping을 상속한다.
@RequestMapping은 요쳥 url 자체를 메소드와 mapping시키는 것이고
@GetMapping은 요청 url에 대한 GET 요청을 메소드와 mapping시키는 것이다.
여기서 눈치가 빠르다면 method = RequestMethod.GET이 무엇을 뜻하는지 바로 알 수 있다.
해당 예제에서는 @GetMapping 어노테이션을 통해 GET : localhost:8000 요청을 getIndex()와 mapping 시킨 것이다.
쉽게 말하자면 이제 localhost:8000로 GET 요청이 오면 getIndex()가 실행 된다는 것이다.
getIndex()가 실행된다는건 무슨 뜻일까?
"index"를 반환한다는 뜻한다는 뜻이다.
그런데 사용자는 GET : localhost:8000 요청을 하면 아래와 같은 페이지가 로드된다.
그럼 이제 index 페이지가 어떻게 로드되는지에 대해 알아볼 것이다.
GET 요청에 대한 페이지 로드
@Controller가 붙은 클래스의 내부 메소드들은 별다른 추가 설정이 없으면,
메소드의 반환 값은 View Resolver를 통해 view 파일의 완전 경로로 만들어 진다.
이때, @Controller 클래스 내부에 있다는 것이 중요하다.
getIndex()는 "index"를 반환했다.
내부적으로 Controller는 ModelAndView객체를 반환하는데 이또한 그냥 model과 view를 감싸는 객체이다.
그러면 이 반환값을 통해 (ModelAndView 객체 내부의 "index" 값)
View Resolver가 갖고 있는 prefix와 suffix를 통해 view 파일의 완전 경로를 만드는 것이다.
완전 경로를 통해 View에서 파일을 불러와 페이지를 로드시킨다.
View Resolver
무슨말이냐면 현재 index.html은 resources/templetes 폴더에 위치한다.
그러면 index.html의 파일 경로는 "resources/templates/index.html"이 된다.
이때, View Resolver는 prefix, "index", suffix를 통해 완전 경로를 만든다고 했다.
prefix는 "resources/templates" 이고 suffix는 ".html"인 것이다.
스프링부트의 기본 설정값이다.
원한다면 설정을 변경 할 수 도 있긴 하다.
View
그리고 index.html은 View에서 꺼내져오고
Client의 브라우저에 render된다.
응답
index.html 파일이 응답으로 온다는 말이다.
postman으로 추가적인 설명을 덧붙이자면,
postman으로 GET : localhost:8000 요청을 보냈다.
아래와 같은 응답이 왔다.
<!DOCTYPE html>을 보면 틀림 없는 html 문서이다.
Headers에서 Content-Type을 확인하면 text/html이다.
@Controller는 이렇게 view(GET) 요청을 handle 하는 것이다.
참고로 postman은 요청을 보내주는 프로그램이다. api 테스트 할 때 용이하다.
@GetMapping에서 2개의 URL
여기까지 어떻게 해당 예제의 @GetMapping("/")이 GET : localhost:8000을 handle 하는지 알아봤다.
그런데 예제를 보면,
@GetMapping({"/", "index"})
uri가 2개다. 이는 최종적으로 mapping 되는 url이 2개임을 뜻한다.
그럼 이제 데이터를 송수신하는 @RequestParam에 대해 알아보겠다.
@RequestParam
Servlet에서 GET 요청때 Parameter로 데이터를 넘겼는데 이것과 똑같다.
request.getParameter("KEY_NAME");
우선 예제를 조금 수정하겠다.
그리고 postman으로 아래의 요청을 날려보았다.
일단 날려보았다.
요청을 보낸후 콘솔을 보니 name이 출력되었다.
GET : localhost:8000?name=jaean의 요청에서 jaean값이 콘솔에 출력된 것을 알 수 있다.
추가적으로 아래에서 보내는 모든 요청은 postman에서 같은 url로 보낼 것이다. (요청 url 변경x)
사실 여기 스프링 부트가 제공하는 편의 기능이 들어가 있다.
@RequestParam은 사실 이런 코드를 통해 작동한 것이다.
이처럼 원래는 @RequestParam에 "KEY_NAME"을 명시해 주어야한다.
Servlet을 사용할 때 항상 명시해왔던 것이다.
그런데 만약 Request Param의 "KEY_NAME"과 Method Param의 이름이 같을 경우
아래의 코드를 자동으로 수행한다.
String KEY_NAME = Request.getParameter("KEY_NAME");
추가적으로 스프링 부트에서는 이름이 같으면 자동으로 수행해주는 기능들이 매우 많다.
심지어 이런것도 된다.
사실 메소드의 파라메터로 기입만 하면 자동으로 받아와진다.
이런 기능들은 @GetMapping을 달아서 되는 것이다.
진짜 매우 편한것 같다. 그런데 여기서 더 편한기능이 존재한다.
그 기능은 다음에 사용 할 것이다.
정리
지금까지 Controller Component에 대해 그리고 내부에서 사용하는 어노테이션들에 대해 알아보았다.
한 줄로 정리하자면 @Controller는 view 요청(GET)을 handle하는데 사용된다는 것을 알 수 있다.
그런데 Comtroller Component중 RestController라는 Component가 아직 하나 더 있다.
@RestController라는 어노테이션을 사용하는 Component이다.
다음에는 @RestController와 이번에는 그냥 넘어간 @RequestMapping에 대해 알아볼 것이다.
추가적으로 해당 예제에서 로드했던 index.html은 아래와 같다.
그냥 페이지 로드용이며 아직 딱히 뭐 없다는 것을 알 수 있다.