🦁멋쟁이사자처럼 백엔드 부트캠프 13기 🦁
TIL 회고 - [36]일차
🚀36일차에는 스프링 MVC에 대해서 더 자세히 알아보고 스프링 MVC의 동작 흐름에 대해서도 공부할 수 있었다.
템플릿엔진인 타임리프를 통해서도 동적으로 페이지에 접근할 수 있는 방법 또한 실습해볼 수 있었다.실습 위주 진행하여 이론에 대해서 자세히 알아볼 수 없는데 회고를 통해 이론에 대해서도 정리해봐야겠다.
Weaving
- AOP 용어 중 Weaving(위빙)은
Advice(부가기능) + Target(핵심 기능)을 결합하여 실행될 프로그램을 구성하는 과정을 의미 - 코드의 실행흐름에 따라 특정 시점에 “부가적인 동작”을 삽입하여 동작하도록 만듦
Proxy를 통한 Weaving
- 과정:
1. Proxy 생성 = Target 객체를 감싸는 Proxy객체가 생성
2. Advice 실행 = Proxy 객체는 메소드 호출 시 먼저 Advice를 실행하고 필요에 따라 Target의 실제 메소드를 호출
3. 결과 반환 = Target 실제 메소드의 결과를 Advice가 가공하거나 그대로 반환 - 즉 Advice 적용 전에는 Target의 메소드를 직접 호출했지만
1. Advice 적용 후(Spring AOP 사용 후)에는 프록시 생성
2. 메소드 호출 시 Proxy가 먼저 실행되어
3. 로그 출력 후
4. 실제 메소드가 실행 - Proxy를 사용한 Weaving은 런타임(실행 시)에 이루어지며 Proxy가 Target객체를 감싸서 추가 동작을 실행
Servlet
- 서블릿 : 자바에서 웹의 요청을 받아낼 수 있는 유일한 기술
- Servlet은 자바가 제공하는 HTTPServlet 클래스가 존재함
- 톰캣은 WAS(웹 애플리케이션 서버)이다.
- Servlet은 main메소드가 없기때문에 시작점이 없어서 "단독으로 동작하지 못한다"
반면 WAS(ex.톰캣)는 시작점을 가지고 있다.
JSP
- JavaServer Pages의 약어로 "서버 사이드 기술"
- 자바 코드를 HTML에 삽입하여 서버에서 동적으로 HTML을 생성해 클라이언트에게 전송
➡️즉 JSP는 서버에서 실행되어 (자바코드 > HTML)로 변환하여 클라이언트에게 전송하는 것 - JSP는 HTML 안에 자바코드를 작성한다. <% %> 태그를 사용
❓JSP vs JSX의 차이
💡JSP
▶️실습 - JSP 구조
// JSP문법
<%@ page language="java" contentType="text/html: charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> JSP TEST </title>
</head>
<body>
<% int age = 50; %>
<%
out.println("나이는 " + age + "살입니다. <br>");
%>
</body>
</html>
- HTML 태그와 유사하지만 page language=”java” 처럼 자바임을 미리 명시
- 또한 <body>태그 안에서 <% %> 안에 자바 코드를 사용한다,
- 즉 JSP안에 자바코드와 HTML태그가 섞여있는 것이다.
▶️실습 - JSP문법 + 서블릿
// [변환 전] : JSP문법
<html>
<body>
<h1>현재 시간: <%= new java.util.Date() %></h1>
</body>
</html>
// [변환 후] : 서블릿 (자바 클래스)
out.print("<html><body>");
out.print("<h1>현재 시간: " + new java.util.Date() + "</h1>");
out.print("</body></html>");
- 서버가 JSP코드를 서블릿으로 변환하여 그 변환된 것을 기반으로 HTML 페이지를 생성해 클라이언트로 전송하는 것
- JSP 흐름에서는 네트워크 통로가 열려 HTML문서를 응답으로 전송할때
HTML 자체를 만들어서 보내게되면 “정적인 화면”밖에 응답할 수 없을 것이다. - 이러한 문제를 해결하기위해 도입된 개념이 JSP인 것
💡JSX
// [변환 전] : JSX문법
const element = <h1>Hello, World!</h1>;
// [변환 후] : Javascript문법
const element = React.createElement('h1', null, 'Hello, World!');
- 리액트의 JSX(Javascript XML)는 HTML과 비슷한 문법으로 작성하여도
최종적으로 자바스크립트 코드로의 변환을 도와줌
➡️Babel 컴파일러를 통해 변환
⭐정리하자면
JSP는 서버에서 실행되는 위치를 가지며 JSX는 클라이언트 단(브라우저)에서 실행되는 위치를 가진다.
JSP + MVC패턴
- 사용자의 요청을 받은 서블릿(Controller), DB(Model)에서 요청 처리 후, JSP(View)에 보여주는 과정이
JSP에 MVC패턴이 적용된 것이라고 볼 수 있다. - Spring MVC에서 Model 1과 Model 2가 있는데 Model 2를 적용한다.
➡️Model 2에서 서버에 들어오는 요청 입구를 하나로 만드는 "FrontController"가 큰 핵심
- ex. 클라이언트의 회원가입 요청과 회원목록 리스트 요청 2가지 요청이 있다고 가정했을때
⚠️회원가입 요청은 A서블릿이 받고 회원목록 리스트 요청은 B서블릿이 받아서 처리하는 방식은 Model 2가 아님
➡️요청 입구를 하나만 만들어서 클라이언트의 각 요청을 모두 하나의 서블릿이 받는 것이 Model 2 방식인 것 - 입구를 단일화시켜서 보안 성능을 향상시킬 수 있다.
- 유지보수가 필요없는 소규모의 프로젝트에서는 Model 1 을 적용해도되지만
유지보수가 필요한 프로젝트에서는 Model 2를 적용해야할 것이다.
Model 1
- JSP에서 직접 클라이언트 요청을 처리
- 비즈니스 로직과 View 로직이 혼합된 구조
- 동작 과정 : 클라이언트 → JSP → 응답
- 장점 : JSP가 요청을 받아 데이터 처리와 화면 렌더링을 동시에 수행하므로 간단
- 단점 : 비즈니스 로직과 View 로직이 혼합되어 변경이 어렵고, 유지보수와 테스트 또한 어려움
Model 2
- 요청 처리를 담당하는 컨트롤러(Controller)를 추가하여 역할을 분리한 구조
- 컨트롤러가 클라이언트 요청을 받아 비즈니스 로직과 View 로직을 분리
- 동작 과정 : 클라이언트 → Controller(DispatcherServlet) → Model(Service, DAO) → View(JSP)
- 장점 : 컨트롤러, 모델, 뷰가 각각 역할 분담하여 유지보수와 테스트가 쉬움
❓Model 2에서의 DispatcherServlet 역할
- 클라이언트의 모든 요청을 하나의 입구로 받아와 요청에 적합한 컨트롤러로 전달하여 역할을 분리
- Model 2의 기본 원칙인 로직과 UI를 분리
Spring MVC
- 모델-뷰-컨트롤러로 나눈 패턴을 기반으로 하는 웹 애플리케이션 프레임워크
- Model : 데이터와 비즈니스 로직을 처리
- View : 사용자 인터페이스를 담당
- Controller : 사용자 입력과 모델의 상호작용을 관리
- Spring의 의존성 주입과 AOP를 통해 애플리케이션 구성 요소를 모듈화하고 관리 가능
➡️애플리케이션의 유지보수성과 확장성이 향상 - 양방향 데이터 바인딩
➡️Spring MVC는 form태그 라이브러리를 사용하여 데이터를 자동으로 바인딩 및 쉽게 유효성 검사를 적용 가능
(모델 객체 ↔ HTML 폼 요소 간)
❓Domain
개발에서의 도메인은 "소프트웨어가 해결하고자 하는 문제의 영역"으로
소프트웨어 개발에서 (요구사항, 문제 영역, 전문 용어 등)을 포함
ex. 쇼핑몰 개발 시 (게시글, 댓글, 결제, 정산 등) = 도메인
도메인 활용 설계 방법은 DDD (=Domain-Driven Design, 도메인 주도 설계)가 있고
이는 도메인 간의 상호작용을 설계의 중심에 두고 설계함
Spring MVC 사용 방법
- @Controller, @RestController 애노테이션을 통해 HTTP 요청 처리 클래스 정의 가능
- @RequestMapping 애노테이션 사용
➡️사용자의 요청 URL을 처리할 수 있는 메소드에 “매핑”하고 다양한 HTTP 메소드 (GET, POST 등)을 처리 가능
Spring MVC 구조
- DispatcherServlet, ModelAndView(Model과 View가 함께 추상화된 객체), ViewResolver 등이 핵심 구성요소
- Front Controller
➡️일반적으로 DispatcherServlet을 의미
모든 요청을 적절한 핸들러나 컨트롤러로 라우팅하는 중앙 집중식 컨트롤러 - Controller
➡️요청을 받아서 필요한데이터를 처리하고 비즈니스 로직을 실행한다음 결과 데이터는 Model객체에 저장 - View Template
➡️대표적으로 JSP나 Thymeleaf가 있고 Model 데이터를 사용하여
최종 사용자에게 보여줄 HTML페이지 등의 “응답을 생성”
Spring MVC 동작 흐름
- Request : 모든 클라이언트 요청은 Model 2에 따라 하나의 입구를 가지고 Dispatcher Servlet으로 들어온다.
- Handler Mapping
➡️Dispatcher Servlet은 Handler Mapping을 사용하여 해당 요청을 처리할 적합한 컨트롤러(Handler)를 찾음 - Handler Adapter
➡️선택된 컨트롤러를 실행할 수 있게하는 Adapter로, 실제 컨트롤러가 실행되도록 중간에서 조정하는 역할수행 - Controller
➡️실제 비즈니스 로직을 처리하는 컨트롤러가 요청을 받아 처리
DB접근이 필요한 작업은 Repository를 통해 수행되고
데이터 접근은 Service 계층(비즈니스 로직)을 통해서도 이루어질 수 있음 - Model
➡️Controller가 생성한 Model은 데이터를 포함하고있고, View를 통해 데이터가 사용자에게 표시됨 - View Resolver
➡️컨트롤러에서 반환된 View 이름을 바탕으로 실제 View 객체를 찾아내는 역할 수행
(View 이름을 통해 실제 렌더링 될 View객체를 찾아내고 결정) - Response : 최종적으로 생성된 View가 클라이언트에게 응답으로 반환
❓라우팅 Routing
➡️ 클라이언트 요청 URL과 매핑된 컨트롤러(Handler)를 찾아 그 요청을 전달하는 과정
ex. Spring에서는 DispatcherServlet이 URL패턴에 따라 요청을 적절한 컨트롤러로 전달하는 과정을 의미
@Controller
public class ProductController {
@RequestMapping("/storePage")
public String getProducts(Model model) {
model.addAttribute("productList", List.of("Laptop", "Smartphone"));
return "products";
}
}
- 라우팅 과정:
1. 클라이언트가 http://localhost:8080/storePage로 요청을 보냄
2. DispatcherServlet이 요청 URL을 분석
3. URL이 @RequestMapping("/storePage")로 매핑된 @Controller를 찾음
4. 찾은 @Controller의 메서드가 실행 (ex. getProducts(Model model)) - DispatcherServlet이 /storePage URL요청을 ProductController의 getProducts(Model model) 메서드로 전달
❓포워딩 forwarding
- 컨트롤러에서 처리한 결과를 View로 전달하여 클라이언트에게 응답하도록 하는 과정을 의미
내부적으로 다른 리소스(JSP 파일 등)로 요청을 넘겨 실행되지만, 클라이언트는 이 과정을 알지 못함
@Controller
public class ProductController {
@RequestMapping("/storePage")
public String getProducts(Model model) {
model.addAttribute("productList", List.of("Laptop", "Smartphone"));
return "products";
}
}
- 포워딩 과정 :
1. 클라이언트가 http://localhostL8080/storePage로 요청을 보냄
2. 컨트롤러에서 데이터를 준비
3. DispatcherServlet이 준비된 데이터를 특정 JSP 파일(ex. products.jsp)에 전달
4. JSP가 HTML을 생성해 클라이언트에게 반환 - return "products";
➡️뷰 이름(View Name)을 반환, Spring의 ViewResolver가 이를 JSP 파일로 매핑해 결과를 클라이언트에게 보냄 - 클라이언트가 처음에 요청했던 HttpServletRequest 객체가 변경되지 않고 그대로 유지되어 전달된다.
서버 내부적으로 수행하여 클라이언트는 객체가 변경되었는지 안되었는지는 알지 못한다.
ex. 작업 명령을 A와 B에게 내렸지만 B만 수행하여도 결국 작업은 수행한 것이므로 누가 수행했는지는 중요치않음 - 활용 :
- 요청된 데이터를 다른 서블릿이나 JSP로 넘겨야 할 때 사용
- 로그인 성공 시, 사용자 정보를 JSP에 표시해야 할 때
❓리다이렉트 Redirect
- 클라이언트에게 HTTP 응답을 보내 브라우저가 다른 URL로 새로 요청하도록 지시하는 과정
브라우저가 요청을 새로 보내기 때문에 요청이 변경된 것을 클라이언트가 인지 가능
@RequestMapping("/login")
public String login(Model model) {
// 로그인 성공
return "redirect:/dashboard";
}
- 리다이렉트 과정 :
1. 클라이언트가 /login으로 로그인을 요청
2. 로그인 인증이 성공하면 서버가 /dashboard로 리다이렉트 요청
3. 클라이언트가 /dashboard로 새 요청을 보내게됨
➡️redirect:
dashboard URL로 새로 요청을 보낼 수 있게함
정리하자면
라우팅 | 요청 URL을 분석하고 적절한 컨트롤러를 호출 | 사용자가 인지하지 못함 | /products → Controller |
포워딩 | 처리 결과를 View로 전달해 최종 응답을 생성 | 사용자가 인지하지 못함 | Controller → JSP |
리다이렉트 | 클라이언트에게 새로운 URL로 요청 지시 | 새 요청 발생을 사용자가 인지 | /login → /dashboard |
HandlerMapping
- DispatcherServlet이 URL과 컨트롤러 메서드를 매핑할 때 사용
- 스프링에서 @RequestMapping, @GetMapping 등 어노테이션이 매핑 규칙 정의
- @Controller 어노테이션이 붙은 컨트롤러 중 적합한 컨트롤러 클래스를 찾아 해당하는 메소드까지 매핑
ViewResolver
- 컨트롤러가 반환한 뷰 이름을 실제 뷰(JSP, Thymeleaf 등)의 파일로 매핑
- ex. return "products"; 을 /WEB-INF/views/products.jsp 파일로 변환하는 것
Model
- 데이터를 View로 전달하기 위해 사용되는 객체
- ex. model.addAttribute("key", value);
스프링 MVC는 WAS(Web Application Server)가 없으면 요청을 받아도 응답시켜줄 수가 없음
WAS (Web Application Server)의 역할
- 내부적으로 클라이언트의 요청과 함께 들어온 정보들(ID, 비밀번호 등)을 추상화 시킨
HttpServletRequest(요청관련) 객체와 HttpServletResponse(응답관련) 객체를 갖고 있음
➡️ex. 사용자가 로그인 요청(ID, 패스워드 정보)을 했을때 HttpServletRequest 요청관련 객체가 갖고 있는 것 - 요청이 들어오면 HttpServletRequest 객체가 생성되는 것
❓HttpServletRequest 객체
➡️ 자바가 제공하는 객체이며, 다른 API에 종속되는 것을 원하지 않는 스프링의 POJO기반 특성으로
사용자가 컨트롤러한테 Request에 직접 접근해서 사용하는 것을 배제시키고
스프링이 HttpServeltRequest, HttpServletResponse 객체 등을 활용하여 대신하는 것이다.
과정 :
- 컨트롤러를 통해 데이터를 받아온 HttpServletResponse 객체는 데이터를 DispatcherServlet에 전달
- 하지만 이 데이터를 View에서 사용하지는 못함 ➡️메모리 영역이 다르기때문
➡️해결방법 : 두 객체(View와 DispatcherServlet)가 접근가능한 공간(=데이터가 유지되는 공간)이 있어야함
데이터 유지되는 영역
1. Page Scope
- 페이지 영역, 자기 페이지에서 선언한 것은 자기 페이지에서만 사용할 수 있는 범위
2. Request Scope
- 요청 영역, 요청이 들어오고 나갈때까지 HttpServletRequest 요청 객체에게 맡김
- View에서는 데이터를 HttpServletRequest 객체로부터 가져오게됨
- 응답이 나간 후에는 소멸되므로 상태유지가 되지 않는다는 단점
3. Session Scope
- 세션 영역, Request Scope가 상태유지가 되지 않아 요청 객체를 유지하지 못하는 문제를 해결하기 위한 영역
- 내부적으로 세션 객체 생성 후 세션 종료까지는 메모리에 요청 객체가 존재함
- 요청이 바뀌었을때에도 유지해야하는 정보가 있다면 Session Scope에 맡기면 된다는 것
- ex. 리다이렉트에서 요청 객체가 새롭게 생성되므로, 요청한 객체의 데이터를 유지하려면 세션 영역에 저장해야함
➡️따라서 리다이렉트에서 세션 영역을 자주 사용 - 단점 :
1. 세션 데이터가 서버 메모리에 저장되기때문에 세션이 많아지면 서버의 부담이 증가함
2. 세션 ID 관리가 취약하면 사용자의 세션 데이터가 노출될 수 있어 보안이 위험할 수 있음
➡️해결방법 : HTTPS 사용 및 세션 ID를 주기적으로 갱신
스프링은 클라이언트가 데이터에 직접 접근하는 것을 방지하기 위해
값을 저장하는 객체인 Model 객체를 만들고 Model 객체에 데이터를 맡겨주어 관리됨
4. Application Scope
- 웹 애플리케이션이 종료될때까지 사용 가능
Lombok
- 개발자가 계속 작성하기 번거로운 코드들을 자동화해주는 자바의 라이브러리
compileOnly 'org.projectlombok:lombok'
- 의존성 추가
@Getter
@Setter
@ToString
@EqualsAndHashCode
public class Book {
private String title;
private int price;
}
public class BookTest {
public static void main(String[] args) {
Book book = new Book();
book.setPrice(3000);
book.getPrice();
book.setTitle("java");
System.out.println(book);
}
}
- Lombok이 컴파일 시점에 Getter,Setter, toString오버라이딩, equals 오버라이딩 메소드 등을 자동으로 추가시켜줌
- Lombok을 통해 어노테이션만 써주어도 모든 메소드가 잘 동작
▶️실습 - 사용자 정의 컨트롤러
@Controller
public class MyController {
@GetMapping("/home")
public String home(){
return "home";
}
}
- @Controller
➡️컨트롤러임을 명시
➡️명시하는 이유 : Bean을 등록하는 것과 정보들을 등록하기 위함 - @GetMapping(”/home”)
➡️URL로 /home을 뒤에 붙여 요청하면 "home"이 리턴될 것
@RestController에서는 화면에 "home" 텍스트를 그려냈지만 @Controller는 다르게 동작하여 오류 발생
- 동작 과정 :
1. DispatcherServlet이 HandlerAdapter를 통해 MyController 클래스에 접근
2. MyController 클래스의 home()메소드를 호출
3. return “home”; ➡️ View Name을 의미 (Controller가 Handler Adapter에게 전달)
4. @Controller 어노테이션을 사용하면 View가 만들어져있지 않아서 오류가 발생하는 것 - 정리하자면 @Controller는 화면으로 응답하는 것, @RestController는 데이터로 응답하는 것
따라서 @RestController는 데이터로 응답하기때문에 바로 화면에 출력을 할 수 있었던 것
❓@Controller와 @RestController의 차이점
➡️@Controller
- 화면(View)을 반환.
- 메소드 반환값 = ViewResolver를 통해 View Name으로 처리
ex. return "home"; 을 하게되면 ViewResolver가 home.html이라는 템플릿 파일을 찾아서 렌더링하는 것
- 주로 정적인 HTML 페이지나 템플릿 엔진(ex. Thymeleaf)과 함께 사용할때 적합
- 과정 :
1. DispatcherServlet (Front Controller)가 클라이언트 요청을 받음
2. HandlerMapping (요청 URL 을 통해 적합한 Controller의 메소드를 매핑함)
3. HandlerAdapter (컨트롤러 호출)
4. Controller의 메서드 실행 (return "home")
5. ViewResolver (View 이름을 통해 View 객체를 매핑)
6. View 렌더링 (Thymeleaf 등의 템플릿 엔진을 통해 템플릿 처리 후 HTML형태로 응답을 반환)
7. 클라이언트에게 HTML 전송
정리하자면
@Controller의 메소드가 문자열로 return "home"처럼 View의 이름을 반환하면 Spring은 ViewResolver를 통해 이 View의 이름에 해당하는 파일을 (일반적으로 resources/templates 경로에서) 찾는데 파일이 없는 경우 오류가 발생
➡️@RestController
- 데이터를 반환.
- @Controller와 다르게 @ResponseBody가 포함되어 있어 메서드의 반환값이 JSON, XML 등의 데이터로 바로 변환
- ex. return Map.of("key", "value"); 처럼 JSON 응답이 클라이언트로 전송됨
- 주로 API 서버 구현에 적합
- 과정 :
1. DispatcherServlet (Front Controller)가 클라이언트 요청을 받음
2. HandlerMapping (요청 URL 을 통해 적합한 Controller의 메소드를 매핑함)
3. HandlerAdapter (컨트롤러 호출)
4. RestController의 메소드 실행 (return "home")
5. HttpMessageConverter (데이터를 JSON으로 변환)
6. 클라이언트에게 JSON 응답을 전송
Thymeleaf
- 기본 설정으로 Prefix, Suffix 등을 가짐으로써 넘어온 정보의 앞이나 뒤 부분에 어떤 정보를 가져갈지를 결정
▶️실습 - (resources/templates)에 "home.html" 파일을 만들기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>home</title>
</head>
<body>
<h1>Hello Home</h1>
</body>
</html>
- localhost:8080/home 접속 후 결과 확인
- @Controller가 View 이름을 반환했음에도 View가 만들어지지 않았던 문제를
View의 이름에 해당하는 View를 직접 만들어서 해결하였음
⭐정리하자면
컨트롤러가 "home"이라는 문자열을 반환하면 ThymeleafViewResolver는 home.html 혹은 home.xhtml 파일을 찾아
해당 내용을 렌더링 하게되는 것
- ⚠️만약 A Controller에 @GetMapping(”/home”)이 있고 B Controller @GetMapping(”/home”)이 있으면 오류 발생
➡️같은 URL을 사용하지 못하며, 둘 중 하나의 컨트롤러의 URL을 바꿔주어야 충돌하지 않는다.
▶️실습 - URL로 값 전달
1번방법. @RequestMapping
@RequestMapping(value = “/URL”, method = RequestMethod.GET)
2번방법. @GetMapping
@GetMapping("/home")
public String home(){
return "home";
}
이 두 코드는 같은 동작을 수행한다.
사용자의 요청을 받을때마다 사용자의 요청정보를 전달할 목적으로 생성되는 객체가 Request 객체이고
브라우저에 응답하기 위해서 생성되는 객체가 Response 객체
이 두 객체는 DispatcherServlet에 전달된다.
DispatcherServlet : 스프링 프레임워크가 제공하는 기능으로 모든 웹 요청을 처리하는 "Front Controller"
▶️실습 - 쿼리 문자열 다루기
- 샘플URL : http://localhost:8080/home?name=willian&age=20&phone=01011111111&address=fulham
➡️?name=willian : 쿼리 문자열을 의미
@GetMapping("/home")
public String home(HttpServletRequest request){
String name = request.getParameter("name");
System.out.println(name);
return "home";
}
- getParameter()를 통해 name속성의 값을 가져올 수 있다. ➡️willian 출력
- 이처럼 HttpServletRequest를 받아 직접 사용하는 과정을 좀 더 간단히 사용한다면
@GetMapping("/home")
public String home(@RequestParam("name") String name){
System.out.println(name);
return "home";
}
- @RequestParam : 이 어노테이션을 통해 "name" 속성을 자동으로 찾아준다.
➡️"name"에서 꺼낸 값을 String타입의 변수에 매핑시켜주는 것이기때문에 변수명은 상관없음
▶️실습 - Model 객체 받기
@GetMapping("/contact")
public String contact(@RequestParam("name") String name, Model model){
System.out.println(name);
model.addAttribute("name", name);
return "contact";
}
- model.addAttribute("name", name);
➡️name이라는 key로 name을 맡김 - templates/home.html에서 이름을 출력하도록 할 수 있음
▶️실습 - Thymeleaf 사용
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head>
<meta charset="UTF-8">
<title>contact</title>
</head>
<body>
<h1>contact 페이지입니다.</h1>
<h2>:::템플릿엔진 Thymeleaf 사용:::</h2>
<h3>ViewResolver가 contact.html 템플릿 파일을 찾아서 렌더링</h3>
<h4 th:text=" 'Hello, ' + ${name}+'!!!'">Thymeleaf를 통해 값을 가져와서 동적 텍스트 처리</h4>
</body>
</html>
- HTML에서 Thymeleaf 사용방법 ➡️xmlns:th="http://www.thymeleaf.org/"
- xmlns은 (XML Name Space)의 약어
- 타임리프를 시작할때는 th로 시작
<h4 th:text=" 'Hello, ' + ${name}+'!!!'">Thymeleaf를 통해 값을 가져와서 동적 텍스트 처리</h4>
- 타임리프에서 값을 가져올때 ${ } 로 사용
- 문자열과 구분하기 위해 작은 따옴표를 사용
- ${name}이 키 값으로써 @GetMapping(”/contact”)의 model.addAttribute("name", name) 의 “name”키와 일치해야함
- 기존 "Thymeleaf를 통해 값을 가져와서 동적 텍스트 처리" 텍스트가 Model 객체를 통해 동적으로 변화됨
🚀 회고를 길게 진행하며 큰 범주로 Spring MVC, 라우팅, 데이터 유지 영역, Thymeleaf 등 개념을 더 이해할 수 있었다.
오늘 수업에서 진행한 예시코드와 함께 다양한 예시코드를 검색해보면서 동작 흐름과 처리 과정을 이해할 수 있게되었다.
'Recording > 멋쟁이사자처럼 BE 13기' 카테고리의 다른 글
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_38일차_"스프링 포워딩/리다이렉팅" (2) | 2025.01.24 |
---|---|
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_37일차_"스프링 Thymeleaf" (1) | 2025.01.23 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_35일차_"스프링 AOP" (1) | 2025.01.21 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_34일차_"스프링 Optional, Annotation" (1) | 2025.01.20 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_33일차_"스프링 DI/IoC" (1) | 2025.01.17 |