MVC (Model-View-Controller) 패턴 개요
MVC 패턴은 소프트웨어 디자인 패턴의 일종으로, 애플리케이션을 세 가지 역할로 분리하여 개발하는 구조이다. 이는 코드의 변경 용이성 및 유지보수성 향상을 목표로 한다.
핵심 내용: View 분리의 근거 (변경)
View 분리의 주된 이유는 변경에 대한 효율적 대응이다. 통상적으로 기획 변경과 비즈니스 로직 변경은 독립적으로 발생한다.
- 화면 구성 변경: View 영역만 수정한다.
- 요구사항 변경: 비즈니스 로직 영역만 수정한다.
결론적으로 상호 연관성이 낮은 코드가 동일 영역에 존재할 필요 없이, 각 역할별 코드 완전 분리가 MVC 패턴의 핵심이다.
1. Controller
- 예시 코드에서 Servlet에 상응하는 영역이다.
- HTTP Request를 수신하여 파라미터를 검증한다.
- 비즈니스 로직 실행을 담당한다. 단, Controller의 역할 과부하 방지를 위해 통상적으로 Service Layer를 별도로 구성하여 비즈니스 로직을 처리한다.
- 데이터베이스 상호작용을 위해 Repository Layer를 추가적으로 분리하여 역할을 명확히 한다. (Layered Architecture 관련 상세 내용은 추후 학습 예정)
- Controller는 비즈니스 로직을 직접 포함할 수 있으나, 일반적인 경우 Service Layer를 호출하는 역할을 수행한다.
- View에 전달할 결과 데이터를 조회하여 Model 객체에 임시 저장한다.
2. Model
- View에 출력할 데이터를 저장하는 객체이다.
- View는 비즈니스 로직 또는 데이터 접근 방식에 대한 지식 없이, Model에 저장된 데이터에만 집중하여 화면을 렌더링한다 (책임 분리).
3. View
- 예시 코드에서 JSP에 상응하는 영역이다.
- Model 객체에 저장된 데이터를 활용하여 화면을 렌더링한다.
Servlet 예시
@WebServlet("/hello-world")
public class HelloWorldServlet extends HttpServlet {
// User 저장소
private UserRepository repository = new UserRepository();
public HelloWorldServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
try {
// 비지니스 로직을 처리하는 코드
// 파라미터 조회
String userIdParam = request.getParameter("userId");
Long userId = null;
if (userIdParam != null) {
userId = Long.parseLong(userIdParam);
}
// 회원 조회
String userInfo = repository.findById(userId);
// 화면을 그리는 코드 START
out.println("<h1>Hello World!</h1>");
out.println("<div>조회한 회원의 정보: " + userInfo + "</div>");
// 화면을 그리는 코드 END
} catch (NumberFormatException e) {
// parsing 에러가 발생한 경우
out.println("<div>Invalid user ID format</div>");
} finally {
out.close();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
- Servlet 문제점
- 화면을 그리는 View 영역과 비지니스 로직이 Servlet 하나에 모두 섞여있다.
- 책임을 너무 많이 가지고 있다.
JSP 예시
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<!-- HTML 코드... -->
<!-- <%...%> 영역에는 Java 코드를 사용할 수 있다. -->
<%
// 게시글 저장소 싱글톤으로 인스턴스 생성
BoardRepository boardRepository = BoardRepository.getInstance();
// 게시글 제목, 내용
String title = request.getParameter("title");
String content = request.getParameter("content");
// 게시글 객체 생성
Board board = new Baord(title, content);
// 게시글 객체 저장
repository.save(board);
%>
<div>
ID : <input type ="text" name = "id" value="<%=id %>">
</div>
<!-- JSP 코드... -->
<!-- HTML 코드... -->
<jsp:forward page="<%=url %>" />
</body>
</html>
Servlet 코드에서 HTML을 만드는 부분인 View가 분리되었다.

- Servlet, JSP 방식의 문제점
- Servlet만을 사용한 경우 View를 위한 코드와 비지니스 로직을 처리하는 코드가 Servlet에 모두 존재하여 유지보수가 어려워진다.
- JSP를 사용하여 View를 분리하였지만 비지니스 로직의 일부가 JSP 파일안에 존재한다. 여전히 책임이 많아 유지보수가 어렵다.