일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- compiler
- 음수가 포함된 최단경로
- 우선순위큐
- dto
- bottom-up
- 코딩테스트
- disjoint set
- kmeans
- onclick
- 다익스트라
- 직무면접
- clean code
- Java
- Python
- top-down
- spring boot
- 기술면접
- union-find
- 최단경로
- Android Studio
- 벨만 포드 알고리즘
- scikit-learn
- Django
- Controller
- 거쳐가는 정점
- 플로이드 와샬
- 엔테크서비스
- 유니온 파인드
- 동적계획법
- BufferedReader
- Today
- Total
춤추는 개발자
[inflearn] 스프링 MVC 1편 review 본문
✅ 강의 소개
웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다.
✅ 강의별 후기
[ Servlet ]
Servlet은 톰캣같은 웹 어플리케이션 서버를 직접 설치하고, 그 위에 서블릿 코드를 클래스 파일로 빌드해서 올린 다음, 톰캣 서버를 실행.
Servlet을 생성하여 실제 Http 요청/응답을 수행.
HttpServletReqeust / HttpServletResponse를 기반으로 각 객체에 담기는 Parameter에 대한 이해.
- Application 클래스 @ServletComponentScan으로 Servlet을 직접 등록해서 사용.
- HttpServlet을 상속받은 클래스에 @WebServlet으로 이름과 urlPattern을 설정, service 메서드를 오버라이딩하여 Servlet으로 활용할 수 있다.
- application.properties에서 로깅 레벨을 설정 - ('logging.level.org.apache.coyote.http11=debug')
- Servlet은 Http 요청 메시지를 파싱하고 HttpServletRequest 객체에 담아서 제공 및 임시 저장소 역할
- setAttribute / getAttribute / getSession 등, START LINE / Header / Body 관련 메서드 제공
- Http 요청 데이터
- GET: URL의 쿼리 파라미터(/url?username=hello&age=20)에 데이터를 포함해서 전달
o HttpServletRequest가 제공하는 메서드로 쿼리 파라미터를 조회할 수 있다.
o getParameter / getParameterNames / getParameterMap / getParameterValues
o getParameterNames().asIterator().forEachRemaining()
o 만약 파라미터 이름이 중복된 경우, getParamterValues를 활용
- POST: content-type: application/x-www-form-urlencoded, 메시지 바디에 쿼리 파라미터 형식으로 전달
o GET에서 사용한 쿼리 파라미터 조회 메서드를 그대로 사용
o POST HTML Form 형식으로 데이터를 전달하면 HTTP 메시지 바디에 해당 데이터를 포함해서 보내기 때문에 바디에 포함된 데이터가 어떤 형식인지 content-type을 지정해야 한다.
- HTTP message body에 데이터를 직접 담아서 요청: HTTP API (Json, Xml, Text), POST / PUT / PATCH
o 단순 텍스트를 메시지 바디에 담을 경우, inputStream으로 읽을 수 있다.
o Json 형식은 content-type: application/json
o Json 형식의 데이터를 ObjectMapper를 활용하여 직접 만든 객체에 담아 파싱할 수 있다.
- Http 응답 데이터 ( HttpServletResponse )
- HTTP 응답코드 지정 / 헤더, 바디 생성
- content-type, cookie, redirect 기능 제공
[ Servlet, JSP, MVC 패턴 ]
회원 저장/조회 기능을 단순 Servlet으로 시작하여 JSP, MVC 패턴으로 개발
단계별로 한계점과 불편한 점들을 개선
- 지난 Servlet 강의 내용을 바탕으로 요구사항 기능 개발 / 자바 코드에 View화면을 위한 HTML이 섞여 지저분하고 복잡.
- 정적인 HTML 문서의 불편함을 동적인 HTML인 JSP로 개발 / 하지만 다양한 코드(비즈니스 로직, 뷰 로직 등)가 섞여있어서 JSP가 많은 역할을 담당.
- 비즈니스 로직과 뷰 로직을 분리한 MVC 패턴으로 개발 / Servlet은 컨트롤러, JSP는 View 역할
o Controller: HTTP 요청을 받아서 파라미터 검증 및 비즈니스 로직 수행, 뷰에 전달할 결과 데이터를 모델에 담는다.
o Model: 뷰에 출력할 데이터를 담는 역할.
o View: 모델에 담겨있는 데이터를 화면에 출력.
- redirect는 실제 클라이언트에 나갔다가, 다시 서버로 요청 / forward는 서버 내부에서 일어나는 호출로 클라이언트가 인지하지 못함.
- 현재 Controller 역할을 하는 Servlet 코드에 중복된 로직이 많음 / 이를 다음 강의에서 해결
o Forward와 Viewpath, 사용하지 않는 코드, 공통 처리의 한계
[ MVC 프레임워크 만들기 ]
프론트 컨트롤러를 도입하여 View 분리 / Model 추가
v1 ~ v5까지 단계별로 로직을 리팩토링
- v1: 요청의 입구가 되는 FrontController 도입
o Servlet과 비슷한 모양의 Controller 인터페이스를 도입, 이를 상속받아 활용하여 process 메서드를 오버라이딩
o 공통 로직의 반복
- v2: v1에서 중복된 로직 중 ViewPath와 ReqeustDispatcher.forward를 공통 처리
o MyView라는 클래스에 View를 반환하는 공통 로직을 담은 메서드를 만든다.
o 사용하지 않는 Servlet 코드
o View 이름 중복
- v3: v2의 Servlet 종속성과 View 이름 중복 제거
o 요청 파라미터 정보를 request 대신 별도의 ModelView 객체를 만들어서 반환.
o ModelView에는 뷰 이름을 담는 viewName과 요청 변수를 담는 Map형식의 model 생성.
o 프론트 컨트롤러에는 HttpServletRequest에 담긴 파라미터를 map에 저장하여 요청에 맞는 controller에 전달.
o Controller들은 view이름이 담긴 ModelView를 반환.
o Controller는 뷰의 논리 이름을 반환하고, 프론트 컨트롤러에서 뷰의 물리 위치를 처리하도록 viewResolver 메서드를 생성.
o MyView 객체에는 model에 담긴 데이터를 request에서 저장하여 반환.
o 항상 ModelView 객체를 생성하고 반환하는 번거로움 존재.
- v4: ModeView를 반환하지 않고, 뷰 이름만 반환
o 프론트 컨트롤러에서 model 객체를 생성해서 controller에 넘겨준다.
o 여기에 유연성을 더해준다.
- v5: 어댑터 패턴을 적용
o 핸들러 어댑터: 다양한 종류의 컨트롤러를 호출
o supports 메서드: 어댑터가 해당 컨트롤러를 처리할 수 있는지 판단.
o handle 메서드: 실제 컨트롤러를 호출하고 ModelView를 반환.
o 핸들러: 더 넓은 범위의 컨트롤러를 의미
o 프론트 컨트롤러에서는 요청받은 URI를 처리할 수 있는 어댑터를 조회
o 매핑된 어댑터가 있으면 handle메서드를 호출하여 ModelView를 반환받고, 뷰 렌더링
- 다음에는 어노테이션 기반으로 컨트롤러를 통합한다.
[ 스프링 MVC - 구조 이해 ]
직접 만든 프레임워크 < --- > 스프링 MVC 비교
FrontController < - > DispatcherServlet
handlerMappingMap < - > HandlerMapping
MyHandlerAdapter < - > HandlerAdapter
ModelView < - > ModelAndView
viewResolver < - > ViewResolver
MyView < - > View
스프링 MVC 구조와 동작 순서를 파악하고 기존 코드 리팩토링
- DispatchServlet도 HttpServlet을 상속받아서 사용하고, 모든 경로에 대해 매핑, 더 자세한 경로가 우선순위가 높다.
- 동작 순서
o 핸들러 조회: 핸들러 매핑을 통해 URL에 매핑된 핸들러(컨트롤러)를 조회
o 핸들러 어댑터 조회: 핸들러를 실행할 수 있는 핸들러 어댑터를 조회
o 핸들러 어댑터 실행: 핸들러 어댑터를 실행
o 핸들러 실행: 핸들러 어댑터가 실제 핸들러를 실행
o ModelAndView 반환: 핸들러 어댑터는 핸들러가 반환하는 정보를 ModelAndView로 변환해서 반환
o viewResolver 호출: 뷰 리졸버를 찾고 실행
o View 반환: 뷰 리졸버는 뷰의 논리 이름을 물리 이름으로 바꾸고, 렌더링 역할을 하는 뷰 객체를 반환
o 뷰 렌더링: 뷰를 통해서 뷰를 렌더링
- 주요 인터페이스 목록
o 핸들러 매핑: org.springframework.web.servlet.HandlerMapping
o 핸들러 어댑터: org.springframework.web.servlet.HandlerAdapter
o 뷰 리졸버: org.springframework.web.servlet.ViewResolver
o 뷰: org.springframework.web.servlet.View
- 스프링 부트가 자동 등록하는 핸들러 매핑과 핸들러 어댑터
o RequestMappingHandlerMapping: 어노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
o BeanNameUrlHandlerMapping: 스프링 빈의 이름으로 핸들러를 찾는다.
o RequestMappingHanlderAdapter: 어노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
o HttpRequestHandlerAdapter: HttpRequestHandler 처리
- 가장 우선순위가 높은 핸들러 매핑과 핸들러 어댑터를 활용할 수 있는 @RequestMapping으로 스프링 MVC의 컨트롤러를 통합
- @RequestMappng 대신, Http 메서드를 나타내는 @GetMapping, @PostMapping으로 처리
[ 스프링 MVC - 기본 기능 ]
로깅 레벨에 대한 이해.
Http 요청 매핑과 요청 파라미터와 관련된 Http 메서드와 어노테이션에 대한 이해.
Http 응답의 종류
요청에 따른 Http 메시지 컨버터
- System.out.print() 대신 SLF4J / LogBack과 같은 로깅 라이브러리의 성능(내부 버퍼링, 멀티 스레드 등등)이 좋다. / 기본적으로 시간, 로그 레벨, 클래스명 등 출력되어 유지보수에 용이
- Log 레벨: TRACE > DEBUG > INFO > WARN > ERROR
- 올바른 로그 사용법: log.debug("data = {}", data)
- @Controller는 반환값이 String이면 뷰 이름으로 인식하여 뷰가 렌더링
- @RestController는 반환값이 Http 메시지 바디에 바로 입력, @ResponseBody와 연관
- @PathVariable로 URL경로에 매칭되는 데이터를 편리하게 조회, pathName과 변수명이 같으면 생략 가능
- @RequestMapping에 특정 헤더나 미디어 타입 조건을 매핑할 수 있다.
- @RequestMapping기반의 컨트롤러에 다양한 파라미터를 지원
o HttpServletRequest
o HttpServletResponse
o HttpMethod: Http 메서드를 조회
o Locale: Locale 정보를 조회
o @RequestHeader MultivalueMap<String, String> headerMap: 모든 Http 헤더 정보를 조회
o @RequestHeader("host"): 특정 Http 헤더 정보를 조회
o @CookieValue(value = "xxx"): 특정 쿠키를 조회
- @RequestParam
o 요청 파라미터를 편리하게 조회 (HttpServletRequest.getParameter("name"))
o String, int, Integer 등 단순 타입이면 생략 가능
o 생략하는 대신, required = false
o 파라미터에 값이 없는 경우, 빈문자 or NULL 반환 or defaultValue 사용
o @RequestParam map<string, object>으로 요청 파리미터와 매핑가능
- @ModelAttribute
o 요청 파라미터를 특정 객체에 자동으로 매핑해준다.
o 요청 파라미터의 이름으로 객체의 프로퍼티를 setter로 찾아서 등록한다.
o @RequestParam처럼 생략가능
- @HttpEntity
o HTTP 헤더와 바디 정보를 편리하게 조회
o 요청 파라미터를 조회하는 @RequestParam, @ModelAttribute와 관계 없음
o 응답에도 사용 가능하며, view 조회는 불가
o @RequestEntity: HttpMethod, url 정보가 추가
o @ResponseEntity: HTTP 상태 코드 설정 가능
- @ResponseBody / @RequestBody
o HTTP 메시지 바디 정보를 편리하게 조회
o @ModelAttribute처럼 직접 만든 객체를 지정할 수 있다.
o 대신, 생략하면 요청 파라미터처럼 동작하게 되어서 생략할 수 없다.
o 응답으로 사용하면 Http 메시지 바디에 데이터를 그대로 입력한다.
- Http 메시지 컨버터
o 스프링MVC 내부에서 HTTP 메시지 바디를 읽어서 문자나 객체로 변환하여 전달하는데, 이때 Http 메시지 컨버터라는 기능을 사용한다.
o ByteArrayHttpMessageConverter: byte[], */*
o StringHttpMessageConverter: String, */*
o MappingJackson2HttpMessageConverter: 객체 또는 HashMap, application/json
o RequestMappingHandlerAdapter 동작 과정에서 호출된다.
- ArgumentResolver
o RequestMappingHandlerAdapter에서 핸들러가 필요로하는 다양한 파라미터의 값을 생성하여 전달
o 이와 유사하게 ReturnValueHandler는 응답값을 변환하고 처리
[ 스프링 MVC - 웹 페이지 만들기 ]
상품에 대한 CRUD 기능을 제작하며 요청/응답에 대한 객체를 처리
핸들러 응답에 따른 브라우저 동작을 이해
- 지금까지 들은 내용을 바탕으로 Controller를 개발
- @RestController, @GetMapping, @PostMapping ,@PathVariable, @ModelAttribute 등 활용
- PRG (Post, Redirect / GET)
o 웹 브라우저의 새로고침은 마지막에 서버에 전송한 데이터를 다시 전송해서 상품 등록 후, 새로고침하면 새로운 데이터가 계속 등록된다.
o 상품 저장 후에 뷰 템플릿이 아닌, 상품 상세 화면으로 리다이렉트
o RedirectAttiributes.addAttribute("itemId", savedItem.getId());
o return "redirect:/basic/items/{itemId}";
o 이외에 addAttribute("status", true)와 같은 방식으로 쿼리 파라미터 처리가 가능
✅ review
스프링 MVC에 대해서는 현업에서 API를 개발하며 당연시하게 사용해왔다. 하지만 MVC가 지금까지 어떤 방식으로 개선되어 왔으며 각각의 어노테이션을 왜 사용하는지 이해할 수 있었다. 특히, MVC 전체 동작 방식을 정확하게 이해하는데 가장 큰 도움이 되었다.
강의 내용을 실무에 적용할 때, 강의에서 다룬 내용에 맞춰 레거시 코드를 파악하고, 개선점을 찾아 리팩토링 방향을 잡을 수 있게 됐다. (물론, 사이드 이팩트로 인해 아직까지 손대기 힘든 코드가 많다...)
가장 최근에는 보안성 이슈가 있었던 기능에 HttpEntity를 활용하며 해결하기도 했다. 임시 방편이였지만, 리다이렉트 형식으로 리팩토링할 예정이다.
'Developer's_til > 스프링 프레임워크' 카테고리의 다른 글
[Spring] 완전한 AOP 솔루션을 제공하는 AspectJ (0) | 2023.10.25 |
---|---|
[inflearn] 스프링 MVC 2편 review (0) | 2023.06.11 |
[inflearn] 스프링 핵심 원리 - 기본편 review (0) | 2023.03.04 |
[Spring] 트랜잭션으로 알아보는 스프링 AOP (0) | 2021.08.24 |
[Spring] 다양한 관점에서 개발하는 스프링의 AOP - 3 (0) | 2021.08.23 |