코딩 개발/Java

MVC - FrontController Pattern

호소세 2023. 5. 31. 21:15
728x90
반응형

https://pabeba.tistory.com/157

 

Model 1 Architecture

Model1 Architecture 이란? Model 1 은 View와 Model을 모두 JSP 페이지 하나에서 처리하는 구조를 말합니다. Java Bean은 class를 만들어서 로직을 작성해 놓은 것입니다. JSP 역할 client 에게 리스트 또는 입력양

pabeba.tistory.com

https://pabeba.tistory.com/158

 

Model 2 Architecture (MVC)

Model2와 Model 1 비교해보면 재밌습니다. https://pabeba.tistory.com/157 Model 1 Architecture Model1 Architecture 이란? Model 1 은 View와 Model을 모두 JSP 페이지 하나에서 처리하는 구조를 말합니다. Java Bean은 class를 만

pabeba.tistory.com

FrontController Pattern

MVC 패턴을 하면서 왜 이렇게 자꾸만 새로운 패턴이 생기고 진화를 하는가부터 생각을 해야합니다.

저는 약간 이런 느낌이라고 생각이 됩니다.

 

제가 쿠팡같은 물류회사를 하는데 물건을 10개 이하로 팔고 있다면 물건을 적당히 정리해서 판매할 것입니다.

하지만, 100개, 1000개, 10000개 의 종류의 물건을 팔게 된다면 체계적인 분류를 통해서 물건을 정리해 놓을 것입니다.

 

프로그래밍 또한 현실세계의 가상화기 때문에 점점 편리하게 정리 정돈하는 패턴이 계속 생겨나는 것입니다.

 

이번 배울 Front Controller Design Pattern은 어떠한 장점을 가지고 있는지 살펴볼까요?

 

Front Controller Design Pattern 이란?

모든 클라이언트의 요청을 하나의 진입점으로 통합하여 처리하는 설계 패턴입니다.

위의 그림을 보시면 Front Controller를 통해서 다른 작업들이 진행됩니다.

 

Front Controller Design Pattern 장점

  • 요청을 처리하는 코드가 단일 위치에 집중되어 있어 유지보수가 쉽습니다.
  • 요청을 처리하는 데 필요한 공통 코드를 프런트 컨트롤러에서 처리할 수 있습니다.
  • 보안을 강화할 수 있습니다.
  • 성능을 향상시킬 수 있습니다.

예를 들면, post 요청 시 인코딩을 해야하는데 front controller를 거치면 모든 post 요청에 인코딩 함수를 사용할 필요없이 front controller에만 작성하면 됩니다.

인코딩 예시 외에도 인증, 예외처리, 데이터 수집 등에 사용됩니다.

 

Front Controller Design Pattern 단점

  • 프론트 컨트롤러 클래스는 모든 요청을 처리해야 하므로 복잡해지고 느려질 수 있습니다.
  • 프론트 컨트롤러 클래스는 모든 요청을 처리해야 하므로 단일 지점에서 보안 취약점이 발생할 수 있습니다.
  • 프론트 컨트롤러 클래스는 모든 요청을 처리해야 하므로 확장하기 어려울 수 있습니다.

 

 

Spring 프레임 워크를 사용하기 위해서 Spring 프레임 워크와 비슷하게 JAVA Servlet과 JSP를 이용해서 예시를 보여드리겠습니다.

예시를 보여드리면서 이해가 잘 될지는 모르겠지만 공부하는 겸 열심히 작성해 보겠습니다.

 

예시

index.js 파일 생성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Web MVC + Front Controller Design Pattern</title>
</head>
<body>
<div>
<h4>Web MVC 기반 Front Controller Design Pattern 적용</h4>
<form action="FrontControllerServletVer3" method="get">
<input type="hidden" name="command" value="findbyid">
<input type="text" name="customerId" placeholder="아이디"  required="required">
<button type="submit">검색</button>
</form>
<br><br>
<form method="post" action="FrontControllerServletVer3">
<input type="hidden" name="command" value="register">
<input type="text" name="id"  placeholder="아이디" required="required"><br>
<input type="text" name="name"  placeholder="이름" required="required"><br>
<input type="text" name="address"  placeholder="주소" required="required"><br>
<button type="submit">고객등록</button>
</form>
</div>
</body>
</html>

get method 와 post method를 form tag에 담아서 html 파일 생성했습니다.

 

