=> 관심사의 분리 (Seperation of Concerns)원칙에 입각하여 Spring MVC를 사용함
survlet의 문제점으로 인해 MVC를 사용하기로 했다

- Model - 데이터와 비즈니스 로직을 담당
Controller에서 View로 데이터를 전달할때 사용하는 객체.
키밸류 형태로 데이터를 저장한다
주로 Model, ModleAndView 클래스 사용- View - 사용자에게 보여지는 화면 담당
Model에 담긴 데이터를 사용해 HTML을 생성하고 클라이언트에게 읃ㅇ답.
Controller가 반환한 View이름을 ViewResolver가 실제 View 파일과 매핑시켜 렌더링- Controller - 사용자의 요청을 받아 Model과 View를 연결해준다
어떤 요청이 들어왓을때 어떤 메소드 실행할지 결정하고 비즈니스 로직을 호출하고 데이터를 Model에 담아 View 이름을 반환
=>@Controller 클래스가 이 혁할을 한다
위 처럼 역할 분담 => 코드가 깔끔해지고 유지보수, 테스트 용이
HTML을 동적으로 만들어줄 수 있는 자바 기반 도구 = 템플릿 엔진
자바코드가(스프링컨트롤러)가 보내주는 데이터를 HTML 코드와결합해 내용이 채워진 완성된 웹페이지를 만들는 것
SSR (Server Side Rendering) - 서버에서 렌더링했다
모든 데이터를 채워 완벽히 조립된 HTML 페이지를 브라우저(클라)에게 전달하는 방식
검색 엔진 최적화(SEO)에 유리함 => 데이터가 모두 채워져있으니까 봇이 이 사이트를 파악가능함
타임리프가 이 SSR 방식임
CSR
서버가 텅 빈 HtML 뼈대와 js파일만 보내주는 방식임
그러면 클라이언트 브라우저가 js파일을 실행해 필요한 데이터르 서버에 재요청하고
브라우저가 직접 페이지를 조립하여 화면에 그린다
React, Vue 같은 프론트엔드 프레임워크들이 사용
모든 클라 요청을 단일 진입점 에서 처리하는 디자인 패턴
요청에 대한 공통 처리( 보안 로깅 인코딩)을 중앙에서 관리

앞서 봣듯이 각 서블릿마다 공통 로직이 중복됨(보일러플레이트 코드)
새 기능 추가시 모든 서블릿에 수정이 필요해진다
=> 관리가 어렵고 일관성 유지가 어렵다
=> 공통 부분이 여러개로 나눠져있을 필요가있나?

프론트 컨트롤러 패턴으로 모든 요청을 하나의 컨트롤러가 받아서 처리
=> 공통 로직을 중앙화/ 일관된 처리 흐름/ 새로운 컨트롤러 추가가 쉽다/ 유지보수 쉽다
서로 다른 인터페이스를 가진 클래스들을 연결해주는 패턴
=> 다형성을 활용한 패턴
앞서 본 마우스 예시에서 삼성ㅇ마우스든 로지텍 마우스든 마우스 타입으로 타이핑할 수 있었다
등호를 기준으로 오른쪽을 가리고 보면 다 똑같은 마우스였잖아
Spring MVC에서의 어댑터가 필요한 이유?
Spring에서 다양한 형태의 컨트롤러를 지원하니까, 프론트 컨트롤러 패턴만으로 다양한 종류의 컨트롤러를 처리하기 힘들다

이때 어댑터 패턴을 도입함으로써 핸들러어댑터를 implements해서 공통 처리가 가능하게됨
=> 다양한 컨트롤러 타입을 통일된 방식으로 처리(다형성)

프론트 컨트롤러 패턴을 구현한 스프링 MVC의 핵심적인 프론트 컨트롤러

1 클라이언트가 웹 애플리케이션에 요청을 보내면 디스패치 서블렛에 도달한다
=>
2 디스패치 서블렛은 핸들러매핑에게 요청을 처리할 핸들러(=컨트롤러)를 찾아달라고 요청한다.
공통의 처리기관이있었으니까 어떤건지 알려줘야하는거겠지?
=>
3 디스패치 서블렛이 핸들러 매핑으로부터 받은 정보를 토대로 컨트롤러에게 요청 처리를 위임
=>
4 컨트롤러가 비즈니스 로직을 수행하고, Model(결과 데이터)와 뷰의 논리적 이름을 담은 ModelAnd View 객체를 디스패치 서블렛에 반환
=>
5 디스패처서블렛은 ModelAndView에서 이름을 추춘해 ViewResolver에게 전달하고 실제 View 객체를 찾아달라 요청
=>
6 디스패처서블렛은 ViewResolver로 부터 받은 View 객체에게 모델 데이터를 전달해 뷰를 렌더링하도록 요청
=>
7 렌더링된 뷰의 겨과물이 디스패처 서블렛을 통해 클라이언트에게 응답으로 전달됨
컨트롤러가 반환한 논리적 뷰 이름ㅇ르 실제 뷰로 바꿔주는 번역기 역할!

