FrontController 패턴
FrontController는 소프트웨어 디자인 패턴 중 하나로, 웹 어플리케이션 및 다른 종류의 소프트웨어에서 사용되는 패턴입니다. FrontController는 어플리케이션의 진입점 역할을 수행하며, 클라이언트 요청을 받아들이고 해당 요청에 대한 처리 방식을 중앙에서 제어하는 컴포넌트입니다.
FrontController 특징
- 중앙 집중화된 요청 처리 : FrontController는 클라이언트로부터 들어오는 모든 요청을 중앙에서 처리합니다. 이렇게 함으로써 애플리케이션의 요청 처리 로직을 한 곳에서 관리할 수 있습니다.
- 인터셉팅과 전처리 : 클라이언트 요청이 들어올 때 FrontController는 해당 요청을 인터셉트하고 전처리 작업을 수행합니다. 이 단계에서는 인증, 권한 확인, 로깅 등과 같은 공통 작업을 처리할 수 있습니다.
- 커맨드 패턴 활용 : FrontController는 커맨드 패턴을 사용하여 요청을 처리하는데, 각 요청에 대한 구체적인 처리 로직은 커맨드 객체로 캡슐화됩니다.
- 뷰 관리 : 요청 처리가 완료되면 FrontController는 적절한 뷰를 선택하고 뷰를 렌더링하여 클라이언트에 반환합니다.
- 렌더링과 후처리 : FrontController는 뷰 렌더링 이후에도 후처리 작업을 수행할 수 있습니다. 이 단계에서는 보안 설정, 캐싱, 리소스 정리 등을 수행할 수 있습니다.
FrontController 장점
- 코드 구조의 명확화 : FrontController 패턴을 사용하면 애플리케이션의 구조가 명확해집니다. 각 커맨드 객체는 특정한 요청 처리만 담당하므로 코드의 모듈화와 재사용성이 높아집니다.
- 유지보수성 향상 : 코드 중복을 최소화하고 공통 작업을 효율적으로 처리함으로써 유지보수성이 향상됩니다. 새로운 요청 타입이나 작업을 추가하는 경우 전체 애플리케이션을 수정할 필요 없이 해당 부분만 확장할 수 있습니다.
- 비즈니스 로직과 UI 분리 : FrontController 패턴을 사용하면 비즈니스 로직과 사용자 인터페이스(UI) 처리를 분리할 수 있습니다. 이로써 애플리케이션의 관리가 더 용이해집니다.
실습
controller.jsp → FrontController.java
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.ArrayList,model.BoardVO" %>
<jsp:useBean id="bDAO" class="model.BoardDAO" />
<jsp:useBean id="mDAO" class="model.MemberDAO" />
<jsp:useBean id="mVO" class="model.MemberVO" />
<jsp:setProperty property="*" name="mVO" />
<jsp:useBean id="bVO" class="model.BoardVO" />
<jsp:setProperty property="*" name="bVO" />
<%
String action=request.getParameter("action");
System.out.println("로그: controller.jsp");
System.out.println("action: "+action);
System.out.println("bVO: "+bVO);
System.out.println("mVO: "+mVO);
if(action.equals("main")){
ArrayList<BoardVO> datas=bDAO.selectAll(null);
request.setAttribute("datas", datas);
request.getRequestDispatcher("b_main.jsp").forward(request, response);
}
else if(action.equals("board")){
bVO=bDAO.selectOne(bVO);
if(bVO!=null){
request.setAttribute("data", bVO);
request.getRequestDispatcher("d_board.jsp").forward(request, response);
}
}
else if(action.equals("login")){
mVO = mDAO.selectOne(mVO); // mVO에 mid,mpw가 setter에 의해 저장됨
if(mVO==null){
out.println("<script>alert('로그인 실패...');history.go(-1);</script>");
}
else{
session.setAttribute("mid", mVO.getMid());
response.sendRedirect("controller.jsp?action=main");
}
}
else if(action.equals("logout")){
session.removeAttribute("mid");
response.sendRedirect("controller.jsp?action=main");
}
else if(action.equals("signupPage")){
response.sendRedirect("e_signup.jsp");
}
else if(action.equals("signup")){
boolean flag=mDAO.insert(mVO);
if(flag){
out.println("<script>alert('회원가입 성공! 로그인후에 이용하세요! :D');location.href='controller.jsp?action=main';</script>");
}
else{
out.println("<script>alert('회원가입 실패...');history.go(-1);</script>");
}
}
else if(action.equals("insertBoardPage")){
response.sendRedirect("c_insertBoard.jsp");
}
else if(action.equals("insertBoard")){
boolean flag=bDAO.insert(bVO);
if(flag){
out.println("<script>alert('게시글 작성 성공!');location.href='controller.jsp?action=main';</script>");
}
else{
out.println("<script>alert('게시글 작성 실패...');history.go(-1);</script>");
}
}
else if(action.equals("updateBoard")){
boolean flag=bDAO.update(bVO);
if(flag){
out.println("<script>alert('게시글 변경 성공!');location.href='controller.jsp?action=board&num="+bVO.getNum()+"';</script>");
}
else{
out.println("<script>alert('게시글 변경 실패...');history.go(-1);</script>");
}
}
else if(action.equals("deleteBoard")){
boolean flag=bDAO.delete(bVO);
if(flag){
response.sendRedirect("controller.jsp?action=main");
}
else{
out.println("<script>alert('게시글 삭제 실패...');history.go(-1);</script>");
}
}
else if(action.equals("mypagePage")){
response.sendRedirect("mypage.jsp");
}
else if(action.equals("mypage")){
///// mVO.setMid((String)session.getAttribute("mid"));
mVO=mDAO.selectOne(mVO);
if(mVO!=null){
request.setAttribute("data", mVO);
request.getRequestDispatcher("f_mypage.jsp").forward(request, response);
}
else{
out.println("<script>alert('비밀번호 불일치...');history.go(-1);</script>");
}
}
else if(action.equals("updateMember")){
boolean flag=mDAO.update(mVO);
if(flag){
out.println("<script>alert('회원정보 변경 성공! 로그인후에 이용하세요! :D');location.href='controller.jsp?action=logout';</script>");
}
else{
out.println("<script>alert('회원정보 변경 실패...');history.go(-1);</script>");
}
}
else if(action.equals("deleteMember")){
boolean flag=mDAO.delete(mVO);
if(flag){
out.println("<script>alert('회원탈퇴 성공!');location.href='controller.jsp?action=logout';</script>");
}
else{
out.println("<script>alert('회원탈퇴 실패...');history.go(-1);</script>");
}
}
else{
out.println("<script>alert('action 파라미터의 값을 확인해주세요!');history.go(-1);</script>");
}
%>
controller.jsp
↓
package controller;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("*.do")
public class FrontController extends HttpServlet {
private static final long serialVersionUID = 1L;
public FrontController() {
super();
}
private void doAction(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. Client가 보낸 요청을 추출 -> 어떤 액션인지 파악
// 더이상 파라미터를 들고다니지않음!
// URL을 분석해야함!!!
String uri=request.getRequestURI();
System.out.println("uri: "+uri);
String cp=request.getContextPath();
System.out.println("cp: "+cp);
String command=uri.substring(cp.length());
System.out.println("command: "+command);
// 2. 추출한 요청에 맞는 Action클래스의 execute() 메서드를 호출
ActionForward forward=null;
if(command.equals("/main.do")) {
forward=new MainAction().execute(request, response);
}
else if(command.equals("/signup.do")) {
forward=new SignupAction().execute(request, response);
}
else if(command.equals("/mypage.do")) {
forward=new MypageAction().execute(request, response);
}
else if(command.equals("/login.do")) {
forward=new LoginAction().execute(request, response);
}
else if(command.equals("/logout.do")) {
forward=new LogoutAction().execute(request, response);
}
else if(command.equals("/board.do")) {
forward=new BoardAction().execute(request, response);
}
else if(command.equals("/signupPage.do")) {
forward=new ActionForward();
forward.setRedirect(true);
forward.setPath("e_signup.jsp");
}
else if(command.equals("/insertBoardPage.do")) {
forward=new ActionForward();
forward.setRedirect(true);
forward.setPath("c_insertBoard.jsp");
}
else if(command.equals("/updateBoard.do")) {
forward=new UpdateBoardAction().execute(request, response);
}
else if(command.equals("/deleteMember.do")) {
forward=new DeleteMemberAction().execute(request, response);
}
else if(command.equals("/deleteBoard.do")) {
forward=new DeleteBoardAction().execute(request, response);
}
else if(command.equals("/updateMember.do")) {
forward=new UpdateMemberAction().execute(request, response);
}
else if(command.equals("/insertBoard.do")) {
forward=new InsertBoardAction().execute(request, response);
}
else {
}
// 3. 사용자에게 응답. View로 이동
if(forward!=null) {
if(forward.isRedirect()) {
response.sendRedirect(forward.getPath());
}
else {
RequestDispatcher dispatcher=request.getRequestDispatcher(forward.getPath());
dispatcher.forward(request, response);
}
}
else {
response.sendRedirect("goback.jsp");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doAction(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doAction(request, response);
}
}
FrontController.java
Action 인터페이스 생성 후 execute() 추상메서드 정의
package controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface Action {
ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
Action.java
ActionForward 클래스 생성
package controller;
public class ActionForward {
private boolean redirect;
private String path;
public boolean isRedirect() {
return redirect;
}
public void setRedirect(boolean redirect) {
this.redirect = redirect;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
ActionForward.java
GitHub
https://github.com/Qkrwnsgus0522/JSP
GitHub - Qkrwnsgus0522/JSP
Contribute to Qkrwnsgus0522/JSP development by creating an account on GitHub.
github.com
FrontController 패턴
FrontController는 소프트웨어 디자인 패턴 중 하나로, 웹 어플리케이션 및 다른 종류의 소프트웨어에서 사용되는 패턴입니다. FrontController는 어플리케이션의 진입점 역할을 수행하며, 클라이언트 요청을 받아들이고 해당 요청에 대한 처리 방식을 중앙에서 제어하는 컴포넌트입니다.
FrontController 특징
- 중앙 집중화된 요청 처리 : FrontController는 클라이언트로부터 들어오는 모든 요청을 중앙에서 처리합니다. 이렇게 함으로써 애플리케이션의 요청 처리 로직을 한 곳에서 관리할 수 있습니다.
- 인터셉팅과 전처리 : 클라이언트 요청이 들어올 때 FrontController는 해당 요청을 인터셉트하고 전처리 작업을 수행합니다. 이 단계에서는 인증, 권한 확인, 로깅 등과 같은 공통 작업을 처리할 수 있습니다.
- 커맨드 패턴 활용 : FrontController는 커맨드 패턴을 사용하여 요청을 처리하는데, 각 요청에 대한 구체적인 처리 로직은 커맨드 객체로 캡슐화됩니다.
- 뷰 관리 : 요청 처리가 완료되면 FrontController는 적절한 뷰를 선택하고 뷰를 렌더링하여 클라이언트에 반환합니다.
- 렌더링과 후처리 : FrontController는 뷰 렌더링 이후에도 후처리 작업을 수행할 수 있습니다. 이 단계에서는 보안 설정, 캐싱, 리소스 정리 등을 수행할 수 있습니다.
FrontController 장점
- 코드 구조의 명확화 : FrontController 패턴을 사용하면 애플리케이션의 구조가 명확해집니다. 각 커맨드 객체는 특정한 요청 처리만 담당하므로 코드의 모듈화와 재사용성이 높아집니다.
- 유지보수성 향상 : 코드 중복을 최소화하고 공통 작업을 효율적으로 처리함으로써 유지보수성이 향상됩니다. 새로운 요청 타입이나 작업을 추가하는 경우 전체 애플리케이션을 수정할 필요 없이 해당 부분만 확장할 수 있습니다.
- 비즈니스 로직과 UI 분리 : FrontController 패턴을 사용하면 비즈니스 로직과 사용자 인터페이스(UI) 처리를 분리할 수 있습니다. 이로써 애플리케이션의 관리가 더 용이해집니다.
실습
controller.jsp → FrontController.java
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.ArrayList,model.BoardVO" %> <jsp:useBean id="bDAO" class="model.BoardDAO" /> <jsp:useBean id="mDAO" class="model.MemberDAO" /> <jsp:useBean id="mVO" class="model.MemberVO" /> <jsp:setProperty property="*" name="mVO" /> <jsp:useBean id="bVO" class="model.BoardVO" /> <jsp:setProperty property="*" name="bVO" /> <% String action=request.getParameter("action"); System.out.println("로그: controller.jsp"); System.out.println("action: "+action); System.out.println("bVO: "+bVO); System.out.println("mVO: "+mVO); if(action.equals("main")){ ArrayList<BoardVO> datas=bDAO.selectAll(null); request.setAttribute("datas", datas); request.getRequestDispatcher("b_main.jsp").forward(request, response); } else if(action.equals("board")){ bVO=bDAO.selectOne(bVO); if(bVO!=null){ request.setAttribute("data", bVO); request.getRequestDispatcher("d_board.jsp").forward(request, response); } } else if(action.equals("login")){ mVO = mDAO.selectOne(mVO); // mVO에 mid,mpw가 setter에 의해 저장됨 if(mVO==null){ out.println("<script>alert('로그인 실패...');history.go(-1);</script>"); } else{ session.setAttribute("mid", mVO.getMid()); response.sendRedirect("controller.jsp?action=main"); } } else if(action.equals("logout")){ session.removeAttribute("mid"); response.sendRedirect("controller.jsp?action=main"); } else if(action.equals("signupPage")){ response.sendRedirect("e_signup.jsp"); } else if(action.equals("signup")){ boolean flag=mDAO.insert(mVO); if(flag){ out.println("<script>alert('회원가입 성공! 로그인후에 이용하세요! :D');location.href='controller.jsp?action=main';</script>"); } else{ out.println("<script>alert('회원가입 실패...');history.go(-1);</script>"); } } else if(action.equals("insertBoardPage")){ response.sendRedirect("c_insertBoard.jsp"); } else if(action.equals("insertBoard")){ boolean flag=bDAO.insert(bVO); if(flag){ out.println("<script>alert('게시글 작성 성공!');location.href='controller.jsp?action=main';</script>"); } else{ out.println("<script>alert('게시글 작성 실패...');history.go(-1);</script>"); } } else if(action.equals("updateBoard")){ boolean flag=bDAO.update(bVO); if(flag){ out.println("<script>alert('게시글 변경 성공!');location.href='controller.jsp?action=board&num="+bVO.getNum()+"';</script>"); } else{ out.println("<script>alert('게시글 변경 실패...');history.go(-1);</script>"); } } else if(action.equals("deleteBoard")){ boolean flag=bDAO.delete(bVO); if(flag){ response.sendRedirect("controller.jsp?action=main"); } else{ out.println("<script>alert('게시글 삭제 실패...');history.go(-1);</script>"); } } else if(action.equals("mypagePage")){ response.sendRedirect("mypage.jsp"); } else if(action.equals("mypage")){ ///// mVO.setMid((String)session.getAttribute("mid")); mVO=mDAO.selectOne(mVO); if(mVO!=null){ request.setAttribute("data", mVO); request.getRequestDispatcher("f_mypage.jsp").forward(request, response); } else{ out.println("<script>alert('비밀번호 불일치...');history.go(-1);</script>"); } } else if(action.equals("updateMember")){ boolean flag=mDAO.update(mVO); if(flag){ out.println("<script>alert('회원정보 변경 성공! 로그인후에 이용하세요! :D');location.href='controller.jsp?action=logout';</script>"); } else{ out.println("<script>alert('회원정보 변경 실패...');history.go(-1);</script>"); } } else if(action.equals("deleteMember")){ boolean flag=mDAO.delete(mVO); if(flag){ out.println("<script>alert('회원탈퇴 성공!');location.href='controller.jsp?action=logout';</script>"); } else{ out.println("<script>alert('회원탈퇴 실패...');history.go(-1);</script>"); } } else{ out.println("<script>alert('action 파라미터의 값을 확인해주세요!');history.go(-1);</script>"); } %>
controller.jsp
↓
package controller; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("*.do") public class FrontController extends HttpServlet { private static final long serialVersionUID = 1L; public FrontController() { super(); } private void doAction(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. Client가 보낸 요청을 추출 -> 어떤 액션인지 파악 // 더이상 파라미터를 들고다니지않음! // URL을 분석해야함!!! String uri=request.getRequestURI(); System.out.println("uri: "+uri); String cp=request.getContextPath(); System.out.println("cp: "+cp); String command=uri.substring(cp.length()); System.out.println("command: "+command); // 2. 추출한 요청에 맞는 Action클래스의 execute() 메서드를 호출 ActionForward forward=null; if(command.equals("/main.do")) { forward=new MainAction().execute(request, response); } else if(command.equals("/signup.do")) { forward=new SignupAction().execute(request, response); } else if(command.equals("/mypage.do")) { forward=new MypageAction().execute(request, response); } else if(command.equals("/login.do")) { forward=new LoginAction().execute(request, response); } else if(command.equals("/logout.do")) { forward=new LogoutAction().execute(request, response); } else if(command.equals("/board.do")) { forward=new BoardAction().execute(request, response); } else if(command.equals("/signupPage.do")) { forward=new ActionForward(); forward.setRedirect(true); forward.setPath("e_signup.jsp"); } else if(command.equals("/insertBoardPage.do")) { forward=new ActionForward(); forward.setRedirect(true); forward.setPath("c_insertBoard.jsp"); } else if(command.equals("/updateBoard.do")) { forward=new UpdateBoardAction().execute(request, response); } else if(command.equals("/deleteMember.do")) { forward=new DeleteMemberAction().execute(request, response); } else if(command.equals("/deleteBoard.do")) { forward=new DeleteBoardAction().execute(request, response); } else if(command.equals("/updateMember.do")) { forward=new UpdateMemberAction().execute(request, response); } else if(command.equals("/insertBoard.do")) { forward=new InsertBoardAction().execute(request, response); } else { } // 3. 사용자에게 응답. View로 이동 if(forward!=null) { if(forward.isRedirect()) { response.sendRedirect(forward.getPath()); } else { RequestDispatcher dispatcher=request.getRequestDispatcher(forward.getPath()); dispatcher.forward(request, response); } } else { response.sendRedirect("goback.jsp"); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doAction(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doAction(request, response); } }
FrontController.java
Action 인터페이스 생성 후 execute() 추상메서드 정의
package controller; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public interface Action { ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException; }
Action.java
ActionForward 클래스 생성
package controller; public class ActionForward { private boolean redirect; private String path; public boolean isRedirect() { return redirect; } public void setRedirect(boolean redirect) { this.redirect = redirect; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } }
ActionForward.java
GitHub
https://github.com/Qkrwnsgus0522/JSP
GitHub - Qkrwnsgus0522/JSP
Contribute to Qkrwnsgus0522/JSP development by creating an account on GitHub.
github.com