Spring MVC
https://jjiyuuuuun.tistory.com/55# MVC(spring mvc) model 1 vs model2 -1-11
Spring MVC는 Spring의 핵심 기능인 의존성 주입(Dependency Injection) 활용
📌 특징
▪️다양한 뷰 기술((JSP, Thymeleaf, FreeMarker 등) 지원, JSON, XML 등 데이터 반환 할 수 있어 RESTful API 구현에 적합
▪️Spring의 **의존성 주입과 AOP(Aspect-Oriented Programming)**를 통해 모듈화하고 관리
▪️애노테이션 기반의 설정을 통해 간단하게 컨트롤러를 구성
ex) @Controller / @RestController / @RequestMapping
▪️초기 설정, 구성 및 배포가 간소화되어, 개발자가 비즈니스 로직에 더 집중할 수 있도록 도와줌
‼️mvc 패턴의 model1과 model 2 큰 차이점 ‼️
: 요청이 들어오는 입구를 단일화(Front Controller,DispatcherServlet )시켰다 (보안 측면 성능👍🏻)
model 1은 여러개 요청이 들어오면 각 요청을 받는 서블릿(컨트롤러) 여러개
📌Spring MVC 프레임워크에서 요청처리
1️⃣ Request : 모든 클라이언트 요청은 Dispatcher Servlet으로 들어옴
▪️DispatcherServlet : 모든 웹 요청의 진입점 역할, HTTPServlet을 상속 받음
✳️ URL Mapping : 클라이언트가 보낸 HTTP 요청(URL)을 서버에서 적절한 서블릿 또는 메서드로 매핑하는 작업
▶️Spring Boot에서는 이 URL 매핑을 자동으로 처리하도록 설정되어 있다
▫️Spring Boot에서는 application.properties 또는 application.yml 파일에서 톰캣, DispatcherServlet 등의 동작을 추가로 설정할 수 있다
@Configuration
public class CustomServletConfig {
@Bean
public ServletRegistrationBean<CustomServlet> customServlet() {
ServletRegistrationBean<CustomServlet> servletBean =
new ServletRegistrationBean<>(new CustomServlet(), "/custom/*");
return servletBean;
}
}
spring boot는 모든 요청이 DispatcherServlet 하나로 받게 설정 되어 있다.
2️⃣ Handler Mapping : Dispatcher Servlet은 Handler Mapping을 사용하여 해당 요청을 처리할 적합한 컨트롤러(Handler)를 찾는다.
▪️RequestMappingHandlerMapping: 모든 URL 매핑과 관련된 메소드를 관리
애플리케이션 시작 시 모든 컨트롤러를 스캔하여 모든 매소드 매핑정보를 찾아 저장
3️⃣ Handler Adapter: 선택된 컨트롤러를 실행할 수 있게 함, 실제 컨트롤러가 실행되도록 중간에서 조정
4️⃣ Controller : 실제 비즈니스 로직을 처리하는 컨트롤러가 요청을 받아 처리, Repository, Service 계층 사용
5️⃣ Model : 컨트롤러가 처리 결과를 Model 객체에 담아 뷰에 전달함
✳️ 스프링은 다른 라이브러리에 종속되어있지 않아야한다. 내부에선 자바 API가 HttpServletRequest에 요청한 데이터를 담아서 뷰에 전달
6️⃣ View Resolver : 컨트롤러에서 반환된 뷰 이름을 바탕으로 실제 뷰 객체를 찾아냄
▫️다양한 뷰 기술(JSP, Thymeleaf 등)을 지원,
ThymeleafViewResolver : 반환된 뷰 이름에 해당하는 Thymeleaf 템플릿을 찾아 렌더링
InternalResourceViewResolver (JSP를 위한): 반환된 뷰 이름을 JSP 파일로 매핑하여 처리
@Bean
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setOrder(1);
return resolver;
}
@Bean
public ThymeleafViewResolver thymeleafViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setOrder(2);
return resolver;
}
▫️ 컨트롤러에서 "home" 이라는 뷰 이름을 반환하는 경우
- DispatcherServlet 은 먼저InternalResourceViewResolver 에 이 이름을 전달
- 만약 /WEBINF/views/home.jsp파일이 존재한다면 이 파일을 뷰로 사용
- 존재하지 않는다면 다음 ViewResolver 인 ThymeleafViewResolver 에게 넘어감
- ThymeleafViewResolver는 해당 이름에 맞는 Thymeleaf 템플릿(home.html)을 찾아 렌더링을 시도
@Bean
public ThymeleafViewResolver thymeleafViewResolver(ISpringTemplateEngine templateEngine) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine);
resolver.setCharacterEncoding("UTF-8");
resolver.setOrder(1);
resolver.setViewNames(new String[] {"*.html", "*.xhtml"});
return resolver;
}
▫️setViewNames : 처리할 수 있는 뷰 이름의 패턴 지정 : html 과 .xhtml 확장자를 가진 파일을 Thymeleaf 템플릿으로 처리하도록 설정
▫️Thymeleaf 의존성 설정
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
자동으로 ThymeleafViewResolver가 Bean으로 등록됨
7️⃣ View : Model 데이터를 사용하여 사용자에게 보여질 최종적인 응답을 생성, 이 과정에서 HTML, JSON 등의 형태로 변환될 수 있음
✳️스프링의 View는 주로 jsp 사용 안하고 타임 리프 사용
8️⃣ Response : 최종적으로 생성된 뷰가 클라이언트에게 응답으로 반환됨.
📌 Spring Boot에서의 Spring MVC
▪️자동 설정 : Spring Boot는 자동으로 DispatcherServlet, Web MVC 설정 등을 구성. 사용자는 Model,View,Controller만 구현해 놓으면 Spring Boot Framework가 위의 과정을 내부에서 동작함
▪️자동 의존성 관리 : Spring Boot의 스타터 패키지를 사용하면 필요한 의존성을 쉽게관리할 수 있다. spring-boot-starter-web 은 Spring MVC, Tomcat 서버, Jackson 라이브러리 등 웹 애플리케이션 개발에 필요한 의존성을 모두 포함
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
}
▪️쉬운 변경 : application.properties 또는application.yml 파일을 통해 애플리케이션의 다양한 설정을 쉽게 변경
▪️내장 서버 : 내장 Tomcat, Jetty 또는 Undertow 서버를 사용하여 별도의 서버 설치 없이 애플리케이션을 실행할 수 있다
📌 Controller 메소드 파라미터
🔹Web 요청과 관련된 파라미터
▫️HttpServletRequest : 원시 서블릿 요청 객체에 접근.
- 클라이언트가 보낸 HTTP 요청 정보를 담고 있는 객체(클라이언트 IP 주소 등 알아낼 수 있음)
getParameter(String name) | 요청 파라미터 값 가져오기 (query string, form) |
getHeader(String name) | 요청 헤더 값 가져오기 |
getRequestURI() | 요청 URI 반환 (/example/test) |
getMethod() | HTTP 메서드 반환 (GET, POST 등) |
getSession() | 현재 요청의 세션 객체 반환 |
@GetMapping("/example")
public String handleRequest(HttpServletRequest request) {
String param = request.getParameter("name"); // 요청 파라미터 'name'
String userAgent = request.getHeader("User-Agent"); // 요청 헤더 'User-Agent'
String uri = request.getRequestURI(); // 요청 URI
return "Param: " + param + ", User-Agent: " + userAgent + ", URI: " + uri;
}
▫️ HttpServletResponse : 원시 서블릿 응답 객체에 접근.
- 서버가 클라이언트에게 보낼 HTTP 응답을 생성하고 조작할 수 있는 객체
setStatus(int statusCode) | HTTP 상태 코드를 설정 (예: 200, 404 등) |
setHeader(String name, String value) | HTTP 응답 헤더 설정 |
addCookie(Cookie cookie) | 응답에 쿠키 추가 |
getWriter() | 응답 본문에 데이터를 쓰기 위한 출력 스트림 제공 |
@GetMapping("/response")
public void handleResponse(HttpServletResponse response) throws IOException {
response.setStatus(HttpServletResponse.SC_OK); // HTTP 200 상태 설정
response.setHeader("Content-Type", "text/plain"); // 응답 헤더 설정
response.getWriter().write("This is the response body"); // 응답 본문 작성
}
▫️ HttpSession : HTTP 세션 객체에 접근할 수 있으며, 세션 데이터를 읽거나 수정할 수 있다.
ex) 로그인 사용자 정보, 장바구니 데이터 등 클라이언트 상태를 유지해야 할 때
setAttribute(String name, Object value) | 세션에 데이터 저장 |
getAttribute(String name) | 세션에서 데이터 가져오기 |
removeAttribute(String name) | 세션에서 데이터 삭제 |
invalidate() | 세션 무효화 |
@GetMapping("/session")
public String handleSession(HttpSession session) {
session.setAttribute("username", "John Doe"); // 세션에 데이터 저장
String username = (String) session.getAttribute("username"); // 세션에서 데이터 가져오기
session.invalidate(); // 세션 무효화
return "Username: " + username;
}
🔹HTTP 요청 데이터를 메서드의 매개변수로 받기
▫️ @RequestParam : 요청 파라미터를 메소드 파라미터로 바인딩.
- 요청 예시 : /user?name=John&age=25
@GetMapping("/user")
public String getUser(@RequestParam String name,
@RequestParam(defaultValue = "0") int age) {
return "Name: " + name + ", Age: " + age;
}
▫️ @PathVariable : URI 경로의 변수 값을 메소드 파라미터로 바인딩.
- RESTful API 설계에서 자주 사용.
- 경로 템플릿 변수와 이름이 동일해야 함.
- 요청 예시/user/123
@GetMapping("/user/{id}")
public String getUserById(@PathVariable int id) {
return "User ID: " + id;
}
▫️ @RequestBody : HTTP 요청 본문(JSON, XML 등)을 메소드 파라미터 객체로 변환.
- 주로 POST, PUT 요청에서 사용.
- Jackson 라이브러리를 통해 JSON 데이터를 객체로 변환.
@PostMapping("/user")
public String createUser(@RequestBody User user) {
return "Created user: " + user.getName();
}
▫️ @ModelAttribute : 요청 파라미터를 객체에 바인딩.
- 주로 HTML 폼 데이터를 객체로 매핑할 때 사용.
@PostMapping("/user")
public String createUser(@ModelAttribute User user) {
return "User created: " + user.getName() + ", Age: " + user.getAge();
}
▫️ @SessionAttribute : 세션에서 값을 가져와 메소드 파라미터로 바인딩.
@GetMapping("/session")
public String getSessionData(@SessionAttribute(name = "user") String user) {
return "Session User: " + user;
}
🔹응답과 관련된 파라미터
▫️ Model : 뷰에 전달할 데이터를 설정할 수 있는 모델 객체
addAttribute(String key, Object value) | 데이터를 키-값 쌍으로 추가. |
addAllAttributes(Map<String, ?> map) | 여러 데이터를 한 번에 추가. |
containsAttribute(String key) | 특정 키가 존재하는지 확인. |
@Controller
public class ExampleController {
@GetMapping("/greeting")
public String greeting(Model model) {
model.addAttribute("name", "John Doe"); // 데이터를 모델에 추가
return "greeting"; // greeting.html로 이동
}
}
✳️ Thymeleaf (타임리프)
- Spring Boot에서 자주 사용하는 템플릿 엔진(Spring MVC와의 높은 호환성)
- HTML 파일을 브라우저에서 바로 열어도 깨지지 않음.
📌템플릿 엔진 이란?
미리 만들어 놓은 HTML 틀(템플릿)에 서버 데이터를 넣어 동적인 웹 페이지를 만드는 도구
서버 사이드 템플릿 엔진 | 클라이언트 사이드 렌더링 |
서버에서 HTML을 완성해서 전달 | 서버에서 데이터만 전달하고, HTML은 브라우저에서 생성 |
속도가 빠름 (초기 페이지 로드 시) | 대규모 인터랙티브 UI에 적합 |
대표: 타임리프, JSP, Freemarker | 대표: React, Vue.js, Angular |
1️⃣템플릿 파일: index.html
HTML 틀(템플릿)을 작성
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>템플릿 엔진 예제</title>
</head>
<body>
<h1>안녕하세요, <span th:text="${name}">이름</span>님!</h1>
<ul>
<li th:each="item : ${items}" th:text="${item}">아이템</li>
</ul>
</body>
</html>
▫️xmlns:th="<http://www.thymeleaf.org>"
- Thymeleaf에서 제공하는 속성(th:text, th:each 등)을 사용하기 위해 추가된 네임스페이스
- 일반 HTML 파일에서는 무시되며, Thymeleaf 템플릿 엔진에서만 동작.
2️⃣Java 코드
서버에서 데이터 제공
@Controller
public class HomeController {
@GetMapping("/")
public String home(Model model) {
model.addAttribute("name", "홍길동");
model.addAttribute("items", List.of("사과", "바나나", "포도"));
return "index"; // index.html 템플릿 사용
}
}
3️⃣최종 HTML 출력
템플릿 엔진이 데이터를 끼워 넣어 최종 HTML 생성
<!DOCTYPE html>
<html>
<head>
<title>템플릿 엔진 예제</title>
</head>
<body>
<h1>안녕하세요, 홍길동님!</h1>
<ul>
<li>사과</li>
<li>바나나</li>
<li>포도</li>
</ul>
</body>
</html>
📌 Spring MVC 응답 방식
▪️ Redirect (리다이렉트)
▪️ Forward (포워드)
'TIL' 카테고리의 다른 글
250124 TIL (2) | 2025.01.24 |
---|---|
250123 TIL (2) | 2025.01.24 |
250121 TIL (1) | 2025.01.22 |
250120 TIL (4) | 2025.01.21 |
250117 TIL (1) | 2025.01.17 |