본문 바로가기
WIL

10/02 WIL

by 달리는 꿈나무 2022. 10. 2.

1.  스프링 웹 MVC 관련 지식 공부 

저번 주 부득이한 일정에 의해 WIL을 작성하는 것을 놓쳤다. 이번 주는 mvc 지식을 마저 정리하려 한다.

 

서블릿 - Servlet

서블릿이란 자바를 사용하여 웹을 만들기 위해 필요한 기술로서 클라이언트에서 오는 request, 클라이언트로 보내주는response 전송과 같은 역할을 하는 자바 프로그램

 

서블릿 특징

  • 클라이언트의 요청애 대해 동적으로 작동하는 웹 어플리케이션 컴포넌트
  • html을 사용하여 요청에 응답한다.
  • 자바 스레드를 이용하여 동작한다. 스레드 풀에서 스레드를 할당받는다.
  • MVC 패턴에서 컨트롤러로 이용된다. 디스패터 서블릿의 경우 프론트 컨트롤러로 작용한다.
  • HTTP 프로토콜 서비를 지원하는 HttpServlet 클래스를 상속받는다.
  • UDP 보다 처리 속도가 느리다.
  • HTML 변경 시 Servlet을 재컴파일 해야한다.

 

서블릿 컨테이너

 서블릿을 관리하는 컨테이너로서 스프링 컨테이너에서 빈을 관리하는 것과 같은 역할을 한다. 클라이언트 request를 받아주고 response를 보내고, 웹소켓과 톰켓으로 통신한다. WAS이 역할을 하는데 대표적으로 스프링의 톰캣이다. 싱글톤으로 관리한다.

 

 

서블릿 컨테이너의 역할

1. 웹서버와의 통신 지원

 서블릿과 웹서버가 손쉽게 통신하도록 관리해준다.

 

2. 서블릿 생명주기 관리

 서블릿을 로딩하고 이에 관한 메서드를 호출시키며, 통신이 끝날 때 서블릿을 갈비지 컬렉션을 진행한다. 

 

3. 멀티 스레드 지원 및 관리

 request가 올 때 마다 스레드풀에서 스레드를 요청하여 사용하고 HTTP 메소드를 실행시키고 나면 이를 다시 반납한다. 개발자는 스레드 관리에 집중을 안 해도 된다.

 

4. 선언적 보안 관리

서블릿 컨테이너를 사용하면 개발자는 보안에 관련된 내용을 서블릿 또는 자바 클래스에 구현해 놓지 않아도 된다. 이로 인해 보안 수정을 할 일이 있더라고도 컴파일 하지 않아도 보안 관리가 가능하다.

 

스프링부트 -> 내장 톰캣 서버 -> 서블릿 컨테이너 내에 서블릿 생성

 

request -> 서블릿 컨테이너 -> 서블릿 실행 -> 종료 후 response

 

 

 

HTTP 요청 데이터

  • GET - 쿼리 파라미터
    • /url?username=hello&age=20
    • 메세지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달
    • 예) 검색, 필터, 페이징 등에서 많이 사용하는 방식
  • POST - HTML Form
    • content-type:application/x-www-form/Urlencoded
    • 메세지 바디에 쿼리 파라미터 형식으로 전달 username=hello&age=20
    • 예) 회원가입, 상품 주문, HTML Form 사용
  • HTTP message body에 데이터를 직접 담아서 요청
    • HTTP API에서 주로 사용, JSON, XML, TEXT
  • 데이터 형식은 주로 JSON 사용
    • POST, PUT, PATCH

참고:

 

GET URL 쿼리 파라미터 형식은 HTTP 메세지 바디를 사용하지 않기 때문에 content-type이 없다.

         

POST HTML Form 형식으로 데이터를 전달하면 HTTP 메세지 바디에 해당 데이터를 포함해서 보내기 때문에 바디에 포함된 데이터가 어떤 형식인지 content-type을 지정해주어야한다. 

 

 

 

