티스토리 뷰
서블릿
서블릿 -> WAS에 서블릿 코드를 클래스 파일로 빌드해서, WAS에서 실행
HttpServlet을 상속받아 HttpServletRequest 객체와 HttpServletResponse 객체를 service 메서드로 관리한다.
HttpServletRequest
HTTP 요청 메시지를 직접 파싱해도 되지만, 불편하고 어렵다.
서블릿은 이를 파싱해주고, 결과를 HttpServletRequest 객체에 담아서 제공한다.
역할
- HTTP 메서드, URL, 쿼리 스트링, message body와 같은 정보를 파싱
- 임시 저장소 기능 - 저장 .setAttribute(), 조회 .getAttribute
- 세션 관리 기능 - .getSession
HttpServletRequest의 정보 조회
- start-line 조회 : request.getMethod() request.getProtocol() 과 같은 메서드 이용
- header 조회 : headerNames = request.getHeaderNames()를 담은 enum에서 조회
HTTP 요청 메세지를 통해 클라이언트에서 서버로 데이터를 전달하는 방법
- GET - 쿼리 파라미터 : 메세지 바디 없이 url의 쿼리 파라미터를 통해 데이터 전달, 검색 시 사용
- POST - HTML Form : 메세지 바디의 쿼리 파라미터 형식으로 전달한다. 회원가입 시 사용
- HTTP 메세지 바디 : 메세지 바디에 데이터를 직접 담아서 전달, HTTP API 방식, 다양한 데이터 형식
GET - 쿼리 파라미터
localhost:8080?username=kim&age=10 , ?로 시작하고 추가는 &
- 전체 파라미터 조회 : request.getParameterNames(), 반복을 돌려 추출
- 단일 파라미터 조회 : request.getParameter("키 값")
- 키 값이 중복인 파라미터 조회 : request.getParameterValues("키 값"), 그리고 배열에서 추출
POST - HTML Form
메세지 바디에 들어가기에 Content-Type : application/x-www-form-urlencoded 사용
+) POST 방식은 Content-Type 지정해야 함
HTTP API 메세지 바디 - 단순 텍스트
HTTP 메세지 바디에 데이터를 직접 담아서 전달, 주로 JSON을 보낸다. POST, PUT, PATCH에서 사용
텍스트를 request.getInputStream()으로 받고, byteCode로 변환해준다.
HTTP API 메세지 바디 - JSON
데이터를 받는 방식은 단순 텍스트와 같다.
이후 JSON을 파싱하기 위한 jackson 라이브러리의 ObjectMapper를 통해 각 데이터를 추출할 수 있다.
HttpServletResponse
역할
- HTTP 응답 메시지 작성 : HTTP 응답 코드 지정, 헤더 생성, 메세지바디 생성
- 편의 기능 제공 : Content-Type, 쿠키, Redirect
기본적으로 .setHeader()를 통해 값을 지정하는데, setContentType() 같은 편의 메서드를 제공한다.
HTTP 응답 데이터 전달 방법
- 단순 텍스트 응답 - 요청 데이터와 같다.
- HTML 응답
- HTTP API - MessageBody JSON
HTML 응답
Content-Type을 text/html로 설정한 후에, 말 그래도 html 코드를 담은 response를 반환한다.
HTTP API - JSON
Content-Type을 application/json 설정한 후, 데이터를 ObjectMapper로 담아 response를 반환한다.
서블릿, JSP, MVC 패턴 - 웹 애플리케이션 점진적 개발
서블릿으로 동적으로 HTML을 만들 수 있었다. 하지만 아래의 코드를 보자.
서블릿으로 HTML을 뿌려주기 위해선, 자바 코드 안에서 html 코드를 작성해야 한다.
비효율적이고 실수할 확률이 높다.
이를 위해 템플릿 엔진이 등장하였으며, HTML 문서에서 필요한 부분에 코드를 적용하여 동적으로 반환할 수 있다.
JSP(Java Server Page)
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <- jsp의 시작
<%@ 지시어 %> import문과 같음, <% 스크립틀릿 %> 자바 코드를 작성하는 공간, <%= 표현식 %> 변수 출력 시 사용
JSP를 사용하면 뷰를 담당하는 html과 자바 코드가 분리되어 서블릿보다 깔끔한 작업을 할 수 있게된다.
하지만 JSP가 너무 많은 역할을 한다. 이렇게 된다면 유지보수에 있어 어려움을 겪게 된다.
비즈니스 로직은 서블릿에서, JSP는 목적에 맞게 화면을 그리는 일에 집중할 수 있게 하는 방법이 바로
MVC 패턴
또한, 변경의 라이프 사이클이 중요하다 - 변경(수정)을 하는 주기
UI를 수정하는 일과 비즈니스 로직을 수정하는 일은 다르게 발생할 확률이 높은데
이 둘을 하나의 코드로 관리하는 것은 유지보수에 좋지 않다.
- Model : 뷰에 출력할 데이터를 담아두는 공간, 뷰가 화면 렌더링에 집중할 수 있게 함
- View : 모델에 담긴 데이터를 사용하여 화면을 그리는 역할, HTML 생성 (서블릿 역할)
- Controller : HTTP 요청을 받아 파라미터 검증 후 비즈니스 로직을 수행한다.
- - 또한, 뷰에 필요한 데이터를 확인하여 모델에 담는다.
+) 컨트롤러가 너무 많은 일을 하기에 비즈니스 로직은 서비스 계층에서 수행하고, 컨트롤러는 서비스를 호출
dispatcher.forward() -> 다른 서블릿이나 JSP로 이동할 수 있는 기능, 서버 내부에서 다시 호출이 발생
WEB-INF 경로 아래에 있는 jsp는 항상 컨트롤러를 통하여 접근 가능, 직접 경로를 입력해도 접근 불가능
redirect vs forward
- redirect는 클라이언트에 응답이 가고, 클라이언트가 리다이렉트 경로로 재요청한다.
- 클라이언트가 인지할 수 있고, 경로도 바뀐다.
- 그에 반해, forward는 서버 내부에서 일어나는 호출, 클라이언트가 인지하지 못한다.
+) jsp의 ${} 문법으로 <%= request.getParameter() %> 대신할 수 있다.
+) jps의 taglib 기능으로 모델에 담아둔 데이터를 반복하여 출력할 수 있다. <c:forEach>
MVC 패턴의 한계
MVC 패턴으로 컨트롤러의 역할과 뷰의 역할을 명확하게 구분할 수 있었다.
뷰는 화면을 그리는 역할을 충실할 수 있는 것이다.
그런데, 컨트롤러는 중복하는 부분이 많다.
- View로 이동해야 하는 코드가 반복된다. dispather.forward();
- ViewPath 의 일부 경로가 중복된다.
- 사용하지 않는 코드가 생긴다. response 객체를 대부분 사용하지 않았다.
결국 공통 처리가 어렵다는 문제가 있다. -> 공통으로 하는 일을 처리해야 한다.
컨트롤러를 호출하기 전, "수문장 역할"을 하는 공통 처리의 담당이 필요하다!
이를 프론트 컨트롤러 패턴을 도입하면 하나로 해결할 수 있다.
본 포스팅은 인프런 강의 김영한님의
[ 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 ] 을 수강하며 작성한 내용입니다.