1. MVC란?
MVC는 애플리케이션의 구성 요소를 각각 Model, View, Controller 세 가지 책임 영역으로 분리하여
개발의 효율성과 유지보수성을 높이는 대표적인 디자인 패턴이다.
2. 구성 요소 설명
- Model (모델)
애플리케이션의 정보, 데이터(데이터베이스, 상수, 변수, 초기화값 등)를 저장하고 데이터를 가공하는 기능을 담당하는 영역이다.
모델의 특징
- 애플리케이션에서 필요한 정보를 모두 저장하고 있다.
- 재사용이 가능하다.
- View나 Controller에 대해서 어떠한 정보도 알지 못한다.
- View (뷰)
사용자에게 모델이 처리한 결과를 인터페이스 요소와 함께 보여주는 UI 기능을 담당하는 영역이다.
뷰의 특징
- 모델이 가지고 있는 정보를 따로 저장하고 있지 않다.
- 재사용이 가능하다.
- Model이나 Controller에 대해서 어떠한 정보도 알지 못한다.
- Controller (컨트롤러)
클라이언트 측의 요청을 받고 Model과 View사이에서 상호작용을 담당하는 영역이다.
컨트롤러의 특징
- Model과 View의 소통의 다리(중개자) 역할이다.
- Model이나 View에 대해서 모두 알고 있다
간단한 프로그램이라면 이렇게 나눌 필요 없이 하나의 파일로 구성하는 것이 낫지 오히려 MVC 패턴을 구성하는 것에서 시간이 더 소요될 것이다. 하지만 어느 정도 복잡한 프로그램일 때라면 MVC 패턴을 구성하는 것이 효율적이다.
MVC 패턴을 사용했을 때 장점
- 관심사의 분리: 개발과 유지보수를 용이하게 해 준다.
- 유연성: 구성 요소가 독립성을 가져 일부분만 수정하고 확장하기 쉽다.
- 재사용성: Model과 View는 재사용이 가능하여 다양한 상황에서 같은 로직을 사용할 수 있다.
2.Spring에서의 MVC 패턴
MVC패턴은 꼭 이렇게 해라! 저렇게 해라! 같이 정형화된 패턴이 아니기 때문에 여러 상황에서 유연하게 사용된다.
Spring에서의 MVC 패턴 또한 다른 구조로 활용되고 있다.

