Spring MVC 4(2): 웹 페이지 작성 실습 1 & 2 { Controller 작성, web.xml 설정 다시 이해하기, 설정 정상 여부 테스트 }
Ben의 프로그램2023. 8. 8. 01:00
728x90
Controller(Handler) 클래스 작성하기(1) : @Controller, @ComponentScan, @RequestMapping 알아보기
-) @Controller, @ComponentScan 컨트롤러 클래스에는 @Controller 애노테이션을 위에 붙여줍니다. 그렇게 하면 아 이것이 컨트롤러구나 하는 정보를 @ComponentScan 이 읽어들여서 Spring Container 가 관리하게 해줍니다.
-) @RequestMapping 이 컨트롤러 클래스를 작성할 때는 클래스 위 혹은 메서드에서 @RequestMapping 애노테이션을 맵핑을 위해서 사용하게 됩니다. 요청이 들어왔을 때 어떤 URL로 들어온 요청인지 파악해서 어떤 컨트롤러를 사용하여 어떤 처리를 해야하는지 알아내야하는데, @RequestMapping 애노테이션을 활용하여 이 메서드는 어떤 요청이 들어왔을 때 사용할 거야 라는 것을 알려주어야 합니다. 즉, @RequestMapping 애노테이션은 Http 요청과 이를 다루기 위한 Controller 의 메서드를 연결하는 애노테이션입니다. Http Method 와 연결하는 방법은 다음과 같습니다. : @RequestMapping("/users", method=RequestMethod.POST) 원래는 이렇게 사용을 했었는데요. Spring 4.3 부터는 @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping 과 같이 다양하게 사용할 수 있게 되었습니다.
한편, Http 특정 헤더와 연결하는 방법으로도 사용할 수 있는데요. : @RequestMapping(method = RequestMethod.GET, headers="content-type=application/json") 메서드를 지정하고, headers 부분을 지정하고 있는 것을 볼 수 있습니다.
또한 Http Parameter 와 연결하는 방법도 있는데요. : @RequestMapping(method=RequestMethod.GET, params="type=raw")
Content-Type Header 와 연결하는 방법도 있습니다. : @RequestMapping(method=RequestMethod.GET, consumes="application/json")
Accept Header 와 연결하는 방법도 있습니다. : @RequestMapping(method=RequestMethod.GET, produces="application/json")
이렇게 다양한 방법으로 @RequestMapping 을 작성하는 것을 Spring 이 제공해주고 있습니다. 이제 실제로 코드로 작성해보겠습니다.
Controller(Handler) 클래스 작성하기(2) : Dispatcher 컨트롤러 코드 작성하기
우선 config 관련 설정을 작성하기 위해 위와 같이 패키지를 추가해줍니다.
우선 강의와는 다르게 클래스가 extends WebMvcConfigurerAdapter 하지 않고 implements WebMvcConfigurer 하고 있는 것을 확인할 수 있는데, 스프링 부트 2.0 부터 java8과 스프링 5.0을 사용하면서 WebMvcConfigurer 메서드에 default를 선언했다. 쓰임새가 사라진 WebMvcConfigurerAdapter 는 제외되었습니다. 그 다음 패키지 안에 WebMVCContextConfiguration 라는 자바 클래스 파일을 하나 추가해줍니다. @Configuration 애노테이션은 이 자바 파일이 설정 파일임을 알려주고요. @EnableWebMvc 애노테이션은 기본적인 설정들을 자동으로 해주고요. @ComponentScan 애노테이션은 'controller' 라는 애노테이션이 붙은 것들을 읽어와서 사용할 수 있도록 해줍니다. 여기서 basePackages 를 사용하면 중괄호를 사용하여 여러개를 지정할 수 있습니다. @ComponentScan 을 사용할 때는 패키지 경로를 지정을 해주어야 하는데요. 그렇지 않으면 어느 경로부터 읽어야 할지 모르기 때문에 수행이 안될 수도 있습니다.
그 다음 addResourceHandlers 라는 메서드를 오버라이드 한 것을 볼 수 있는데요. 이전에 DispatcherServlet 에 대한 설정을 web.xml 에서 해주었을 때 <url-pattern> 에서 '/' 로 설정하여 모든 요청에 대해 DispatcherServlet 이 동작하도록 설정하였었는데요. 이 요청이 단순 GET 같은 요청 뿐만 아니라 CSS, HTML 등 다양한 요청을 하게 됩니다. 요청이 들어올 때 url 요청이 시작하는 것을 기준으로 구분하여 각각 찾아가야 하는 경로를 설정하는 코드가 addResourceHandlers 메서드라고 이해할 수 있습니다. 한편, 초창기에는 URL pattern 부분에 / 가 아니라 ~.do 혹은 ~.x 방식으로 한 요청에 해당하는 설정을 다 일일이 해주었습니다.
그 다음 configureDefaultServletHandling( ) 메서드를 오버라이드 하고 있는 것을 볼 수 있는데요. 이 메서드는 DefaultServletHandlerConfigurer 객체를 인자로 받아서 enable( ) 메서드를 사용합니다. DefaultServletHandling을 사용하도록 만드는 역할을 수행합니다. 맵핑 정보가 없는 URL 요청은 DefaultSevletHandler 가 처리하도록 해줍니다. Spring 의 DefaultServletHandler 는 WAS의 DefaultServletHandler 에게 해당 일을 넘기게 되는데요. WAS 는 DefaultServlet 의 Static 자원을 읽어서 보여주게 해줍니다.
그 다음 addViewController( ) 메서드를 오버라이드하고 있는 것을 볼 수 있는데요. addViewController 메서드는 특정 URL 에 대한 처리를 컨트롤러 클래스를 작성하지 않고 맵핑할 수 있도록 해주는데요. 요청 자체가 / 하고 들어오면 main 이라고 하는 뷰로 보여주도록 하는 거죠.
이 view main 은 ViewResolver 객체를 이용해서 찾게 되는데요. 실제 main 이라는 이름만 가지고는 View 정보를 찾아낼 수는 없구요. View 정보는 getInternalResourceViewResolver 라는 메서드에서 설정된 형태로 View 를 사용하게 됩니다. 위 코드 내부를 보면 InternalResourceViewResolver 객체를 생성한 다음 resolver 의 Prefix 와 Suffix 를 지정하는 것을 볼 수 있는데요. 바로 위 addViewController 에서 사용된 name 인 main 앞에 Prefix 에서 설정한 주소를 붙여주고 뒤에 Suffix 에서 지정한 주소를 붙여주게 됩니다. 이 뷰 정보는 결국 /WEB-INF/views/main.jsp 가 되게 됩니다.
DispatcherServlet 을 FrontController 로 설정하는 web.xml 이해하기
이런 DispatcherServlet 이 실제로 동작하게 하기 위해서 이 DispatcherServlet 을 Front Controller 로 등록해야 한다고 이야기했었는데요. 이 설정하는 부분을 web.xml 에 추가를 해야지만 Spring 이 제공하는 DispatcherServlet 이 Front Controller 역할을 수행할 수 있게 됩니다. 위 설정 파일을 이해해보겠습니다.
-) url pattern '/' : URL 의 모든 요청에 대해서 servlet name = mvc 가 실행되어라는 설정입니다.
-) servlet-name 'mvc', DispatcherServlet, WebMvcContextConfiguration, contextClass(빈공장) : 위에서 설정한 mvc 가 실행되기 때문에 <servlet> 태그 안의 servlet-name = mvc 로 설정된 이름을 찾아갑니다. 이 mvc 라는 것에는 springframework 가 제공하고 있는 DispatcherServlet 이 들어있는 것을 확인할 수 있습니다. 따라서 모든 URL 에 대한 요청이 DispatcherServlet 으로 흘러 들어가게 되구요. DispatcherServlet 이 실행이 될 때 DispatcherServlet 의 설정들을 읽어내게 되는데, 우리가 작성한 WebMvcContextConfiguration 클래스 파일에서 읽어오게 됩니다. 이렇게 읽어오도록 설정하는 부분이 <init-param> 에서 contextConfigLocation 은 ~WebMvcContextConfiguration 이다고 알려주고 있습니다. 또한 contextClass 에 대한 init-param 도 있는 것을 볼 수 있는데요. IoC 빈 공장들이 필요하다고 우리가 전에 배웠었는데요. AnnotatinoConfigWebApplicationContext 라는 빈 공장을 사용을 할 것이라고 등록 하고 있는 것을 확인할 수 있습니다.
이렇게 설정을 해주어야 DispatcherServlet 이 FrontController 역할을 수행하게 됩니다.
설정 정상 여부 테스트 (main.jsp)
여기까지 진행을 했으면 잘 설정이 되었는지 테스트를 한번 해보겠습니다.
우리가 WebMvcContextConfiguration 이라는 DispatcherServlet 의 설정파일에 위와 같이 설정을 하였는데요. / 라는 주소로 들어오면 /WEB-INF/view/main.jsp 가 보여지도록 설정하였습니다. 즉 해당 위치에 main.jsp 라는 파일을 만들어주면 테스트를 진행할 수 있습니다. (만약 STS에서 jsp 파일 만드는 버튼이 보이지 않는다면 marketplace 에서 web developer tools 를 설치합니다.)
우선 지정된 위치에 views 폴더를 만들고 그 아래에 main.jsp 를 생성하였습니다.
main.jsp 는 테스트 파일이므로 별다른 것은 작성하지 않고 h1 태그 하나만 작성하였습니다.
서버를 구동시키면 위와 같은 화면이 보이게 되는데요. 우리가 작성한 main.jsp 가 아니라 엉뚱한 화면이 보이게 됩니다.
index.jsp 라는 파일이 기본적으로 생성이 되는데요. 이 파일 때문에 기본적으로 이런 일이 발생합니다. Web application 자체가 아주 기본적인 설정으로 주소가 없었을 때 index 로 시작하는 파일을 찾도록 되어있습니다. 그 설정 때문에 이 파일이 우선 열린 것입니다. 이 index.jsp 위치를 옮기거나 이름을 바꾸면 이 파일을 찾지는 않게 됩니다. 이 파일을 없애주겠습니다.
강의에서는 여기까지만 하면 실행이 정상적으로 되었는데, 저는 버전이 달라서 Get Mapping 이 안되었습니다. 그래서 위처럼 @GetMapping 어노테이션을 통해서 GetMapping 을 시켜주었고