* 65. MVC 모델2
#MVC ?
model1 | model2 | |
장점 | 빠르고 쉽게 개발 가능 | 디자이너와 개발자의 분업이 가능하며 유지보수 및 확장이 쉬움 |
단점 | JSP파일이 너무 비대해지며 Controller와 view 가 혼재하므로 향후 유지보수에 어려움 | 설계가 어려우며 개발 난이도가 높음 |
- Model (모델): 모델은 어플리케이션의 데이터와 비즈니스 로직을 담당. 데이터의 저장, 가져오기, 수정, 삭제 등과 같은 작업을 처리하며, 데이터의 변화를 감지하고 필요한 경우 뷰(View) 및 컨트롤러(Controller)에 알릴 수 있는 기능을 가진다.
- View (뷰): 뷰는 사용자에게 데이터를 시각적으로 표현하는 역할. 웹 어플리케이션에서는 주로 HTML, CSS 및 JavaScript로 구성되며, 사용자 인터페이스를 생성하고 데이터를 효과적으로 표시하는 역할을 수행한다.
- Controller (컨트롤러): 컨트롤러는 사용자의 입력을 처리하고 모델 및 뷰 간의 흐름을 관리. 사용자가 뷰를 통해 요청을 보내면 컨트롤러가 이를 받아 모델을 업데이트하거나 데이터를 가져오는 작업을 수행하며, 변경된 데이터를 다시 뷰에 반영한다.
MVC2 패턴은 MVC 패턴의 변형으로써, 주로 웹 어플리케이션에서 사용되는데,
여기서 컨트롤러(Controller)는 사용자의 요청을 처리하고 비즈니스 로직을 수행하는 역할을 맡는다.
또한, 뷰(View)는 사용자 인터페이스를 생성하고 데이터를 표시하는 역할을 담당하며,
모델(Model)은 데이터와 데이터 조작을 다룬다.
요약하자면, MVC2는 모델, 뷰 및 컨트롤러로 구성되어 있으며,
이 구성 요소들은 각각의 역할과 책임을 가지고 협력하여 웹 어플리케이션을 구조화하고 개발하는 데
도움을 주는 디자인 패턴이다.
# MVC2 모델 적용해보기 (Login)
기존의 Servlet을 Controller로 변경 해준다.
즉, header 에서도 form.jsp로 바로 링크를 보내주었던 것을
form 으로 보냄으로써 Controller가 관리하게 한다.
그런데 한번 더 나아가서 ...
from 에서 처리하는 것을 /auth/login 에서 일괄 처리해주기로 하자.
즉..
/auth/form의 get, /auth/login의 post 요청을
LoginController에서 일괄 처리한다.
이렇게 해주면 로그인 화면 및 로그인 기능을 모두 하나의 파일에서
관리할 수 있게 된다.
그림에서 보듯이,
로그인폼(GET요청), 로그인(POST요청) 모두
LoginController 가 처리하는 것을 볼 수있다.
이렇게 /auth/login 으로 페이지가 이동된다면,
아래 코드에서 보듯이 GET과 POST 요청을 처리하는데,
get요청으로 form 을 불러오고 바로 해당 파일에서
Post 요청으로 로그인 정보를 확인한다.
@WebServlet("auth/login")
package bitcamp.myapp.contlloer;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import bitcamp.myapp.dao.MemberDao;
import bitcamp.myapp.vo.Member;
// form 이후 로그인
@WebServlet("/auth/login")
public class LoginController extends HttpServlet {
private static final long serialVersionUID = 1L;
// (기존 loginform)
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 인클루딩 하는 경우,
// 여기서 콘텐트 타입을 미리 설정해야 한다.
response.setContentType("text/html;charset=UTF-8");
// view 컴포넌트를 인클루딩 한다.
request.getRequestDispatcher("/auth/form.jsp").include(request, response);
}
// (기존 login)
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Member m = new Member();
m.setEmail(request.getParameter("email"));
m.setPassword(request.getParameter("password"));
if (request.getParameter("saveEmail") != null) {
Cookie cookie = new Cookie("email", m.getEmail());
response.addCookie(cookie);
} else {
Cookie cookie = new Cookie("email", "no");
cookie.setMaxAge(0);
response.addCookie(cookie);
}
MemberDao memberDao = (MemberDao) this.getServletContext().getAttribute("memberDao");
Member loginUser = memberDao.findByEmailAndPassword(m);
if (loginUser != null) {
// 로그인 정보를 다른 요청에서도 사용할 있도록 세션 보관소에 담아 둔다.
request.getSession().setAttribute("loginUser", loginUser);
response.sendRedirect("/");
return;
}
request.setAttribute("message", "회원 정보가 일치하지 않습니다.");
request.setAttribute("refresh", "1;url=/auth/form.html");
request.getRequestDispatcher("/error.jsp").forward(request, response);
}
}
# MVC2 모델 적용해보기2 (Member)
먼저 member의 add, delete, detail, form, list, update 요청을 살펴보면..
add 와 update 는 doPost 요청이고 delete, detail, form, list는 doGet 요청이다.
form 에서 add 요청까지 실행하기때문에
MemberAddController에서 member/form 과 member/add 의
doPost 와 doGet을 모두 받아주면 된다.
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
request.getRequestDispatcher("/member/form.jsp").include(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
MemberDao memberDao = (MemberDao) this.getServletContext().getAttribute("memberDao");
SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) this.getServletContext().getAttribute("sqlSessionFactory");
NcpObjectStorageService ncpObjectStorageService = (NcpObjectStorageService) this.getServletContext().getAttribute("ncpObjectStorageService");
Member m = new Member();
m.setName(request.getParameter("name"));
m.setEmail(request.getParameter("email"));
m.setPassword(request.getParameter("password"));
m.setGender(request.getParameter("gender").charAt(0));
Part photoPart = request.getPart("photo");
if (photoPart.getSize() > 0) {
String uploadFileUrl = ncpObjectStorageService.uploadFile(
"bitcamp-nc7-bucket-22", "member/", photoPart);
m.setPhoto(uploadFileUrl);
}
delete 와 update jsp 파일들은 Controller 에서 구현하므로 삭제한다.
# 에러처리 페이지
또한, 기존에 forward (주소변경은 없이 해당 오류 처리 페이지로 넘겨주는 기능)을 제거하고
web.xml 파일에서 아래 문구를 추가해서 ServletException 오류가 발생하면
자체적으로 오류 처리 화면으로 이동해주도록 만들어준다.
이제 ServletException이 발생하면 /error.jsp 로 이동한다.