mojo's Blog
스프링 웹 개발 기초 본문
정적 컨텐츠
1. static 폴더 아래에 hello-static.html 파일을 만든다.
2. 아래와 같이 hello-static.html 파일에 코드를 작성한다.
<!DOCTYPE HTML>
<html>
<head>
<title>hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
정적 컨텐츠 입니다.
</body>
</html>
3. 실행시키고 크롬에 localhost:8080/hello-static.html 을 작성하면 다음과 같이 화면이 나타난다.
정적 컨텐츠의 원리
1. localhost:8080/hello-static 을 크롬에서 치면 내장 톰켓 서버가 요청을 받는다.
그 후에 요청 받은것을 스프링 컨테이너에 넘긴다.
컨트롤러 측에서는 hello-static이 존재하는지 찾는다. (하지만 존재하지 않음)
여기서 알 수 있는 점은 컨트롤러가 우선순위를 갖는다는 것을 알아두자.
2. 그렇다면 내부의 resources 안에 있는 static/hello-static.html 이 존재하는지 찾는다.
위에서 resources 폴더 아래의 static 폴더에 hello-static.html 파일을 작성하였기 때문에 존재한다.
따라서 이를 반환하여 웹 브라우저에 화면이 나타나게 되는 것이다.
만약 controller 에 @GetMapping("hello-static.html") 에 대한 메서드를 생성한다면?
=> hello-static.html 은 static 폴더 아래에 있으므로 에러가 발생한다.
해결 방법은 template 아래에 hello-static.html 을 새로 생성하여 실행 가능하도록 할 수 있다.
@GetMapping("hello-static.html") 을 추가하여 실행한 경우
@GetMapping("hello-static.html")
public String helloStatic(Model model) {
model.addAttribute("data", "네");
return "hello-static";
}
<!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="'컨트롤러(스프링 컨테이너)에 @GetMapping(hello-static) 이 있을까요? => ' + ${data}">
컨트롤러(스프링 컨테이너)에 @GetMapping(hello-static) 이 있을까요? => 아니오
</p>
</body>
</html>
template 에 있는 hello-static.html 이 실행된 것을 볼 수 있다.
@GetMapping("hello-static.html") 을 주석처리한 경우
이번에는 static 에 있는 hello-static.html 이 실행된 것을 볼 수 있다.
MVC와 템플릿 엔진
MVC란?
Model, View, Controller 를 포함한 것을 MVC 라고 한다.
좀더 자세한 내용은 MVC 패턴의 이해 (tistory.com) 에 정리해뒀었다.
1. hello.hellospring 폴더 아래의 controller 폴더에 HelloController 자바 파일을 형성한 후 다음과 같이 코드를 작성한다.
package hello.hellospring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class HelloController {
@GetMapping("hello")
public String hello(Model model){
model.addAttribute("data", "hello!");
return "hello";
}
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model){
model.addAttribute("name", name);
return "hello-template";
}
}
localhost:8080/hello-mvc 을 크롬에 치면 컨트롤러가 인식하도록 구현하였다.
그런데 이번엔 특별하게 파라메터 "name" 값을 받아오도록 하였다.
예를들어서 localhost:8080/hello-mvc?name=value 을 크롬에 치면 name의 파라미터 값을 value 로 하여 String name 에 name = "value" 가 된다.
2. 이번엔 static 폴더가 아닌 template 폴더 아래에 hello-template.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="'hello ' + ${name}"> hello! empty </p>
</body>
</html>
<p th:text="'hello ' + ${name}"> hello! empty </p> 부분을 살펴보도록 한다.
템플릿엔진을 통해 hello! empty 부분이 "'hello ' + ${name}" 부분으로 치환되는 것으로 이해하면 된다.
그렇다면 hello! empty 를 작성한 이유는?
서버 없이 html 을 만들어서 볼 때 html 을 마크업해주시는 분들이 해당 html 이 제대로 화면에 나오는지를 확인하기 위해 작성해둔 더미용으로 알아두면 될 것 같다.
3. 크롬에 localhost:8080/hello-mvc?name=value 를 검색해보도록 한다.
이때 value 값은 spring! 으로 하고 검색해보도록 하자.
MVC, 템플릿 엔진의 원리
1. 웹 브라우저에서 localhost:8080/hello-mvc 를 띄우면 먼저 내장 톰켓 서버를 거친다.
그리고 내장 톰켓 서버에서는 hello-mvc 가 왔다는 것을 helloController 에 전달한다.
2. helloController 에서 hello-mvc 가 매핑되어있는 것을 인식하게 된다. (@GetMapping("hello-mvc") 로 애너테이션을 작성했기 때문)
이때 model 에는 name에 파라미터로 받아온 value 값을 추가하고 hello-template를 리턴하게 된다.
3. 이때 스프링 내부의 viewResolver 에서 뷰를 찾아주고 템플릿 엔진을 연결시켜주는 역할을 한다.
위에서 리턴값으로 받아온 hello-template를 templates 폴더 내에서 찾고 Tyhmeleaf 템플릿 엔진에게 처리를 넘긴다.
4. 템플릿 엔진이 최종적으로 렌더링하여 변환한 HTML을 웹 브라우저에 나타나게 한다.
정적 컨텐츠와 MVC와 템플릿 엔진의 차이점?
- 정적 컨텐츠 : static 폴더의 html 파일을 변환하지 않고 그대로 웹 브라우저에 넘긴다.
- MVC와 템플릿 엔진 : templates 폴더의 html 파일을 변환 과정을 거친 후 웹 브라우저에 넘긴다.
API
1. HelloController 자바 코드에 다음을 추가한다.
@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name){
return "hello " + name;
}
@ResponseBody 는 html의 body 부분이 아니라 http에서 header와 body 부분이 존재하는데 body 부분에 리턴값을 직접 넣어주는 것을 의미한다.
2. localhost:8080/hello-string?name=spring! 을 크롬에 띄우도록 한다.
3. 코드를 확인해보면 리턴한 "hello spring!" 이 그대로 있는 것을 알 수 있다.
이번엔 실제로 API 방식을 사용하여 데이터를 제공하도록 하는 코드를 직접 작성해보도록 한다.
1. 정적 클래스 Hello 를 만들어준다.
이때 String name 를 선언하고 이에 대한 Getter/Setter 를 만들어준다.
꿀팁!!! "alt + Insert" 버튼을 클릭하여 Getter와 Setter를 쉽게 만들 수 있다.
static class Hello {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
위와 같이 getName(), setName() 이 형성된 것을 알 수 있다.
이러한 것을 자바빈 규격이라고 한다.
2. Hello 객체를 리턴할 수 있도록 하는 helloApi 함수를 작성하도록 한다.
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name){
Hello hello = new Hello();
hello.setName(name);
return hello;
}
3. localhost:8080/hello-api?name=spring! 을 크롬에 띄운다.
json 형식으로 key-value 형태로 "name"과 "spring!" 이 화면에 나타난 것을 알 수 있다.
API 원리
1. 웹 브라우저에서 localhost:8080/hello-api 를 띄우면 먼저 내장 톰켓 서버를 거친다.
그리고 내장 톰켓 서버에서는 hello-appi 가 왔다는 것을 helloController 에 전달한다.
2. helloController 에서 hello-api 가 매핑되어있는 것을 인식하게 된다.
그런데 @ResponseBody 라는 애너테이션이 붙어있는것을 확인하게 되고 http의 응답에 데이터를 그대로 넘겨줘야 하는 것을 인식하게 된다.
3. @ResponseBody 애너테이션을 통해 viewResolver 가 아닌 HttpMessageConverter 로 이동하게 된다.
JsonConverter와 StringConverter가 존재하는데 JsonConverter는 객체에 대한 처리를 하고 StringConverter는 문자열에 대한 처리를 하는 것으로 이해하면 된다.
번외로 기본 객체처리 중에서 'MappingJackson2HttpMessageConvert' 가 존재한다.
4. JsonConverter를 통해 객체를 처리하면 Json 형태로 변환이 되고 이를 웹 브라우저에게 보낸다. (객체가 아닌 문자열일 경우 Json 형태가 아닌 문자열 그대로 변환)
[추가 실습]
이번엔 name, age 를 같이 받아와서 데이터를 제공해보도록 한다.
Hello 클래스는 다음과 같이 만들었다.
public class Hello {
String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
그리고 다음과 같이 @RequestParam 을 두 개 설정하여서 객체를 생성하고 반환한다.
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name,
@RequestParam("age") int age,
Model model) {
Hello hello = new Hello();
hello.setName(name);
hello.setAge(age);
return hello;
}
위와 같이 변경하여 실행한 결과는 아래와 같다.
'Spring' 카테고리의 다른 글
스프링 빈과 의존관계 (0) | 2022.01.12 |
---|---|
회원 관리 - 백엔드 개발 (0) | 2022.01.12 |
IntelliJ로 프로젝트 생성 및 view 환경설정 (0) | 2022.01.10 |
스프링 기반 뉴스 기사 관리 웹 서비스 (0) | 2022.01.07 |
스프링 MVC 컨트롤러 및 RestController 구현 (0) | 2022.01.07 |