스프링 MVC 개요
스프링 MVC는 스프링 프레임워크에서 제공하는 웹 개발용 모듈로, MVC(Model-View-Controller) 아키텍처를 구현하는 대표적인 프레임워크입니다. 이는 요청 경로 매핑, 뷰 해석, 데이터 바인딩 등 웹 애플리케이션의 주요 기능을 지원합니다.
MVC 패턴 구성 요소
- Model(모델): 비즈니스 로직 처리 및 데이터 저장을 담당하는 자바 객체 (예: 도메인 클래스, 서비스 계층).
- View(뷰): 사용자에게 보여줄 출력 결과를 생성하는 템플릿 파일 (HTML, Thymeleaf, JSP 등).
- Controller(컨트롤러): 클라이언트 요청을 수신하고, 적절한 비즈니스 로직을 호출하며, 결과를 뷰에 전달하는 역할.
핵심 컴포넌트 구조
- DispatcherServlet: 모든 요청의 진입점으로, 요청을 처리하기 위한 하위 컴포넌트들을 조율하는 중심 역할.
- HandlerMapping: 요청 경로와 해당 처리 메서드(핸들러) 간의 매핑을 결정.
- HandlerAdapter: 다양한 컨트롤러 타입(예: @RequestMapping, @GetMapping 등)에 맞춰 호출 가능하도록 어댑터 제공.
- HandlerInterceptor: 요청 처리 전/후에 특정 작업을 수행할 수 있는 인터셉터.
- ModelAndView: 처리 결과로 반환되는 모델 데이터와 뷰 이름을 포함.
- ViewResolver: 논리적 뷰 이름을 실제 파일 경로(물리적 뷰)로 변환.
요청 처리 흐름
- 클라이언트 요청이
DispatcherServlet에 도착. HandlerMapping이 요청 경로에 맞는Handler를 찾음.HandlerAdapter를 통해 핸들러 메서드 실행.- 비즈니스 로직 처리 후
ModelAndView반환. ViewResolver가 뷰 이름을 물리적 경로로 변환.- 뷰에 모델 데이터를 결합하여 응답을 클라이언트에 전송.
@RequestMapping 사용법
기본적으로 @RequestMapping은 요청 경로를 정의하며, 다음과 같은 속성을 제공합니다:
value또는path: 매핑할 경로 (필수).method: HTTP 메서드 제한 (GET, POST 등).params: 특정 파라미터 존재 여부 확인.headers: 요청 헤더 조건 설정.consumes,produces: 미디어 타입 지정.
경로 패턴 예시:
@RequestMapping("/api/user/{id}")
public String getUser(@PathVariable("id") Long userId) {
return "userDetail";
}
URL 패턴은 * (0개 이상), ** (하위 디렉토리 포함), ? (1글자) 등을 지원하며, {variable} 형태로 경로 변수를 활용할 수 있습니다.
HTTP 메서드 별 애노테이션
대표적인 파생 애노테이션:
@GetMapping: GET 요청만 처리.@PostMapping: POST 요청만 처리.@PutMapping,@DeleteMapping: PUT/DELETE 요청 처리.
브라우저는 기본적으로 GET/POST만 지원하므로, 다른 메서드를 사용하려면 _method 숨김 필드를 사용해 요청 방식을 위조해야 합니다.
파라미터 처리 방법
- 기본 파라미터 바인딩: 메서드 매개변수 이름과 요청 파라미터 이름이 일치하면 자동 매핑.
- @RequestParam: 명시적 매핑,
required=false및defaultValue지원. - 엔티티 객체 바인딩: 폼 데이터가 객체의 필드명과 일치하면 자동 생성.
- @RequestHeader, @CookieValue: 헤더 및 쿠키 값 추출.
문자 인코딩 처리
요청 본문의 인코딩 문제를 해결하기 위해 CharacterEncodingFilter를 등록합니다.
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
공유 데이터 전달 방식
다양한 방법으로 요청 스코프에 데이터를 공유할 수 있습니다:
Model,Map,ModelMap사용.HttpServletRequest.setAttribute().HttpSession또는ServletContext를 통해 세션/애플리케이션 범위 데이터 저장.
뷰 처리 방식
- 전달(Forward):
forward:/target형식으로 내부 요청 전달. - 리다이렉트(Redirect):
redirect:/target형식으로 클라이언트 재요청 유도. - 뷰 컨트롤러: XML 또는 구성 클래스에서 경로와 뷰 이름을 직접 매핑.
RESTful 설계 적용
URI에 리소스와 동작을 포함시키며, 각 메서드에 따라 동작을 구분합니다. 예시:
@DeleteMapping("/users/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
// 삭제 로직
return ResponseEntity.noContent().build();
}
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
// 생성 로직
return ResponseEntity.ok(user);
}
HTTP 메시지 변환
@RequestBody: 요청 본문을 자바 객체로 변환.@ResponseBody: 메서드 반환 값을 응답 본문으로 전송.RequestEntity,ResponseEntity: 요청/응답의 전체 정보를 제어 가능.
파일 업로드 처리
MultipartFile 타입 파라미터를 사용하여 파일을 받고, transferTo()로 저장합니다.
<form method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<button type="submit">업로드</button>
</form>
@PostMapping("/upload")
public String handleFileUpload(@RequestParam("file") MultipartFile file) throws IOException {
String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
Path uploadPath = Paths.get("uploads");
Files.write(uploadPath.resolve(fileName), file.getBytes());
return "success";
}
인터셉터 설정
HandlerInterceptor 인터페이스를 구현하여 요청 전/후에 로직을 삽입할 수 있습니다.
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (request.getSession().getAttribute("user") == null) {
response.sendRedirect("/login");
return false;
}
return true;
}
}
설정은 WebMvcConfigurer 인터페이스의 addInterceptors() 메서드에서 수행.
예외 처리 전략
@ControllerAdvice+@ExceptionHandler로 전역 예외 처리 가능.SimpleMappingExceptionResolver를 통해 예외 발생 시 뷰 이름 매핑.
구성 클래스 기반 설정
@Configuration와 @EnableWebMvc를 사용해 스프링 부트 외 환경에서도 설정 가능.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/login", "/css/**");
}
@Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxInMemorySize(1024 * 1024); // 1MB
return resolver;
}
}
스프링 MVC 실행 순서 요약
- DispatcherServlet가 요청을 수신.
- HandlerMapping을 통해 핸들러를 검색.
- HandlerAdapter를 통해 핸들러 실행.
- 모델과 뷰 정보를 포함한
ModelAndView반환. - ViewResolver를 통해 뷰 이름을 실제 파일로 변환.
- 최종 렌더링된 결과를 클라이언트에 전송.