⭐️ input 박스 중에 hidden type 이 있는데, 이것은 화면에는 안보이지만 데이터를 보낼 때 같이 보내지기 때문에 통신에서 유용하고 많이 이용된다고 합니다! ⭐️

 

복습해보자면 FrontControllerServletVer3 로 get or post 메소드를 보낼 수 있는 form tag 입니다!

 

다음으로는 FrontControllerServletVer3  라는 servlet 입니다.

FrontControllerServletVer3

@WebServlet("/FrontControllerServletVer3")
public class FrontControllerServletVer3 extends HttpServlet {
	private static final long serialVersionUID = 1L;
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// client의 요청 분석
		String command = request.getParameter("command");
		if (command.equals("findbyid")) {
			FindCustomerByIdController controller=new FindCustomerByIdController();
			String path=controller.findCustomer(request, response);
			request.getRequestDispatcher(path).forward(request, response);
		} else if (command.equals("register")) { // 고객 등록
			RegisterController controller=new RegisterController();
			String url=controller.register(request, response);
			response.sendRedirect(url);
		}
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doDispatch(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// post 방식 한글처리 => 공통정책
		request.setCharacterEncoding("utf-8");
		doDispatch(request, response);
	}
}

이제 이쪽으로 client의 요청이 들어옵니다.

아까 위에서 말씀드렸다시피 post 로 들어오는 모든 방식에는 인코딩을 넣어놓았습니다. 이렇게 되면 모든 코드를 변경하지 않아도 인코딩이 됩니다. (역시 숲을 봐야합니다.)

protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// post 방식 한글처리 => 공통정책
		request.setCharacterEncoding("utf-8");
		doDispatch(request, response);
	}

요청이 들어오면 각자의 method로 들어가서 doDispatch 메소드를 호출하게 됩니다.

 

1. doDispatch() 메서드에 hidden 타입의 command 라는 이름을 가진 parameter를 가져와서 어떤 함수를 실행시켜야하는지 if~ else if 문으로 구별해내고 있습니다.

2. 구별해 낸 후에는 각자의 메소드를 실행시켜 다음 화면에 보내줄 path를 받아와서 요청을 종료합니다.

 

 

하지만 이것 또한 뭔가... 캡슐화가 덜 되어있는 것 같습니다. 어짜피 통신을 보낼 path 및 url을 보내는 것이기 때문에 인터페이스를 통해 오버라이딩을 하면 될 것 같습니다.

 

public interface Controller {
	public String handleRequest(HttpServletRequest request,HttpServletResponse response) throws Exception;
}

이렇게 Controller interface를 만들고

다른 Controller에 implements를 하여 handleRequest를 오버라이딩 해줍니다.

@WebServlet("/FrontControllerServletVer4")
public class FrontControllerServletVer4 extends HttpServlet {
	private static final long serialVersionUID = 1L;
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// client의 요청을 분석
		String command = request.getParameter("command");
		if (command.equals("findbyid")) {
			FindCustomerByIdController controller=new FindCustomerByIdController();
			String path=controller.handleRequest(request, response);
			request.getRequestDispatcher(path).forward(request, response);
		} else if (command.equals("register")) { // 고객 등록
			RegisterController controller=new RegisterController();
			String url=controller.handleRequest(request, response);
			response.sendRedirect(url);
		}
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doDispatch(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// post 방식 한글처리 => 공통정책
		request.setCharacterEncoding("utf-8");
		doDispatch(request, response);
	}
}

중간의 함수들이 캡슐화되어 handleRequest 하나로 처리됩니다.

 

이렇게  Front Controller Design Pattern 을 알아보았는데요.

 

소감

사실 처음에는 그냥 Servlet 여러개 만들어서 통신하면 되는거 아닌가? 라고 생각했지만 역시 기술은 진화해야한다고 느낀 포인트는 인코딩 방식과 에러 핸들링 등 중복되는 것들을 servlet에 하나하나 작성해야한다는 생각에 치가 떨렸기 때문입니다.

오늘은 시간의 소중함을 느끼는 하루였습니다. 좋은 글이 있어서 하나 올리고 글 마치겠습니다. 독서실에 항상 마지막까지 남아있는 사람이... 서울대 생이였나... 그랬던 것 같아요.

https://m.blog.naver.com/ihappy0304/223116188600

 

반응형