웰컴 페이지는 src > main > resources > static
경로에 index.html 이라는 이름으로 파일을 생성하면 된다. 접속 요청을 받은 페이지를 렌더링할 때 서버가 가장 먼저 html 파일을 찾는 위치가 static 폴더라는 얘기다.
<!DOCTYPE HTML>
<html>
<head>
<title>Hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
Hello
<a href="/hello">hello</a>
</body>
</html>
위 페이지는 정적 페이지이기 때문에 동적인 부분들은 모두 템플릿 엔진을 통해 적용하면 된다.
이를 위해 먼저 컨트롤러를 만든다. 웹 애플리케이션의 진입점은 컨트롤러이다.
📁 HelloController.java
package hello.hello_spring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HelloController {
@GetMapping("hello")
public String hello(Model model) {
model.addAttribute("data", "hello!!");
return "hello";
}
}
- GetMapping("hello"):
/hello
로 접속하면, hello 메서드를 호출한다.- model.addAttribute("data", "hello!!");: 뷰에 전달할 모델에 data라는 키에 hello!!라는 값을 가지는 속성을 추가한다.
- return "hello";: 스프링이 "hello"라는 이름의 템플릿을 찾아 html을 반환한다.
🚨이 모든 것은 Thymeleaf 엔진을 사용하기 때문에 가능 !!🚨
📁 hello.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'안녕하세요. ' + ${data}">안녕하세요. 손님</p>
</body>
</html>
따라서 위와 같은 상황에서 data에 "hello!!" 값이 추가되어, /hello
경로에서는 다음과 같이 보이게 된다.
이 과정을 그림으로 나타내면 다음과 같다.
컨트롤러에서 반환 값으로 문자를 반환하면, viewResolver가 화면을 찾아서 처리한다.
- 정적 컨텐츠: 서버에서 별도의 변환을 거치는 것 없이 파일 그대로 브라우저에 전달하는 것.
- MVC와 템플릿 엔진: 서버 내 프로그래밍을 통해 HTML을 동적으로 변환 후 브라우저에 전달하는 것을
템플릿 엔진
이라고 하며, 이 템플릿 엔진과 모델, 컨트롤러를 합쳐MVC
라고 한다.- API: 클라이언트에게 데이터를 전달할 때 JSON 형식으로 전달하는 방식.
공식 문서를 확인하면, 정적 컨텐츠를 활용하기 위해서는 프로젝트 내 src > main > resources > static
폴더 하위에 파일을 위치시키면 된다. 이 파일에는 내가 원하는 어떠한 컨텐츠든 넣을 수 있지만, 대신 정적 컨텐츠이기 때문에 프로그래밍이 불가능하다.
예를 들어 📁 hello-static.html 이라는 이름의 파일을 만들었다면, 접속할 때도 주소 뒤에 hello-static.html 을 입력해주면 된다.
그럼 이 흐름은 어떤 원리로 구성되어있는 걸까❓
hello-static.html
파일을 찾는다. 찾으면 바로 반환!뷰에 모든 걸 다 때려넣었던(!!) 옛날 방식과 다르게, 뷰는 화면과 관련된 일만을, 컨트롤러는 비즈니스 로직과 서버에 관련된 일들을, 모델은 화면에 관련된 것들을 담아 뷰에 전달하는 일을 담당하는 식으로 관심사를 분리하였다. 이것이 MVC 패턴이다.
위와 같이 컨트롤러에 새로운 기능을 추가하였다.
여기서
RequestParam
은 주소 내 쿼리 스트링을 받을 수 있게 하며, 위 코드에서는 value가 "name"으로 설정된 상태이다. 보이지 않는 설정인 required는 true로 기본 설정되어 있다.
기능 추가 후, localhost:8080/hello-mvc 로 접속하면 에러가 난다. 인수를 받는다고 설정해놓았는데, 쿼리 스트링으로 아무 인수도 전달하지 않았기 때문이다. 따라서 localhost:8080/hello-mvc?name=spring!!!!과 같이, 주소와 함께 원하는 인수를 전달해야 한다.
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>
해당 주소로 접속하면 보여지는 페이지는 함수 helloMvc가 반환하는 📁 hello-template.html 이다. p
태그 내부에 있는 문자열("hello! empty")은 html 파일을 서버의 도움 없이 열었을 때 확인할 수 있는 컨텐츠이다. 일종의 정적 컨텐츠 개념인 것이다. 이는 Thymeleaf 템플릿 엔진이 제공하는 기능이다.
하지만 템플릿 엔진이 동작하면, 정적 컨텐츠는 th:text에 설정한 내용으로 치환이 된다.
따라서 소스코드가 위와 같을 때, 쿼리 스트링으로 전달한 문자열이 변수 name의 값으로 전달되어 페이지는 다음과 같이 보여진다.
여기까지의 동작 방식을 그림으로 나타내면 다음과 같다.