오늘 진행한 학습 요약
1. 기초 Spring 3주차
- Template Engine
- MVC 패턴
- Servlet
- Spring MVC
김영한 - 스프링 입문 강의 소개 링크 : https://youtu.be/qyGjLVQ0Hog?si=bAfflwZ3PDThiTdL
2. 알고리즘 코드카다 Day17 (작성 생략)
CodingTest Git-hub 링크 : https://github.com/chews26/CodingTest
학습 정리
1. 기초 Spring 3주차
- Template Engine
- 동적인 웹 페이지를 생성하기 위해 사용되는 도구
- 템플릿을 기반으로 정적인 부분과 동적인 데이터를 결합하여 HTML, XML 등의 문서를 생성하는 역할을 수행
- 우리가 흔히 말하는 UI(User Interface)를 만듬
- SSR(Server Side Rendering)에 사용
- 등장 이유
- HTML 문서에 동적으로 변경해야 하는 부분만 자바 코드를 넣을 수 있다면 더 편리
- 대표적인 템플릿 엔진
- Thymeleaf
- JSP(Java Server Pages)
- FreeMarker
- Velocity
- Mustache
- Servlet
- 화면을 그리는 View 영역과 비지니스 로직이 Servlet 하나에 모두 섞여있음
- 책임을 너무 많이 가지고 있음
- JSP
- servlet 코드에서 HTML을 만드는 부분인 View가 분리
- Servlet, JSP 방식의 문제점
- Servlet만을 사용한 경우 View를 위한 코드와 비지니스 로직을 처리하는 코드가 Servlet에 모두 존재하여 유지보수가 어려워 짐
- JSP를 사용하여 View를 분리하였지만 비지니스 로직의 일부가 JSP 파일안에 존재
- 전히 책임이 많음
- MVC패턴 등장 배경
- Servlet이나 JSP만으로 비지니스 로직과 View Rendering 까지 모두 처리하면 너무 많은 역할을 하므로 고안된 패턴
- Web Application은 일반적으로 MVC(Model View Controller) 패턴을 사용
- MVC 패턴
- 하나의 Servlet이나 JSP로 처리하던 것들을 Model, View, Controller 영역으로 나눈것
- 핵심은 변경
- 기획이 변하지 않는 이상 비지니스 로직과 View의 수정 원인은 별개로 발생
- 화면 구성에 수정이 발생하면 View만 변경
- 요구사항에 수정이 발생하는 경우 비지니스 로직 변경
- 완전히 분리
- Controller
- HTTP Request를 전달받아 파라미터를 검증
- 예시 코드에서 Servlet에 해당하는 영역
- 비지니스 로직을 실행
- Service Layer를 별도로 만들어서 처리
- Database와 상호작용 하는 Layer를 따로 구분
- Repository Layer를 추가로 구성
- 일반적으로 Service Layer를 호출하는 역할을 담당
- Model
- View에 출력할 Data를 저장하는 객체
- View Rendering에만 집중
- View
- JSP에 해당하는 영역
- Model 객체에 담겨져 있는 Data를 사용하여 화면을 Rendering
- MVC 패턴의 문제점
- dispatcher.forward(request, response) View로 이동하는 forward가 항상 중복 호출
- String path= “/WEB-INF/views/new-form.jsp” View의 path를 입력(중복 작업)
- jsp 파일의 경로 혹은 이름이 바뀌면 해당 코드가 변경
- JSP 이외의 확장자를 사용하려면 전체가 변경
- HttpServletResponse 객체를 사용하는 경우가 적음
- HttpServletRequest와 HttpServletResponse는 Test 코드를 작성하기도 매우 힘듬
- 공통 기능이 추가될수록 Controller에서 처리해야 하는 부분들이 많아짐
- 공통 기능 처리?
- 모든 컨트롤러에서 공통으로 적용되는 기능
- Log 출력, 인증, 인가 등
- 프론트 컨트롤러 패턴
- Servlet(Controller)이 호출되기 전에 공통 기능을 하나의 Servlet에서 처리해주는 패턴
- 프론트 컨트롤러(Servlet) 하나에 모든 클라이언트측 요청이 들어옴
- 입구가 오직 하나, 프론트 컨트롤러(Servlet)에서 공통 기능을 처리
- 프론트 컨트롤러의 역할
- 모든 요청을 하나의 프론트 컨트롤러가 받음
- 공통 기능을 처리
- 요청을 처리할 수 있는 Controller를 찾아서 호출
- 프론트 컨트롤러를 제외한 나머지 컨트롤러는 Servlet을 사용하지 않아도 됨
- 일반 Controller들은 HttpServlet을 상속받거나, @WebServlet을 사용하지 않아도 됨
- 공통 처리 로직에 모든 컨트롤러가 연결되기 위해서는 모든 컨트롤러가 return 하는 결과의 형태가 동일해야 함
- 응답을 동일하게 맞추려고 한다면 해당 애플리케이션은 확장성, 유지보수성을 잃음
- 어댑터 패턴
- 다양한 컨트롤러(Handler)를 유연하게 만들기위해 어댑터 패턴을 도입
- 컨트롤러들은 동일한 인터페이스를 구현, 해당 인터페이스와 공통 로직 사이에 어댑터를 두어 유연
- 서로 다른 인터페이스를 갖는 두 클래스를 연결해주는 패턴
- 프론트 컨트롤러, 어댑터, 핸들러 모두 각자의 역할만 수행한다. (책임 분리)
- 새로운 컨트롤러(Handler)가 추가되어도 컨트롤러와 어댑터만 추가한다면 공통 로직의 변경이 발생하지 않음
- Spring MVC
-
- DispatcherServlet : Spring의 프론트 컨트롤러
- 클라이언트 HTTP Request를 알맞게 파싱하고 클라이언트에게 알맞은 응답을 반환
- 핸들러 목록 정보를 알고 있음
- 핸들러 어댑터 목록 정보를 알고 있음
- HandlerAdapter :
- 자신이 처리할 수 있는 Handler인지 확인할 수 있는 기능(Method)이 필요
- 프론트 컨트롤러에서 요청을 위임받았을 때 핸들러에게 요청을 지시하는 기능이 필요
- return 시 Handler로부터 전달받은 결과를 알맞은 응답으로 변환
- Handler :
- 요청에 대한 로직을 수행하는 기능이 필요
- View : 인터페이스로 구성되어 있다, 확장성을 가지고 있다.
- DispatcherServlet : Spring의 프론트 컨트롤러
- 실행 순서
- 1. Client로 부터 HTTP 요청(Request)받음
- 2. Handler 조회
- 3. Handler를 처리할 Adapter 조회
- 4. Handler Adapter 실행(handle)
- 5. Handler 실행(호출)
- 6. Model And View 반환(return)
- 7. viewResolver 호출(알맞은 View 요청)
- 8. View 반환
- 9. View Rendering
-
- Dispatcher Servlet
- Spring MVC의 프론트 컨트롤러는 Dispatcher Servlet(Servlet의 한 종류)
- Spring MVC의 핵심 기능
- Spring Boot는 Dispatcher Servlet을 서블릿으로 자동으로 등록, 모든 URL 경로에 대해서 Mapping
- 개발자가 만들 Servlet이 항상 우선순위가 높아서 실행
- Spring MVC의 주요 Interface
- 인터페이스를 implements 하여 구현하면 내가 만든 클래스를 사용할 수 있다. (다형성)
- org.springframework.web.servlet
- HandlerMapping
- HandlerAdapter
- ViewResolver
- View
- Controller Interface
- Controller Interface를 implements 하여 구현하게되면 개발자가 원하는 Controller(Handler)를 사용할 수 있음
- @Component
- Spring Bean에 등록하는 역할을 수행
- Spring Bean은 애플리케이션의 구성 요소를 정의하는 객체
- 마치 Servlet이 Servlet Container에 등록되는 것과 같음
- Controller는 어떻게 호출?
- Handler Mapping, Handler Adapter가 해당 컨트롤러(핸들러)가 호출되도록 만들어줌
- Handler Mapping
- 핸들러 매핑에서 ExampleController를 찾을 수 있어야 한다.
- Spring Bean의 이름으로 핸들러를 찾을 수 있는 핸들러 매핑이 필요
- RequestMappingHandlerMapping
- 우선순위가 가장 높다
- Annotation 기반 Controller의 @RequestMapping에 사용
- BeanNameUrlHandlerMapping
- Spring Bean Name으로 HandlerMapping
- Handler Adapter
- Handler Mapping을 통해 찾은 핸들러를 실행할 수 있는 Handler Adapter가 필요
- Controller Interface를 실행할 수 있는 Handler Adapter를 찾고 실행
- RequestMappingHandlerAdapter
- Annotation 기반 Controller의 @RequestMapping에서 사용
- HttpRequestHandlerAdapter
- HttpRequestHandler 처리
- SimpleControllerHandlerAdapter
- Controller Interface 처리
- View Resolver
- 반환된 ModelAndView 객체를 알맞은 View로 전달하기 위해 DispatcherServlet에서 ViewResolver를 호출하여 View 정보를 설정하는 역할을 수행
- application.properties 설정
- 설정을 기반으로 Spring Boot가 InternalResourceViewResolver 를 만듬
- Spring Boot의 ViewResolver
- BeanNameViewResolver
- Bean Name으로 View를 찾아 반환
- InternalResourceViewResolver
- application.properties 설정 파일에 등록한 prefix, suffix 설정 정보를 사용하여 ViewResolver 등록
- BeanNameViewResolver
- InternalResourceViewResolver - Spring MVC 동작 순서
- 1. HandlerAdapter 호출
- 2. ViewResolver 호출
- 3. InternalResourceViewResolver
- 4. InternalResourceView
- 5. view.render()
- Thymeleaf
- Thymeleaf는 View와 Resolver가 이미 존재한다. 라이브러리 의존성만 추가해주면 SpringBoot가 모두 자동으로 해준다. 즉, return “viewName”; 만으로 View가 Rendering 된다.
- 노션에 Spring 관련 개념 정리
- Spring 관련해서 더 공부를 해야할 것 같다. 아직 많이 헷갈린다 ㅠㅠ