Java Spring - MVC

김재현·2022년 8월 2일
0

Programmers

목록 보기
11/28

Front Controller Pattern

  • 서블릿은 클라이언트로부터 요청을 받아 실제로 비즈니스 로직이나 서비스를 처리하거나 받은 내용을 갖고 JSP에 모델을 생성하거나, 또는 다운로드나 파일을 반환하거나.. 해야하는 일이 많음.
    매번 서블릿을 생성하지 않고 통합적으로 해주거나, 템플릿화 해놓고 변경이 필요한 부분에만 변경을 해주는 방법을 모색하게 된다. 로직 변경이 필요한 곳을 변경해주거나 서비스 호출과 처리 하는 것을 분리한다.
  • 중앙 집중형 컨트롤러를 가장 앞에서 배치. 서블릿은 하나만 생성된다.
    요청을 먼저 받아 등록되어 있는 다른 컨트롤러를 호출할지 말지 결정한다. 필요하다 판단되면 다른 컨트롤러를 호출하여 요청 처리를 위임한다.
    응답 받은 것으로 view를 만드는 것도 한다.
  • 프론트 컨트롤러를 사용하면 각 컨트롤러에서 발생한 예외도 처리하고, 컨트롤러의 응답에 대한 view를 생성해서 클라이언트에게 전달하는 작업도 수행한다.
    공통 코드에 대해서는 Front Controller에서 처리하고, 서로 다른 코드들만 각 Controller에서 처리할 수 있도록 한다.
  • 장점
    • 공통 코드 처리가 가능하다.
    • Front Controller 외 다른 Controller에서 Servlet 사용하지 않아도 된다.

DispatherServlet

  • 프론트 컨트롤러. 서블릿.
  • 서블릿을 작성하는 것이 아닌, 컨트롤러를 작성하고 스프링이 작성된 컨트롤러를 호출하게 됨.
  • 서블릿은 디스패쳐 서블릿이 알아서 처리해줌.

MVC 처리 흐름

  1. HTTP요청을 받음.
  2. 디스패쳐 서블릿에서 요청에 맞는 컨트롤러를 탐색하고 컨트롤러에게 요청을 위임.
  3. 호출된 컨트롤러는 모델을 만들거나, 서비스를 호출함. 서비스는 실제 엔터티를 만들고 그것을 가지고 비즈니스 로직을 처리하며 컨트롤러에 결과가 리턴됨.
  4. 컨트롤러는 그것을 가지고 화면에 전달할 모델을 생성. 그 모델을 갖고 view에 전달함. 컨트롤러는 모델과 뷰를 생성하고 그것을 디스패쳐 서블릿에 리턴.
  5. 디스패쳐서블릿은 모델과 뷰를 갖고 적당한 응답, 적당한 컨텐츠를 만듦. JSP, xml, JSON 등 다양한 뷰가 만들어질 수 있음.
  6. 이것을 HTTP 응답으로 바디에 담아서 전달해줌.

요약

요청이 오면, 컨트롤러가 선택되고 컨트롤러에서 메서드가 호출. 메서드는 모델과 뷰를 생성하고 모델과 뷰를 리턴. 디스패쳐 서블릿은 뷰에다 모델을 전달하며, view가 컨텐츠를 만들어줌. 랜더링된 결과물이 만들어지고, 그것을 HTTP응답으로 전달.

만드는 법

  • 서블릿 등록할 때 web.xml과 web application Initializers 사용도 가능.
  • 어플리케이션 컨텍스트를 만들어서 등록할 수 있음.
  • 디스패쳐 서블릿을 만들어 서블릿에 등록할 수 있음.

Handler Mapping

  • 스프링에서는 컨트롤러를 Handler라고 부름.
    요청을 다루는(Handle)하는 오브젝트라는 의미.
  • 디스패쳐 서블릿은 주로 요청의 URL기준으로 어떤 컨트롤러에게 작업을 위임할지 결정함. (+ 파라미터 정보, HTTP 메서드 등 참고)
    URL정보와 같은 사용자 요청과 해당 요청을 어떤 핸들러로 처리할 지 연결해주는 것을 'Handler Mapping'이라고 함.
  • 가장 많이 쓰이는 것은 RequestMappingHandlerMapping
  • 컨트롤러 에노테이션 작성 후 RequestMapping이라는 에노테이션을 사용함.
    이것에 의해서 URL은 어떤 리퀘스트 매핑 메서드에 호출되야하는지 결정이 되게 됨.

Handler Adapter

  • 핸들러 매핑에 의해서 어떤 컨트롤러가 처리할지 결정됐다면, 핸들러가 호출될 때 핸들러가 갖고 있는 메서드 파라미터들을 매서드 파라미터에 맞는 정보로 변경해주는 것이 Handler Adapter.
    컨트롤러가 특정 인터페이스를 구현해야한다면, 스프링의 유연성을 위해 시그니처를 제약하지 않음.
  • 디스패쳐 서블릿이 핸들러의 특정 메서드를 호출하기 위해 컨트롤러와 서블릿 사이에 어답터를 삽입.
  • 서블릿을 마주보는 것은 핸들러라는 특정 메서드. 핸들러를 사용하면 어답터가 컨트롤러에 있는 타입에 맞춰 변환해서 호출해준다.
    스프링에서는 핸들러어답터를 통해 다양한 종류의 컨트롤러 타입을 지원해줌.
  • 디스패쳐 서블릿은 모든 웹 요청의 정보가 담긴 HTTP서블릿 리퀘스트 타입의 오브젝트를 핸들러 어답터에 전달해주면 어답터가 적절하게 변환을 해서 컨트롤러의 메서드를 받을 수 있는 파라미터로 변환해서 전달해주게 됨. 어떠한 어답터를 쓸지는 핸들러 어답터 전략에 따라 결정됨.
  • 어답터와 맵핑이 공존하게 됨.