| 구성요소 | 설명 |
| DispatcherServlet | 모든 HTTP 요청을 가장 먼저 받아 처리하는 Front Controller 역할을 한다. |
| HandlerMapping | 요청 URL을 어떤 Controller가 처리할지 결정한다. |
| HandlerAdapter | 해당 Controller를 실행할 수 있는 어댑터이다. |
| Controller | 클라이언트 요청을 수행하고 결과를 반환한다. |
| ModelAndView | Controller가 처리한 결과를 담는 정보 객체이다. |
| ViewResolver | View 이름에 따라 실제 View의 경로와 정보를 결정한다. |
| View | 사용자에게 보여질 최종 화면이다. |
동작 순서
1. 클라이언트가 HTTP 요청을 전송하면, Spring의 DispatcherServlet이 해당 요청을 가장 먼저 받는다.
(DispatcherServlet는 Front Controller 패턴 중 하나로, DispatcherServlet은 Spring MVC의 중심이 되는 Front Controller이다.)
2. DispatcherServlet은 HandlerMapping을 통해 요청 URL에 대응하는 핸들러를 조회한다.
(Spring에서 제공하는 기능이다.)
3. Controller를 실행하기 위한 HandlerAdapter를 조회한다.
(Spring은 다양한 형태의 Controller를 지원하므로, 이를 일관되게 실행하기 위해 어댑터가 필요하다.)
4. HandlerAdapter가 실제로 Controller를 실행한다.
5. Controller는 처리 결과를 ModelAndView 객체에 담아 반환한다.
6. DispathcerServlet이 ModelAndView를 ViewResolver에 전달하여 View이름에 해당하는 실제 View 객체를 찾는다.
7. ViewResolver는 해당하는 View 객체를 반환하고, View가 실행되며 렌더링 된 HTML 화면이 응답으로 전송된다.
3. 간단한 예시
간단하게 MVC 구조를 이용하여 Spring 게시판을 만들어 보았다.
이 예제는 Controller가 클라이언트의 요청을 받아 Service를 통해 데이터를 처리하고,
그 결과를 Model에 담아 View로 전달하는 MVC 흐름을 보여준다.
ArticleController.java
package study.crudboard.controller;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
// import ...
@Controller
@RequiredArgsConstructor
@RequestMapping("/articles")
public class ArticleController {
private final ArticleService articleService;
// 글 목록 보기
@GetMapping
public String list(Model model) {
model.addAttribute("articles", articleService.findAll());
return "articles/list";
}
// 글 작성 폼
@GetMapping("/form")
public String form(Model model) {
model.addAttribute("article", new ArticleForm());
return "articles/form";
}
// 글 저장
@PostMapping
public String create(@ModelAttribute ArticleForm form, HttpSession session) {
// 로그인된 사용자 정보 가져오기
Member loginMember = (Member) session.getAttribute("loginMember");
String author = (loginMember != null) ? loginMember.getName() : "login plz";
int id = articleService.generateId();
String nowDate = Util.getNowDateStr();
Article article = new Article(id, form.getTitle(), form.getBody(), nowDate, author);
articleService.create(article);
return "redirect:/articles";
}
// 생략
// ....
}
| 어노테이션 | 설명 |
| @Controller | 이 클래스가 Spring MVC 컨트롤러임을 선언한다 |
| @RequestMapping | /articles로 시작하는 모든 요청을 이 컨트롤러에서 처리한다 |
| @GetMapping, @PostMapping | 각각 HTTP GET, POST 요청에 매핑된다 |
| @RequiredArgsConstructor | Lombok 어노테이션. final 필드에 대해 생성자를 자동 생성한다 |
@GetMapping // {/articles} URL로 접근했을 때의 HTTP GET 요청을 처리한다.
public String list(Model model) {
model.addAttribute("articles", articleService.findAll());
return "articles/list";
}
// articleService.java
package study.crudboard.service;
import java.util.List;
@Service
@RequiredArgsConstructor
public class ArticleService {
public List<Article> findAll() {
return articleRepository.findAll();
}
// 생략
// ...
}
- Service영역을 호출하여 비즈니스 로직을 처리 후, 위와 같이 Model에 데이터를 추가하고,
"articles/list"이라는 뷰 이름을 반환한다. - Spring은 반환된 뷰 이름과 모델 데이터를 사용해 자동으로 ModelAndView 객체를 구성하고,
이를 기반으로 ViewResolver가 실제 뷰 템플릿을 찾아 렌더링을 수행한다.
// /articles/form 경로로 HTTP GET 요청이 들어오면,
// HandlerMapping을 통해 이 URL에 매핑된 메서드를 찾아 호출한다.
@GetMapping("/form")
public String form(Model model) {
model.addAttribute("article", new ArticleForm()); // "article"이라는 이름으로 Model에 추가한다.
return "articles/form";
}
- "articles/form"를 반환하면, ViewResolver가 이 이름을 해석하여 해당 뷰 템플릿 파일을 찾는다.
- View 템플릿에서 ArticleForm 객체의 값을 사용할 수 있게 된다. (article이 변수명이 된다.)
순서 진행
클라이언트 요청 → Controller 실행 → Model에 데이터 저장 → View 반환 → ViewResolver가 해석하여 HTML 렌더링
list.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Post List</title>
</head>
<body>
<h1>All Posts</h1>
<table border="1">
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Author</th>
<th>Date</th>
<th>Hits</th>
</tr>
</thead>
<tbody>
<tr th:each="article : ${articles}">
<td th:text="${article.id}"></td>
<td>
<a th:href="@{/articles/{id}(id=${article.id})}" th:text="${article.title}"></a>
</td>
<td th:text="${article.author}"></td>
<td th:text="${article.nowDate}"></td>
<td th:text="${article.hit}"></td>
</tr>
</tbody>
</table>
<a th:href="@{/articles/form}">Create New Article</a>
</body>
</html>
form.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Create New Post</title>
</head>
<body>
<h1>Create New Post</h1>
<form th:action="@{/articles}" th:object="${article}" method="post">
<label>Title:
<input type="text" th:field="*{title}" required>
</label><br>
<label>Content:
<textarea th:field="*{body}" required></textarea>
</label><br>
<button type="submit">Submit</button>
</form>
<a th:href="@{/articles}">Back to List</a>
</body>
</html>
출처
https://m.blog.naver.com/jhc9639/220967034588
https://ittrue.tistory.com/234
'Spring' 카테고리의 다른 글
| [Spring] AOP & Proxy 란? (3) | 2025.08.01 |
|---|---|
| [Spring] 트랜잭션 전파(Propagation) 정리 (3) | 2025.07.12 |
| [Spring] JDBC Template 정리 (0) | 2025.05.31 |
| [Spring] IoC / DI 정리 (0) | 2025.03.22 |
| [Spring] 빈 / 빈 스코프(Bean / Bean Scope) 정리 (0) | 2025.03.19 |