
김영한의 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 강의를 공부하며 작성한 글입니다.
스프링 웹 개발 방식은 3가지로 분류할 수 있다.
└─src
├─main
│ ├─java
│ │ └─com
│ │ └─example
│ │ └─hello_spring
│ │ │ helloSpringApplication.java
│ │ │
│ │ └─Controller
│ │ HelloController.java
│ │
│ └─resources
│ │ application.properties
│ │
│ ├─static
│ │ hello-static.html
│ │ index.html
│ │
│ └─templates
│ hello-template.html
│ hello.html
│
└─test
└─java
└─com
└─example
└─hello_spring
helloSpringApplicationTests.java
스프링 공식 문서에서는 static을 static 디렉토리에서 제공한다고 적혀있다. 📌 스프링 공식문서 링크

hello-static.html
<!DOCTYPE html>
<html>
<head>
<title>static content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
정적 컨텐츠입니다.
</body>
</html>
static 폴더에 hello-static.html 파일을 생성한다.

정적 컨텐츠는 localhost:8080/hello-static.html이라는 파일경로를 적어줘야 웹브라우저에서 확인이 가능하다.
정적 컨텐츠는 넣어준 정적 파일 그대로 웹브라우저에서 반환이 된다.
그래서 동적 프로그래밍을 할 수는 없다.

(강의 교안의 참고자료를 직접 따라 그렸습니다.)
localhost:8080/hello-static.html을 입력하면 내장 톰켓 서버에서 요청을 받고 스프링 컨테이너에게 넘긴다.Controller를 우선 살펴본다. hello-static 와 관련(Mapping) 된 Controller가 없다면 다음 단계로 넘어간다.resources 폴더 내부에 있는 static/hello-static.html을 찾는다. 있다면 웹브라우저에 반환한다.hello-static.html

웹브라우저에서의 hello-static.html

두 코드가 동일한 것을 확인 가능.
예전 Model과 View가 분리되어 있지 않던 개발 방식(Model1 방식)과 달리
요즘에는 MVC 패턴을 이용한 개발이 일반적이다.
Model
Controller
View
HelloController.java
@Controller
public class HelloController {
@GetMapping
public String hello(Model model) {
model.addAttribute("data", "반가워요?!");
return "hello";
}
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model){
model.addAttribute("name", name);
return "hello-template";
}
}
hello-template.html
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${name}">hello! world</p>
</body>
</html>
뷰이다.웹브라우저에 Controller에서 정의한
localhost:8080/hello-mvc 을 입력해본다.

에러가 발생한다. 왜지?

에러 로그는 다음과 같다.
Required request parameter 'name' for method parameter type String is not present
반드시 넘겨줘야할 파라미터가 넘어오지 않았다는 뜻이다.
따라서 웹브라우저에 파라미터를 넘겨준다.
http GET방식에서 파라미터를 넘겨주는 방법은 다음과 같다.
localhost:8080/@GetMapping이름?@RequestParam키값=입력값
다음과 같이 파라미터를 넘겨준다.
localhost:8080/hello-mvc?name=spring!


웹브라우저에 입력한name=spring!식이 넘어가면 Controller에서 name은 입력값인 spring으로 바뀐다. 바뀐 값은 model에 담긴다.
hello-template.html에서의 ${name}은 model에서 키 값이 name인 것을 꺼내 해당 키의 값으로 치환한다는 뜻이다. 따라서 화면에서는 hello 뒤에 입력값이 붙어서 출력된다.

(강의 교안의 참고자료를 직접 따라 그렸습니다.)
localhost:8080/hello-mvc을 입력하면 내장 톰켓 서버에서 요청을 받고 스프링 컨테이너에게 넘긴다.hello-mvc메서드가 HelloController와 Mapping된 것을 발견하고 해당 메서드를 호출한다. 이때, return시 이름은 hello-template, 모델은 name(키값):spring!(밸류)으로 해서 viewResolver에게 넘겨준다.viewResolver가 동작해서 http에게 응답으로 돌려줄 뷰(templates/hello-template.html)를 찾고, 타임리프 템플릿 엔진에게 넘긴다. 정적 컨텐츠와 템플릿 엔진의 차이
정적 컨텐츠 : Html을 변환하는 과정이 없음
템플릿 엔진 : Html을 변환한 뒤 웹 브라우저에 반환
변환 전 hello-template.html

