-
학원 day76. MVC 패턴기록 2022. 12. 21. 16:57
웹 어플리케이션 개발방식은 크게 Model1 개발방식과 Model2 개발방식이 있다.
클라이언트의 요청이 오면 톰캣은 jsp와 서블릿을 실행하고, 클라이언트는 응답으로 html컨텐츠를 받게 된다.
(웹서버 안에는 만들어놓은 웹어플리케이션이 있고, 웹어플리케이션은 보통 jsp와 서블릿이다.)
Model1 개발방식에는 서버에 jsp가 들어있는데 JSP 안에는 html태그(디자인코드)와 java코드(로직코드)가 섞여서 들어있다. 그래서 헷갈리고 유지보수가 어려운 문제점이 있었다. 그리고 JSP에서 바로 DAO를 실행시켜 db엑세스를 요청하면 조회결과를 반환받는다. (세미프로젝트에서 사용했던 방식)
Model2 개발방식에서는 MVC(Model-View-Controller)패턴을 적용해서 구현한다.
JSP 안에 자바코드는 없고 디자인코드만 있다. EL + JSTL 을 사용한다.
비즈니스로직과 디자인코드를 분리하는 것이 목적이다.
모델2 개발방식에서는 Front Controller 역할을 하는 서블릿, Controller 역할을 하는 Java클래스, View 역할을 수행하는 JSP를 만들고 Model 역할을 수행하는 Java클래스가 있다.
Model : 업무로직을 수행해서 뷰에 표현할 데이터 제공, 뷰에서 표현하는 데이터 그 자체
View : 모델에서 제공하는 데이터 표현
Controller : 클라이언트 요청 처리 담당 (요청을 하려면 db엑세스가 필요하므로, 클라이언트가 무엇을 요청했는지 분석하는 것까지가 Controller의 역할이다.)
Front Controller
- 서블릿 혹은 필터로 구현
- 클라이언트의 요청을 접수받는다.
- 클라이언트의 요청을 분석해서 적절한 Controller를 실행한다.
- 요청처리가 완료되면 View로 내부이동 또는 재요청 URL 응답으로 보낸다.
- 프레임워크에서 제공한다.
Controller
- 클라이언트의 요청을 처리
(요청파라미터값 조회, 세션에서 로그인된 사용자 정보 조회, 내부이동할 JSP 페이지, 재요청할 URL제공)
- 클라이언트의 요청을 처리하기 위해서 업무로직 메소드를 호출한다.
- Model이 반환하는 데이터를 View에 전달
- FrontController에 내부이동할 JSP 혹은 재요청 URL 제공
View
- JSP 구현
- Controller가 전달한 Model의 데이터를 표현한다.
- HTML 컨텐츠를 생성해서 응답으로 제공한다.
Model
- View에 표현할 데이터
- View에 표현할 데이터를 획득하는 작업(업무로직)
모델2는 이제 jsp 주소를 작성할 일이 없다. 이제는 jsp에 요청하는게 아니라 서블릿에 요청하는 것이다.
jsp는 더이상 첫 진입점이 아니다. 맨 마지막에 표현해주는 놈이다.
FrontController가 요청을 받아서 분석하여 Controller를 실행시키고
Controller가 데이터를 받아서 JSP로 전달한다.
Service에서 데이터를 반환한다.
주소창에 .hta를 적으면 무조건 FrontController가 실행되도록 설정함.
HttpServlet을 상속받은 자바클래스는 톰캣이 http요청이 오면 FrontController의 service라는 메소드를 실행해준다.
그리고 web.xml에 url패턴정보를 적어서 톰캣에다가 알려준다.
URL : 자원의 위치
URI : 자원에 대한 식별자 (자원의 위치가 아닌 어떤 요청을 했는지 식별하는 것)
요청 URI : /model2/posts/detail.hta
요청 URI에는 쿼리스트링이 포함되지 않는다.
model2는 웹어플리케이션을 대표하는 이름
쿼리스트링은 요청URI에 표시하지 않는다.
Context Path : 웹어플리케이션을 구분하는 고유한 경로로 보통은 프로젝트명과 동일하다.
public class FrontController extends HttpServlet { private Map<String, Controller> controllerMap = new HashMap<>(); /** * 서블릿의 초기화 메소드다. <br /> * 서블릿 객체가 생성되면 톰캣이 딱 한번 호출해서 서블릿을 초기화시킨다.<br /> */ public void init(ServletConfig config) throws ServletException { controllerMap.put("/home.hta", new HomeController()); controllerMap.put("/register-form.hta", new RegisterFormController()); controllerMap.put("/login-form.hta", new LoginFormController()); } @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("### FrontController의 service(request, response) 메소드 실행."); // 요청 URI 분석하기 // ContextPath(웹 어플리케이션을 구분하는 고유한 경로다. 보통은 프로젝트명과 동일하다.) 조회하기 String contextPath = request.getContextPath(); System.out.println("### contextPath : " + contextPath); // 요청 URI 조회하기 String requestURI = request.getRequestURI(); System.out.println("### 요청 URI : " + requestURI); requestURI = requestURI.replace(contextPath, ""); System.out.println("### 요청 URI : " + requestURI); // 컨트롤러 실행하기 try { // HashMap객체에 저장된 Controller 인터페이스 구현객체 꺼내기 Controller controller = controllerMap.get(requestURI); // 조회된 컨트롤러 객체의 execute(request, response); 실행 String viewName = controller.execute(request, response); // 지정된 뷰페이지(viewName)으로 클라이언트의 요청을 이동시킨다. // 즉, JSP를 실행시키는 것이다. RequestDispatcher requestDispatcher = request.getRequestDispatcher(viewName); requestDispatcher.forward(request, response); } catch (Exception e) { throw new ServletException(e); } } }
요청이 왔으면 요청객체와 응답객체가 만들어질텐데, 톰캣이 서블릿(FrontController)을 실행시키기 위해서 요청객체와 응답객체를 FrontController의 서비스 메소드에 전달하고, execute로 controller를 호출할 때 전해주는 것이다. 그러니까 Controller에서 모든 요청정보를 꺼내올 수 있는 것이다.
더이상 요청처리할 때 JSP가 필요없어진 것이다. 자바클래스이지만 HTTP요청을 처리할 수 있는 것이다. (요청객체에서 값을 꺼내고, 응답객체에 값을 담을 수 있게 된 것이다.)
요청객체에는 요청파라미터와 속성을 담을 수 있다.
클라이언트가 요청할 때 쿼리스트링과 폼입력값을 전할 수 있는데 요청파라미터라는 곳에 NAME, VALUE로 저장된다.
속성도 마찬가지로 NAME, VALUE로 구성되는데 요청파라미터와 차이점은 VALUE가 Object타입이다. 객체를 담을 수 있는 것이다. HttpServletRequest에 속성이라는 것을 저장할 수 있다.
요청객체를 세군데에서 공유한다.
request에도 속성을 담을 수 있다. 세션처럼. 그런데 세션에 담은 속성은 로그아웃하기 전까지 유지된다.
request에 담은 속성은 응답가면 사라진다.
속성은 값을 꺼낼 수도 있고 담을 수도 있다.
요청객체 속성에 값을 담는 이유는 FrontController의 service메소드 실행할 때 전달되니까.
톰캣이 만든 요청객체와 응답객체를 전달해주지 않고 service메소드를 실행할 수 없다.
우리는 요청객체에서 요청URI를 조회하고, controllerMap에서 URI이름으로 되어 있는 객체를 꺼낸다.
그리고 해당 객체에 들어있는 execute라는 메소드를 실행하는데, 실행하면서 자신이 전달받은 request객체를 해당 Controller에 전달해 주는 것이다. 해당 Controller에서는 값을 담을 수 있다.
jsp로 내부이동할 때 요청객체와 응답객체를 모두 전달해줘야 jsp를 실행시킬 수 있다.
이때가지는 request.getAtrribute();로 값을 받았지만 이제부터는 jsp에서 자바코드를 적지 않을 것이다. 대신
EL이라는 *표현언어를 적을 것이다.
* EL (Expression Language)
- 표현언어
- JSP 2.0부터 지원된다.
- EL은 값을 표현할 때 사용되는 스크립트 언어다.
- 기능 :
- 요청파라미터값, 초기화파라미터값의 표현
- PageContext, 요청객체, 세션객체, 애플리케이션객체의 속성값 표현
- 요청헤더정보, 쿠키값의 표현
- 사칙연산, 비교연산, 논리연산자, 기타 연산자 제공
- 메소드 호출 기능 제공
- 형식 : ${EL표현식}
값을 무슨이름으로 담았는지를 기억하고, 그 이름으로 요청객체에 담아 home_jsp에 전달되는 것이다.
값을 뽑을 때는 jsp안에서 <p>${message }</p> <- 이렇게 적으면 된다.
- 자바코드를 jsp에서 저장할 때 이름만 알면 값을 알면 값을 꺼낼 수 있다.
- 속성에서 message라는 이름으로 저장된 걸 꺼내서 표현한다.
밑에꺼는 jsp를 직접 호출하여 FrontContreller의 경로를 안탔기 때문!
Controller에서 값을 담는 과정이 빠졌기 때문이다.
home.jsp를 호출할 수도 있으니 절대 호출하지 못하게 web-inf 폴더에 옮겨놓는다. 그러면 아래 화면처럼 접근 불가하다.
WEB-INF 폴더는 보호되는 폴더다. 서버가 아닌 바깥에서 WEB-INF 내부를 볼 수 없다.
jsp에 대한 직접적인 접근을 허용하지 않는다.
기존 model1방식에서는 jsp에서 값을 조회하고 표현하였다.
앞으로 model2방식에서는 값을 조회하는 건 controller에서 하고 요청객체에 담아서 jsp에 전달한다.
EL만으로는 표현 못하는 건 JSTL을 사용한다.
EL은 값을 표현하는 것 밖에 못하지만 JSTL은 값을 반복처리, if문처리 등도 할 수도 있다.
JSTL(JSP Standard Tag Library)
- JSP 표준태그 라이브러리
- 스크립틀릿을 사용해서 작성했던 자바코드를 대체할 수 있다.
- 변수 선언/삭제, 값 출력, 제어문 처리, 반복문 처리, 숫자나 날짜에 대한 포맷팅, 국제화처리, URL처리
- 사용법
- JSTL 파일을 다운받아서 WEB-INF/lib에 복사한다.
- JSP 파일에 사용할 태그라이브러리를 지시어를 사용해서 정의한다.
<%@ taglib prefix="별칭" uri="태그라이브러리식별자" %> <별칭:태그명 value="${EL표현식}" />
JSP의 속성과 스코프
속성 :
- 속성은 객체(값)다.
- 속성은 뷰에 표현할 정보다.
- JSP는 속성(값, 객체)을 저장할 수 있는 4종류의 객체를 제공한다.
PageContext - 해당 jsp 페이지에서밖에 못꺼내간다. jsp마다 생김.
HttpServletRequest - 내부이동한 다른 jsp에서 꺼내갈 수 있다, 응답이 완료되면 자동으로 사라진다.
HttpSession - 로그인한 해당 클라이언트만 꺼내갈 수 있다. 로그아웃하기전까지 유지된다. 로그아웃하기 전까지 모든 jsp에서 꺼내갈 수 있다.
ServletContext - 톰캣이 꺼질때까지 유지된다.
4가지 내장객체에 저장할 수 있는 객체를 속성이라고도 한다.
어디에 담는가에 따라서 속성을 유지할 수 있는 시간, 사용할 수 있는 범위가 다르다.
=> 스코프가 다르다라고 표현
스코프
- 속성(값, 객체)를 공유할 수 있는 유효범위를 말한다.
- 속성(값, 객체)을 위의 4 종류 객체 중 어디에 저장하느냐에 따라서 저장된 속성(값, 객체)에 대한 이용범위 혹은 생존시간이 달라진다.
session은 로그아웃하기 전까지 유지되어서 함부로 쓰면 안된다.
응답이 내려가면 자동으로 없어지는 request객체가 가장 유리하다.
요청객체는 메모리에 부담이 가지않는다. pageContext와 달리 내부이동하면 다른 jsp에서도 사용가능하다.
Request객체는 컨트롤러와 뷰 사이의 데이터를 전달하는 버스 역할을 하는 중요한 객체이다.
'기록' 카테고리의 다른 글
학원 day78. JSTL(2) (0) 2022.12.23 학원 day77. JSP의 속성과 스코프, EL, JSTL (0) 2022.12.22 학원. 세미프로젝트 (0) 2022.12.21 학원 day71. (0) 2022.12.14 학원 day70. 회원가입 (0) 2022.12.13