반응형
Spring MVC 패턴
Spring MVC 패턴 정의
Spring MVC는 Spring Framework에서 제공하는 웹 애플리케이션 개발용 아키텍처로, 전통적인 MVC(Model-View-Controller) 패턴을 기반으로 설계되었습니다. 사용자의 요청과 응답 사이의 흐름을 명확히 분리하여 웹 애플리케이션의 확장성과 유지보수성을 높이는 데 목적이 있습니다.
Spring MVC 패턴 구성요소
- DispatcherServlet
Spring MVC의 프론트 컨트롤러입니다. 클라이언트의 모든 요청을 가장 먼저 받아 적절한 컨트롤러로 전달합니다. - Controller (@Controller)
클라이언트 요청을 처리하고 Model과 상호작용한 후, 뷰 이름을 반환합니다. 이 뷰 이름을 바탕으로 어떤 뷰를 렌더링할지 결정합니다. - Service
비즈니스 로직을 담당합니다. Controller와 Repository 사이에서 데이터를 가공하거나 트랜잭션 처리를 합니다. - Repository (@Repository)
데이터베이스와 직접 연결되는 레이어로, JPA, MyBatis, JDBC 등을 통해 데이터를 처리합니다. - Model
Controller에서 데이터를 View로 전달하기 위한 객체입니다. 일반적으로 Model, ModelMap, ModelAndView를 사용합니다. - View
최종적으로 사용자에게 보여지는 HTML, JSP, Thymeleaf 템플릿 등이 위치합니다. 반환된 Model 데이터를 활용해 페이지를 렌더링합니다.
Spring MVC 패턴 흐름
- 요청 수신
클라이언트가 /user/list 같은 URL로 요청을 보냅니다. - DispatcherServlet 호출
모든 요청은 DispatcherServlet이 받아들입니다 (web.xml 또는 SpringBootApplication에 자동 등록). - HandlerMapping 탐색
DispatcherServlet은 요청 URL과 매핑되는 @Controller 메서드를 찾기 위해 HandlerMapping을 참조합니다. - Controller 호출
매핑된 컨트롤러 메서드가 호출되어 요청을 처리하고 Model에 데이터를 담아 View 이름을 반환합니다. - ViewResolver 작동
DispatcherServlet은 반환된 뷰 이름을 기반으로 ViewResolver를 통해 JSP, HTML 등 실제 렌더링할 뷰 파일 경로를 결정합니다. - View 렌더링
Model 데이터를 전달받은 뷰가 최종적으로 HTML 응답을 생성하여 클라이언트에 반환합니다.
Spring MVC 패턴 실무 활용 예시
예: /users 요청에 대해 사용자 목록을 반환하는 예제
Controller
@Controller
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users")
public String getUserList(Model model) {
List<User> users = userService.getAllUsers();
model.addAttribute("users", users);
return "userList"; // View 이름
}
}
Service
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List<User> getAllUsers() {
return userRepository.findAll();
}
}
Repository (JPA 사용 시)
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
View (Thymeleaf 사용 예)
<!-- templates/userList.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<h1>User List</h1>
<ul>
<li th:each="user : ${users}" th:text="${user.name}"></li>
</ul>
</body>
</html>
Spring MVC 패턴 장점
- 역할의 명확한 분리: 요청 처리 → 로직 처리 → 결과 출력까지 각 단계가 분리되어 있어 유지보수성이 뛰어남
- 높은 확장성: 인터페이스 기반 설계와 계층 분리로 인해 기능 추가 및 테스트가 쉬움
- View 유연성: Thymeleaf, JSP, JSON, PDF 등 다양한 뷰로 응답 가능
- Spring 의존성 주입(DI)과 결합되어 테스트 및 모듈화가 용이
Spring MVC 패턴 단점
- 구성요소가 많음: DispatcherServlet, Controller, Service, Repository 등으로 인해 초기 진입장벽이 존재
- 복잡한 요청 흐름: HandlerMapping, ViewResolver 등의 내부 구조가 추상화되어 있어 디버깅이 어려울 수 있음
REST API와 Spring WebMVC의 차이
Spring WebMVC는 전통적인 서버 사이드 렌더링 방식의 MVC 구조를 지원합니다. 반면, REST API는 데이터를 JSON이나 XML 형태로 주고받는 비동기적, 클라이언트 중심의 API 설계 방식입니다.
항목 | Spring WebMVC (전통 MVC) | REST API |
응답 형태 | HTML, JSP, Thymeleaf 등 템플릿 | JSON, XML 등 데이터 |
View 처리 | ViewResolver 사용 | 없음 (HttpMessageConverter로 변환) |
주요 애너테이션 | @Controller + @ResponseBody | @RestController |
클라이언트 | 브라우저 기반 (View 중심) | 앱, 프론트엔드, 외부 시스템 등 |
용도 | 사용자 인터페이스 제공 | API 서버, 마이크로서비스, 백엔드 API |
실무 적용 예
- Spring WebMVC → 쇼핑몰, 게시판, 관리자 페이지 같은 뷰 중심 시스템
- REST API → 모바일 앱 백엔드, 프론트엔드(Vue/React) 연동, 외부 API 제공
@RestController 사용 시 흐름 차이
@Controller vs @RestController
항목 | @Controller | @RestController |
목적 | View 반환 | 데이터(JSON) 반환 |
View 처리 방식 | return "viewName" → ViewResolver 작동 | return 객체 → JSON 자동 변환 |
사용 조합 | @Controller + @ResponseBody | @RestController만 사용 가능 |
응답 처리 | ModelAndView, Model | ResponseEntity, DTO 반환 |
@RestController 흐름 구조
- 요청 → DispatcherServlet
- 매핑된 @RestController 메서드 호출
- 객체 또는 값 반환
- HttpMessageConverter가 자동으로 JSON 변환
- HTTP Response로 전송
예시
@RestController
@RequestMapping("/api")
public class UserApiController {
@GetMapping("/users")
public List<UserDto> getUsers() {
return userService.getAllUsers(); // 자동으로 JSON으로 변환
}
}
→ ViewResolver를 사용하지 않고, MappingJackson2HttpMessageConverter가 동작하여 JSON으로 응답합니다.
비동기 컨트롤러 처리 방식
1. @Async (Spring MVC 기반 비동기)
- @EnableAsync 활성화 후 @Async 메서드는 별도의 스레드에서 실행
- 비즈니스 로직을 비동기 처리할 수 있으나, 컨트롤러는 여전히 동기
@Async
public CompletableFuture<List<User>> getUsersAsync() {
return CompletableFuture.completedFuture(userRepository.findAll());
}
하지만 클라이언트는 응답을 기다려야 함
→ 비동기 로직일 뿐, 논블로킹 I/O는 아님
2. Spring WebFlux (Reactive, 논블로킹 구조)
- 완전히 논블로킹 기반으로 동작하는 새로운 웹 스택
- Mono, Flux를 사용해 비동기 스트림을 처리
@RestController
public class ReactiveUserController {
@GetMapping("/users")
public Flux<User> getUsers() {
return userReactiveRepository.findAll(); // Flux: 여러 개
}
}
- WebFlux는 서블릿 스택이 아닌 Netty 기반으로 동작 → 성능이 뛰어나고 리소스 효율적
항목 | Spring MVC + Async | Spring WebFlux |
동작 방식 | 멀티스레드 기반 | 논블로킹, 이벤트 기반 |
반환 객체 | Future, CompletableFuture | Mono, Flux |
사용 목적 | 백그라운드 작업 | 대규모 트래픽, 실시간 스트림 처리 |
예 | 이메일 전송, 로깅 | 채팅, 주식 차트, 센서 데이터 처리 등 |
Spring MVC 패턴 면접 예상 질문
- DispatcherServlet의 역할은 무엇인가요?
→ 모든 요청을 받아 해당 Controller에 위임하고, 처리된 결과를 ViewResolver를 통해 View로 전달하는 프론트 컨트롤러입니다. - Controller는 View를 직접 호출하나요?
→ 아니요, View 이름(String)만 반환하고, 실제 렌더링은 ViewResolver가 담당합니다. - ModelAndView와 Model의 차이는?
→ ModelAndView는 View 이름 + 데이터(Model)을 함께 반환할 때 사용하고, Model은 데이터만 전달할 때 사용합니다. - Spring MVC 구조에서 비즈니스 로직은 어디서 처리하나요?
→ Service 계층에서 처리합니다. Controller는 흐름만 담당하고 로직은 포함하지 않는 것이 원칙입니다. - Spring Boot에서는 어떻게 ViewResolver가 설정되나요?
→ application.properties에서 spring.thymeleaf.prefix, suffix 등을 설정하거나, 자동 설정에 의해 기본값이 적용됩니다.
반응형
'백엔드 공부일지 > 스프링부트 공부일지' 카테고리의 다른 글
Spring Boot에서의 CI/CD (1) | 2025.03.28 |
---|---|
[Spring] JWT (JSON Web Token) (0) | 2024.12.28 |