이론/백엔드 개념정리

MVC (Model-View-Controller) 패턴 개요

블스뜸 2025. 5. 5. 14:25

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