변환 후 hello-template.html

변환 전과 후의 코드가 다르다.
intellij에서 [Ctrl + Shift + c] 를 통해 Apsolute path를 복사한 뒤 웹 브라우저에 주소를 붙여넣으면 파일을 그대로 전달할 수 있다. 이 방법을 통해 서버를 통하지 않아도 HTML파일의 출력화면을 확인할 수 있다.

다만 서버를 통할 때와 서버를 통하지 않을 때 결과로 출력되는 내용은 조금 다르다.
서버를 통하지 않을 때는 hello! empty가 출력되지만
서버를 통해 웹브라우저와 연결한다면 'hello ' + ${name} 가 치환되어 출력될 것이다.

API를 쓰는 가장 큰 이유는 데이터 전송 때문이다.
HelloController.java
@Controller
public class HelloController {
@GetMapping
public String hello (Model model) {
model.addAttribute("data", "반가워요?!");
return "hello";
}
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model){
model.addAttribute("name", name);
return "hello-template";
}
@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name) {
return "hello " + name;
}
}
@ResponseBody란?
- http에는
header 부, body 부가 존재.@ResponseBody는 body 부에 내용을 직접 넣는다는 의미.


실제 브라우저에 hello-stirng에 밸류값을 줘서 호출해보면 화면은 MVC방식과 비슷하게 나온다.
하지만 웹브라우저로 전송된 코드에는 html태그가 하나도 없다.
return으로 반환한 문자가 그대로 출력되는 것이다.
HelloController.java
@Controller
public class HelloController {
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name) {
Hello hello = new Hello();
hello.setName(name);
return hello;
}
static class Hello{
private String name; // 키
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}


API 방식을 통해 객체를 반환하면 브라우저에서는 JSON형식의 코드가 출력된다.
JSON은 {키:밸류}의 구조를 가지고 있다.
html처럼 열고 닫는 구조가 아니기 때문에 html에 비해 단순하고 간단하다.
스프링에서는 @ResponseBody로 객체를 반환할 때, 기본적으로JSON을 반환하도록 세팅되어 있다.
static 클래스 Hello의 name 필드는 private이기 때문에 외부에서 직접 접근할 수 없고 getter, setter를 이용해 접근해야 한다.

(강의 교안의 참고자료를 직접 따라 그렸습니다.)
웹브라우저에서 localhost:8080/hello-api를 입력하면 내장 톰켓 서버에서 요청을 받고 스프링 컨테이너에게 넘긴다.
스프링 컨테이너는 hello-api메서드가 HelloController와 Mapping된 것을 발견하고 해당 메서드를 호출한다. @ResponseBody가 있으므로 http에 대한 응답(return)에 데이터를 바로 넣는다(body에 직접 반환). 단, 데이터가 문자가 아닌 객체일 때는 return시 JSON 방식으로 만들어서 반환한다.
@ResponseBody를 확인하면 HttpMessageConverter가 동작한다.템플릿 엔진과 API의 차이
템플릿 엔진: 뷰(템플릿)을 조작하는 방식. return 발생 시viewResolver동작API: 뷰 없음. 데이터를 그대로 내려준다. return 발생 시HttpMessageConverter동작
정적 컨텐츠 : 파일을 그대로 내려준다.
MVC와 템플릿 엔진 :뷰리졸버가뷰를 찾고,템플릿 엔진으로뷰(HTML)를 랜더링해서 반환
API :HttpMessageConverter를 통해JSON 형식으로 객체를 반환
색인
viewResolver
view를 찾아주고 template에 연결시켜주는 기능을 한다.
Jackson, Gson
객체를 Json으로 변환시켜주는 라이브러리