위에서 hello를 리턴하고있지만, 이는 ViewResolver에 의해 /templates/hello.html이라는 실제 뷰 파일 경로와 매핑됨
따라서 hello는 논리적 뷰 이름
/templates/hello.html은 실제 뷰
(근데 왜 /templates/..에 들어있을까? Thymeleaf 의존성 때문임.)

모델 객체를 세팅하는 과정임 => view에서 메세지 키로부터 밸류값을 뽑아옴
th:text -> html 태그의 텍스트 내용을 서버에 전달
th:*로 HTML태그의 다양한 속성 값을 동적 설정가능
th:each for-each같이 사용가능
th:if th:unless 마찬가지 조건문

Controller의 역할이 중요해지고
View 반환 대신 데이터(Json)을 반환하는 API의 엔드포인트 역할
Model - View에 전달할 데이터가 아닌 API응답으로 보낼 데이터(DTO)로 바뀜
View- View의 역할은 사라지고 벡인드는 더 이상 HTML을 만들지 않음
@Controller
주로 View를 반환하기 위해 사용됨
@RestControoller
@Controller 에 @ResponseBody가 추가된 것
@ResponseBody
Json형식으로 리턴하기 위해 필수적으로 사용해야하는 어노테이션
@RequestMapping
특정 URL로 request보내면 들어온 요청을 Controller 내부의 특정 메서드와 매핑하기 위해 사용한다
사용법1)
@RequestMapping("/hello") 이런식으로 전체 경로 prefix를 설정가능
사용법2 - 잘 안씀)
@RequestMapping(value = "/hello", method = RequestMethod.GET) 이런식으로 특정 API의 전체 경로를 허용할 수 있따
즉, get /hello 사용할때 매핑되는 부분이라는거임
그럼 메서드별로 매핑 어떻게하는데?
@GetMapping,@PostMapping... 이런식으로 @메서드Mapping 어노테이션이 존재함

@GetMapping("/users") 이걸로 프리픽스 설정돼잇꼬
각 RequestParam을 보면 defaultValue가 있는건 존재하지 않는경우 default값을 반환하는거고, sort의 경우 requried가 false 이므로 없어도되는 값, 들어오지 않았으니까 sort에는 null이 들어있음
기본적으로required =true라서 false할라면 명시해야됨

단, 쿼리 파라미터가 너무 많이 붙어있는 경우에는? 써줘야하는게 너무 많아지잖아
=> 바인딩용 DTO 클래스를 생성
DTO : Data Transfer Object -> 데이터를 옮기는 객체

경로변수를 중괄호로 묶어서 그 부분에 원하는 값을 넣을 수 있게함
경로변수 pathvariable은 반드시 값이 있어야함! => 경로 변수는 생략되면 안되는 필수값이다

requestparam은 쿼리파라미터를 받아오는데 이는 조건부 값이잖아? 쿼리파람이 있뜬 없든 동일한 API잖아
requestparam은 조건부인것을 잊지말자!

면접에 자주나오는 흐름 정리
핸들러는 컨트롤러다
1. 클라가 요청을 보내면 디스패처 서블렛이 받음
2. 디스패처서블렛이 핸들러매핑에게 요청을 처리할 핸들러를 찾아달라하고
3. 디스패처 서블렛이 핸들러매핑으로부터 받은 정보를 이용해 컨트롤러에게 요청 처리 위임
4. 컨트롤러가 일을 마치고 결과 데이터(Model)와 뷰의 논리적 이름(View Name)을 담은 ModelANdView객체를 디스패처서블렛에 전달
5. 디스패처서블렛이 그걸 보고 뷰이름 추출해서 ViewResolver에게 전달하고, 실제 View 객체를 찾아오라함
6. ViewResolver로부터 받은 View객체에게 모델 데이터를 전달하여 View를 렌더링하도록 요청
7. 렌더링된 View의 결과물이 디스패처 서블렛을 통해 클라에게 응답으로 전달
View 는 뷰 리졸버에의해 결정된 뷰 구현체로 모델 데이터를 받아 최종 HTML 응답을 생성하는 컴포넌트(결과를 그린다)