ViewResolver

  1. Get 요청을 보냄.
  2. view 이름과 data반환. view model 반환.
    디스패쳐 서블릿 내부적으로 viewresolver라는 것이 등록되어 있음.
    컨트롤러가 view name을 반환하면
  3. viewresolver가 여러 개의 체인처럼 연결되어 등록되어 있음.
    첫번째 뷰리절버에서 이름에 해당하는 뷰가 찾아지면 그 뷰를 리턴함.
    첫번째가 아니라면 두번째, 세번째.. 마지막까지 찾아서 해당 뷰를 반환하게 됨.
  4. 반환된 뷰를 사용해 랜더링해서 나온 결과를 디스패쳐 서블릿이 응답에 실어 클라이언트에 전달하게 됨.
  • 디스패처 서블릿은 뷰리절버를 통해 원하는 뷰를 찾음.

  • 기본적으로는 InternalResourceViewResolver가 사용됨.
    뷰 리절버 중 가장 하위. 가장 마지막에 검색된다.

정리

  1. 요청이 오면 DispatcherServlet이 받음.
  2. HandlerMapping 전략에 의해 Controller가 선택됨.
  3. 디스패쳐 서블릿이 HandlerAdapter을 가지고 HTTP Servlet Request를 컨트롤러의 특정한 메서드에 맞는 파라미터로 변환을 해줌.
  4. 매서드가 호출되고 Controller가 BusinessLogic을 실행시킴.
    Service에서 반환된 것을 가지고 View에 전달할 Model을 만들어줌.
  5. view name과 모델이 만들어짐.
    뷰 네임이 만들어지고 어답터에 전달되면
  6. 디스패쳐 서블릿이 ViewResolver에 view name과 Model을 전달함.
    뷰 리절버는 특정한 뷰를 찾고(resolve View) 만들어짐.
  7. 각 뷰에 해당하는 것을 랜더링해서 출력하게됨. (JSONview > JSON메세지 포맷, JSP view > HTML ...)
  • Controller, Service, Repository를 만들고 나머지는 웬만하면 spring이 구축해준다.

실습

  • jstl
    JSP에서 사용할 수 있는 태그 제공. 태그를 이용해서 코드를 깔끔하게 만들어 줌.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
  • JSP별로 안 씀.. 타임리프 많이 사용한다.
    백엔드는 APR서버 위주로 만들지, View 랜더링 많이 안함.
    뷰 처리를 자바스크립트 어플리케이션 레이어로 전달해버림.
    백엔드는 뷰를 만들기보다는 정보의 덩어리인 JSON 같은 API가 리턴되게 함.
  • dispatcherServlet은 webApplicationContext가 필요
    dispatcherServlet의 업무가 굉장히 많음.
  • Controller에는 @controller을 붙여아 됨.
    ModelAndView 리턴해주기.
    메서드를 찾아주기 위해서 @RequestMapping을 사용할 수 있음.
  • BootStrap 사이트를 이용해서 괜찮은 템플릿을 사용할 수 있음.
    JSTL

Static Resource 처리하기

  • 정적 리소스(이미지 등)를 처리하기 위해서 스프링에서는 Resource Handler 제공.
    리소스 핸들러를 셋업하면 정적인 컨텐츠를 호스팅할수 있음.
  • 서블릿 컨테이너의 web.xml에 가면 default servlet이 셋업되어 있음.
    리소스 핸들러는 디폴트서블릿에 요청을 위임해서 디폴트 서블릿을 통해 리소스를 서빙하게 됨.
  • EncodedResourceResolver를 사용하면 알아서 인코딩 해준다. (압축 등)

Thymeleaf

  • 자바 템플릿 엔진.
    HTML로 작성. 템플릿 엔진이기 때문에, 응답으로 보내질 컨텐츠를 만들게 됨. 컴파일하지 않고 패싱하게 됨.
  • 성능 상으로 조금 느릴 수 있지만, 가독성이 좋고 표현식이 막강함.
    API는 JSON만 리턴하고 뷰를 랜더링 처리하지 않는 추세임.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
  • pom.xml에 추가
    새로운 viewResolver, ThymeleafViewResolver추가.
    ThymeleafViewResolver는 템플릿 엔진을 추가해주어야 하기 때문에 ThymeleafViewResolver.setTemplateEngine();이 됨.

Expression

  • 변수 식 : ${OGNL}
    OGNL(Object-Graph Navigation Language) 표현식은 객체의 속성에 값을 가져오고 설정하는데 사용됨.
<p>Today is: <span th:text="${today}">13 february 2011</span>.</p>
==> ctx.getVariable("today");
  • 객체 자체가 context가 돼서 object가 되고, 필드들이 접근할 수 있음.
    th:를 붙여서 Thymeleaf가 이해하는 태그로 변경해 줘야함.
    th:each 반복이 되는 태그에 들어감.
  • 메시지 식 : #{코드}
    스프링 메세지소스와 연동해서 메세지 코드를 넣으면 메세지가 출력됨. 다국어 처리에 용이.
  • 링크 식 : @{링크}
  • 선택변수 식 : *{OGNL}
    th:object로 선택한 객체에 한해서 필드에 접근하게 됨.

0개의 댓글