템플릿 엔진

 레거시 코드들은 컨트롤러에 서블릿 로직과 비즈니스 로직, String으로 HTML 까지 만들었다. 이런 건 매우 복잡하고 비효율 적이다. 그냥 하나에 다 때려 박은 것이다. 차라리 HTML 문서에 동적으로 변경해야하는 부분만 자바 코드를 넣을 수 있으면 좋지 않겠는가. 이래서 템플릿 엔진이 나왔다. 템플릿 엔진은 JSP. Thymeleaf, Freemarker, Velocity 등이 있다.

 

 

서블릿과 JSP의 한계

 JSP를 사용한 덕에 뷰를 생성하는 HTML 작업을 깔끔하게 가져가고, 중간 중간 동적으로 변경이 필요한 부분만 자바 코드를 적용했다.

 하지만 JSP는 다양한 비즈니스 로직 자바 코드가 모두 JSP에 노출되어 있다. JSP가 너무 많은 역할을 하고 있는 것이다.

 

 

MVC패턴의 필요성

너무 많은 역할

 하나의 서블릿이나 JSP만으로 비즈니스 로직과 뷰 랜더링까지 모두 처리하게 되면, 너무 많은 역할을 하게 되고, 결과적으로 유지 보수가 어려워진다. 

 

변경의 라이프 사이클

 비즈니스 로직 서블릿 코드와 HTML 사이의 변경의 라이프 사이클이 다르다. 변경의 라이프 사이클이 다른 부분을 하나의 코드로 관리하는 것을 유지보수 하기 좋지 않다.

 

기능 특화

 JSP와 같은 뷰 템플릿은 화면을 렌더링 하는데 최적화 되어 있어 이 부분의 업무만 담당하는게 효과적이다.

 

 

MVC패턴

모델, 뷰 컨트롤러

 

컨트롤러: HTTP 요청을 받아서 파라미터를 검증하고, 비즈니스 로직을 실행한다. 그리고 뷰에 전달할 결과 데이터를 조회해서 모델에 담는다.

 

모델: 뷰에 출력할 데이터를 담아둔다. 뷰가 필요한 데이터를 모두 모델에 담아서 전달해주기 때문에 뷰와 컨트롤러가 분리된다.

 

뷰: 모델에 담겨있는 데이터를 동적으로 화면에 그린다.

 

 

MVC패턴의 한계

컨트롤러들이 딱 봐도 중복이 많고 필요하지 않는 코드들이 많다.

 

MVC 컨트롤러의 단점

  • 포워드 중복: 뷰로 이동하는 코드가 중복된다.
  • 뷰 패스 중복: 뷰의 위치가 같은 파일인 경우 중복된다.
  • 사용하지 않는 코드
  • -> 공통 처리가 어렵다. 
  • 컨트롤러들의 중복된 코드들 -> 프론트 컨트롤러를 만들자!

 

 

프론트 컨트롤러 패턴

  • 프론트 컨트롤러 서블릿 하나로 클라이언트의 request를 받는다.
  • 프론트 컨트롤러가 요청에 맞는 컨트롤러를 찾아서 호출
  • 입구를 하나로
  • 공통 처리 가능
  • 프론트 컨트롤러를 제외한 나머지 컨트롤러는 서블릿을 사용하지 않아도 된다.

 

스프링 웹 MVC와 프론트 컨트롤러

스프링 웹 MVC의 핵심도 바로 프론트 컨트롤러

스프링 웹 MVC의 디스패처 서블릿이 프론트 컨트롤러의 패턴으로 되어있다.

 

 

스프링 웹 MVC 구조

스프링 MVC 구조, 출처: 김영한의 스프링 MVC 1편

 

디스패처 서블릿

  • 부모 클래스에서 HttpServlet을 상속 받아서 사용하고, 서블릿으로 동작한다.
    • DispacherServlet -> FrameworkServlet -> HttpServletBean -> HttpServlet
  • 스프링 부트는 디스패처 서블릿을 서블릿으로 자동으로 등록하면서 모든 경로(urlPatterns="/")에 대해서 매핑한다.
    • 참고: 더 자세한 경로가 우선 순위가 높다. 그래서 기존에 등록한 서블릿도 함께 동작한다.

