*inflearn 김영한님의 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
웹 개발은 크게 3가지 방법 있다.
1. 정적 컨텐츠
서버에서 뭐 하는 거 없이 파일을 그대로 web browser에 보여주는 것.
2. MVC와 템플릿 엔진
가장 많이 하는 방식.
jsp,php같은 것들이 소위 말하는 템플릿 엔진임. html을 그냥 주는 게 아니라 서버에서 프로그래밍해서 html을 동적으로 바꿔주는 걸 템플릿 엔진이라고 하고,
그걸 하기 위해 컨트롤러, 모델, 화면, 해서 Model View Controller = MVC임.
정적컨텐츠는 그냥 파일을 그대로 브라우저에 전달해준다면, 이건 서버에서 HTML을 뭔가 변형해서 바꿔서 전달
3. API
안드나 아이폰클라이언트랑 개발을 해야된다.
과거에는 xml, 요즘은 json이라는 데이터 구조 포멧으로 클라이언트에게 데이터를 전달하는게 API방식
뷰js나 리엑트같은걸 쓸 때도 API로 데이터만 내려주면 화면은 클라이언트가 알아서 그리고 정리하는 방식을 할때도 이 방식 사용함.
서버끼리 통신할때도. 서버끼리는 통신할 때 HTML을 내릴 필요가 없음. 어떤 데이터가 왔다갔다하는지가 중요하기때문에!
정적 컨텐츠
스프링부트 정적 컨텐츠 기능
static아래 htllo-static.html을 생성해준다.
1
2
3
4
5
6
7
8
9
10
|
<!DOCTYPE HTML>
<html>
<head>
<title>static content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
정적 컨텐츠 입니다.
</body>
</html>
|
cs |
이렇게
그리고 실행시켜서, localhost:8080/htllo-static.html 에 접속해보면
잘 실행된다!
☞ 여기 그냥 원하는 file을 넣어주면 된다. 그럼 그대로 브라우저로 띄울 수 있음. 대신 프로그래밍을 할 수는 없음.
이런걸 정적 컨텐츠를 제공하는 기능이라고 한다.
이 원리를 간단히
1. hello-static을 spring controller에서 먼저 찾아봄.(컨트롤러가 우선순위를 먼저 가진다는 뜻!) 근데 없었으니까
2. 내부에서 찾음.
MVC와 템플릿 엔진
과거에는 controller와 view가 따로 분리되지 않았고, view에서 다 했음. : model 1방식
지금은 MVC스타일로 많이하는데
view는 그냥 화면을 그리는데 모든 역량을 집중해줘야됨.
controller는 내부처리, 비즈니스 로직에 집중을 해야한다.
그래서 view와 controller를 쪼개는게 기본이다.
HelloController.java에 GetMapping("hello-mvc")를 추가하자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
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") //웹 어플리케이션에서 /hello라고 들어오면, 이 메소드를 호출해줌
public String hello(Model model){
model.addAttribute("data", "hello!!"); //key:data, value:hello
//value에서 hello가 치환됨.
return "hello";
}
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model){
model.addAttribute("name",name);
return "hello-template";
}
}
|
cs |
그리고 resources > template에 hello-static.html을 추가하자.
1
2
3
4
5
6
7
|
<html xmlns:th="http://www.thymeleaf.org">
<!--타임리프 템플릿 엔진을 써야함! html을 막 바꿔야하니까-->
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>
|
cs |
타임리프의 장점은 html을 서버 없이 파일 자체를 그냥 열어봐도 볼 수 있다는 것인데,
hello-template file을 오른쪽 클릭해서 absolute path 해보자. (ctrl+shift+c)
그리고 주소창에 쳐보면 hello! empty가 나오는 것을 확인할 수 있는데,
1
|
<p th:text="'hello ' + ${name}">hello! empty</p>
|
cs |
여기 hello! empty를 띄워주는 것이다.
나중에 이게 템플릿 엔진으로서 동작이 되면, th:text="'hello ' + ${name}" 이 안의 내용으로 바뀌게된다.
이 상태에서 실행하면 뭔가 오류가 나는데,
인텔리제이 아래 오류를 살펴보면
그렇다고 한다.. name 파라미터가 없다.
.java에
1
2
3
4
5
|
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model){
model.addAttribute("name",name);
return "hello-template";
}
|
cs |
이 부분을 보자. Ctrl+P를 누르면 커맨드 옵션을 볼 수 있다.
여기 required라는 옵션을 볼 수 있는데,
1
2
3
4
5
|
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam(value = "name") String name, Model model){
model.addAttribute("name",name);
return "hello-template";
}
|
cs |
이렇게 value = "name"으로 바꿔주자.
required라는 옵션도 있는데, default값이 true이므로,(윗 사진 참고) 값만이라도 무조건 넘겨야되는거.
required = false를 하면 안넘겨도 된다. 기본이 true이기때문에 값을 넘겨야하는데,
주소창에
http://localhost:8080/hello-mvc?name=spring!
이렇게 적어주면
이렇게 가능한.
http://localhost:8080/hello-mvc?name=spring!
spring이 controller에서
name이 spring으로 바뀜. 그리고 model에 담기고,
hello-template로 넘어가서
이게 model의 key값이 name인거에 가서 값을 꺼내는건데, spring으로 치환해주는 것!
정적일때는 변환하지 않았지만 이런 템플릿에서는 변환이 되어 넘어감.
API 방식
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
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;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
@GetMapping("hello") //웹 어플리케이션에서 /hello라고 들어오면, 이 메소드를 호출해줌
public String hello(Model model){
model.addAttribute("data", "hello!!"); //key:data, value:hello
//value에서 hello가 치환됨.
return "hello";
}
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam(value = "name") String name, Model model){
model.addAttribute("name",name);
return "hello-template";
}
@GetMapping("hello-string")
@ResponseBody
//@ResponseBody:HTML에 나오는 body태그가아니라 http 통신 프로토콜(헤더부분과 바디부분 있음)의
//body에 이 데이터(return "hello "+name)를 직접 넣어주겠다는 방식.
public String helloString(@RequestParam("name") String name){
return "hello "+name; //View이런게 없고 이 문자가 그대로 내려감.
}
}
|
cs |
맨 아래 @GetMapping 추가.
실행 후 http://localhost:8080/hello-string?name=spring!!! 를 입력하면
이렇게 나오는데, 소스보기를 하면 MVC와 달리 진짜 그대로 내린 것을 알 수 있음.
템플릿 엔진은 템플릿이 있어서 그걸 조작하는 방식이고 얘는 그대로 내려준다.
정적 컨텐츠 방식을 제외하면 MVC방식에서 View를 찾아서 템플릿 엔진에서 화면을 렌더링해서 HTML을 넘겨주는 방식이 있고, API방식이 있음.
만약에 문자가아니라 data를 내놓으라고하면,(이것때문에 API방식 많이 씀.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
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;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
@GetMapping("hello") //웹 어플리케이션에서 /hello라고 들어오면, 이 메소드를 호출해줌
public String hello(Model model){
model.addAttribute("data", "hello!!"); //key:data, value:hello
//value에서 hello가 치환됨.
return "hello";
}
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam(value = "name") String name, Model model){
model.addAttribute("name",name);
return "hello-template";
}
@GetMapping("hello-string")
@ResponseBody
//HTML에 나오는 body태그가아니라 http 통신 프로토콜(헤더부분과 바디부분 있음)의 body에
//이 데이터(return "hello "+name)를 직접 넣어주겠다는 방식.
public String helloString(@RequestParam("name") String name){
return "hello "+name; //View이런게 없고 이 문자가 그대로 내려감.
}
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name){
Hello hello = new Hello();
hello.setName(name); //파라미터로 넘어온 name 넣어줌.
return hello; //문자가 아닌 객체를 넘겨줌
}
static class Hello{//static class로 만들면 HelloController이 클래스 안에서 이 클래스를 또 쓸 수 있음.(HelloController.Hello)
//private이니까 외부에서 바로 못꺼냄,
// 라이브러리나 내가 쓸때도 getter setter 메서드를 통해 접근하게 됨.
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
|
cs |
static class Hello를 작성할 때는
Alt+Insert 누르고 getter and setter를 선택해주면 된다. : java bean 표준 규약 / 프로퍼티 접근방식 이라고도 함. (아래 자세히)
java bean 규약
vividswan.github.io/2020/10/08/Java-%EC%9E%90%EB%B0%94%EB%B9%88-%EA%B7%9C%EC%95%BD.html
access property
java bean 규약
vividswan.github.io/2020/10/08/Java-%EC%9E%90%EB%B0%94%EB%B9%88-%EA%B7%9C%EC%95%BD.html
[Java] 자바빈 규약 - TIL Blog💻
자바빈(JavaBean) 자바빈의 사용 이유와 규약을 알아본다. 자바빈의 사용 이유 자바빈을 사용하는 이유는 디자인(프론트엔드)와 로직(백엔드)를 분리하기 위해서이다. JSP, Mustache 등 자바로 만든 서
vividswan.github.io
access property
접근자 프로퍼티(access property)
1. 자바스크립트는 '객체'기반의 스크립트 언어이다. '객체'는 영어로 'Object'이고, 이는 자바스크립트 타입의 거의 대부분을 구성한다. (원시타입 제외) 이러한 자바스크립트의 객체는 키(key)와
navydoc.tistory.com
이렇게해서 돌려보면
이렇게 된다. 소스보기해도 똑같음. 이건 JSON이라는 방식인데, key-value로 이뤄진 구조다. name이 key고 spring이 value.
xml방식은 무겁고 귀찮아서,,, 최근엔 거의 JSON방식으로 통일됨.
spring도 기본이 json으로 반환하는게 default로 세팅되어있음.
동작 방식
spring은 hello-api가 있는데 @ResponseBody라는 어노테이션이 붙어있네?
이전 템플릿에서는 viewResolver한테 던짐 : 나한테 맞는 템플릿 찾아서 돌려줘!인데
얘는 Http 응답에 그대로 데이터를 넘기는 식으로 동작하는데, return한게 문자가 아니라 객체잖아
문자면 그냥 바로 넣어서 주면 끝인데 객체를 반환하면
default인 json방식으로 응답을 만들어서 http응답에 반환하겠다는게 기본 정책임.
@ResponseBody로 왔고, hello객체를 넘기면 이 객체를 보고 몇가지 조건을 보는데
HttpMessageConverter가 동작을 한다. (기존엔 viewResolver, @ResponseBody가 오면 얘 동작)
단순 문자면 StringConverter, 객체면 JsonConverter가 동작한다.
그래서 hello객체를 보니까 name이 있고 값이 있네? 하면서 json 스타일로 바꿈.
바꾼 json을 요청한 웹브라우저든 서버든 보내준다.
- @ResponseBody 를 사용
1) HTTP의 BODY에 문자 내용을 직접 반환 //객체, 문자로 바꿔서 반환해야겠지?
2) viewResolver 대신에 HttpMessageConverter 가 동작 //spring boot에서 등록 해놨음
3) 기본 문자처리: StringHttpMessageConverter
4) 기본 객체처리: MappingJackson2HttpMessageConverter //객체를 json으로 바꿔주는 유명한 라이브러리중 하나가 Jackson,구글에서 만든 Gson이 있는데 spring에서는 Jackson이 기본으로 탑재하도록 설정되어있음. 이 컨버터가 바꾸는 역할을 해준다.
5) byte 처리 등등 기타 여러 HttpMessageConverter가 기본으로 등록되어 있음
*참고 : 클라이언트의 HTTP Accept 해더와 서버의 컨트롤러 반환 타입 정보 둘을 조합해서 HttpMessageConverter 가 선택된다.
정리
*정적 컨텐츠 : 파일을 바로 그냥 내려준다.
*MVC와 템플릿 엔진 : 템플릿 엔진을 Model View Controller 방식으로 쪼개서 View를 템플릿엔진으로 HTML을 프로그래밍 해서 렌더링된 HTML을 클라이언트에 전달.
*API : 일반적으로 spring 개발할때 말하는 API는 객체를 반환하는 것이다.
HttpMessageConverter를 통해 json스타일로 바꿔서 뷰 이런거 없이 바로 http response에다가 딱 값을 넣어서 반환해주는거.