요청 흐름

서블릿 호출 -> HttpServlet.service() 호출 -> FrameworkServlet의 service()를 오버라이드하여 호출 -> DispacherServlet.doDispatch() 호출

 

 

스프링 MVC  동작 순서

1. 핸들러 조회: 핸들러 매핑을 통해 요청 URL에 매핑된 핸들러(컨트롤러)를 조회

2. 핸들러 어댑터 조회: 핸들러를 실행할 수 있는 핸들러 어댑터 조회

3. 핸들러 어댑터 실행: 핸들러 어댑터를 실행한다.

4. 핸들러 실행: 핸들러 어댑터가 실제 핸들러를 실행한다.

5. ModelAndView 반환: 핸들러 어댑터는 핸들러가 반환하는 정보를 ModelAndView로 변환해서 반환한다.

6. viewResolver 호출: 뷰 리졸버를 찾고 실행한다.

  • JSP의 경우: 인터널 리소스 뷰 리졸버가 자동 등록되고, 사용된다.

7. View 반환: 뷰 리졸버는 뷰의 논리 이름을 물리 이름으로 바꾸고, 렌더링 역할을 담당하는 뷰 객체를 반환한다.

  • JSP의 경우: 인터널 리소스 뷰를 반환하는데, 내부에 forward()로직이 있다.

8. 뷰 렌더링: 뷰를 통해서 뷰를 렌더링한다.

 

 

인터페이스 살펴보기 

  • 스프링 MVC의 큰 강점은 디스패처 서블릿 코드의 변경 없이, 원하는 기능을 변경하거나 확장할 수 있다는 점이다. 대부분의 기능을 확장 가능하도록 인터페이스를 제공해준다.
  • 이 인터페이스들만 구현해서 디스패처 서블릿에 등록하면 나만의 컨트롤러를 만들 수 있다.

 

정리

 스프링 MVC는 전세계 수많은 개발자들의 요구사항에 맞추어 기능을 확장해왔고, 그래서 웹 어플리케이션을 만들 때 필요로 하는 대부분의 기능이 이미 다 구현이 되어있다.

 

 

핸들러 매핑과 핸들러 어댑터

핸들러 매핑

  • 핸들러 매핑에서 특정 컨트롤러를 찾을 수 있어야한다.
  • 예) 스프링 빈의 이름으로 핸들러를 찾을 수 있는 핸들러 매핑이 필요하다.

핸들러 어댑터

  • 핸들러 매핑을 통해서 찾은 핸들러를 실행할 수 있는 핸들러 어댑터가 필요하다.
  • 예) 컨트롤러 인터페이스를 실행할 수 있는 핸들러 어댑터를 찾고 실행해야한다.

스프링은 이미 필요한 핸들러 매핑과 핸들러 어댑터를 대부분 구현해두었다.

 

1. 핸들러 매핑으로 핸들러 조회

 1. HandlerMapping을 순서대로 실행해서, 핸들러를 찾는다.

 2. 이 경우 빈 이름으로 핸들러를 찾아야 하기 때문에 이름 그대로 빈 이름으로 핸들러를 찾아주는 BeanNameUrlHandlerMapping가 실행에 성공하고 핸들러인  OldController를 반환한다.

 

2. 핸들러 어댑터 조회

 1. HandlerAdapter의 supports()를 순서대로 호출한다.

 2. SimpleControllerHandlerAdapter가 Controller인터페이스를 지원하므로 대상이 된다.

 

3. 핸들러 어댑터 실행

 1. 디스패처 서블릿이 조회한 SimpleControllerHandlerAdapter를 실행하면서 핸들러 정보도 함께 넘겨준다.

 2. SimpleControllerHandlerAdapter는 핸들러인 OldController를 내부에서 실행하고, 그 결과를 반환한다.

 

 

 

 

 

 

'WIL' 카테고리의 다른 글

10/16 WIL  (0) 2022.10.23
10/09 WIL  (0) 2022.10.09
9/18 WIL  (0) 2022.09.18
9/11 WIL  (0) 2022.09.11
09/04 WIL  (0) 2022.09.04