[Spring 강의 작성] 스프링 웹 개발 방식 3가지 실습
스프링으로 웹개발을 하는 방식은 크게 세 가지가 있다.
- 정적 컨텐츠
-> 이미 정해진 html 그냥 그대로 보여주기
localhost:8080/good.html로 이동할 경우, 스프링부트 내에서 good에 매핑된 controller가 있는지 확인하고,
없으면 resources/static/good.html을 찾아서 보여준다고 보면 된다. - MVC와 템플릿 엔진
-> html을 동적으로 수정하여 보여주기
템플릿 엔진 : php, jsp, 타임리프
Model, View, Controller
View는 보여지는 것에 모두 집중. Controller와 그를 이용하는 Model이 비즈니스 로직을 담당한다. - API
-> 모바일 등 프론트엔드를 구분하여, 다양한 프론트와 통신할 때, 등 데이터 기반으로 통신. 주로 json 포맷을 이용.
-> RESTful 방식을 적용 권장
@Controller + @ResponseBody = @RestController
2, 3번 모두 동적 방식이라고 볼 수 있는데
웹페이지 자체를 보여주게 하느냐, 아니면 데이터를 넘기냐의 차이가 있다.
본격적으로 진행할때에는
RESTful 기반의 웹서버를 구현할 것이지만
그 전에 간단하게 웹뷰를 뿌려주는 방식으로, 템플릿 엔진 타임리프를 이용해 동적인 웹페이지를 생성하여 프론트 단에서 보여주는 방법을 간단하게 다룬다.
타임리프에 대해서 자세히 알고 싶다면 : https://hevton.tistory.com/821
SpringBoot가 제공하는 Welcome page 위치는
src -> resources -> static -> index.html 이다.
static 패키지나 index.html 파일이 없으면 생성해주면 된다.
여기에 이렇게 파일을 만들어주면 스프링부트가 Welcome page의 위치를 이곳으로 인식해서 뿌려준다.
Welcome page란 주소만 입력했을 때 이동하는 곳이다. 기본적으로 주소만 입력할 경우
스프링 부트 내에서 index.html 파일을 찾아서 보여주고, 이것은 웹 서버들의 공통된 약속? 이라고 볼 수 있다.
static 패키지 내의 다양한 파일 (ex. good.html)을 넣고
localhost:8080/good.html 로 이동하면 해당 파일로도 이동할 수 있다.
index.html
<!DOCTYPE HTML>
<html>
<head>
<title>Hello</title>
</head>
<body>
Hi
</body>
</html>
하지만 이러한 방식은, 정적인 웹 사이트 방식이다.
이미 만들어진, 변함없는 html을 매번 똑같이 뿌려주는 방식이다.
그럼 동적인 웹 사이트는 어떻게 만드는가?
바로 템플릿 엔진을 사용한다. 템플릿 엔진에는 타임리프가 있다.
우선, Controller를 만들어준다.
Controller는, 유저의 입력을 어떻게 처리해줄지를 결정하는 공간이라고 생각하면 된다.
package io.spring.hevton.Hello.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) { // mvc 중에 model
model.addAttribute("data", "Good Morning"); // key가 'data', 값은 'Good Morning'
return "hello"; // templates 의 hello.html로 가라는 것. 이 작업은 viewResolver가 찾아서 랜더링을 해준다.
}
}
GetMapping("hello") 이렇게 하게 되면
localhost:8080/hello 로 이동하게 되면 아래 hello 함수가 실행된다.
스프링부트가 Model을 생성해서 함수 인자로 넘겨주게 되고, 우리는 그 model에 attribute를 추가해준다.
key는 "data" 이며, value는 "Good Morning" 으로 넣어주었고
return으로는 "hello"를 넘겨주었다.
여기서 hello의 의미는, resources/templates/hello.html 파일을 찾아서 보여주라는 뜻이다.
따라서 우리는 이 경로에 파일을 생성해준다. ViewResolver가 이런 View를 찾고, 템플릿 엔진을 연결시켜준다.
hello.html
<!DOCTYPE html>
<html xmlns:th="http//www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Hello</title>
<meta http-equiv="Content-Type" content="text.html"; charset="UTF-8"/>
</head>
<body>
<p th:text="'안녕하세요. ' + ${data}">템플릿 엔진으로 동작 안할 땐 이게 보여짐</p>
</body>
</html>
${data} 라고 작성하면, 우리가 model.addAttribute로 넘겨주었던
key : data
value : Good Morning
를 통해, value 값인 Good Morning이 들어가게 된다.
타임리프 템플릿 엔진을 이용해 코드를 작성할 때 장점이 뭐냐면,
템플릿 엔진을 이용해서 보여질 땐 '안녕하세요. ~' 저 부분이 보여지고,
그냥 html 자체를 열 때에는 태그 내의 글자가 보여지게 된다.
이렇게 하고 서버를 재시작한다.
그리고 브라우저에
localhost:8080/hello 로 이동하면
이렇게 페이지를 받아볼 수 있다.
HelloController에 코드를 조금 더 추가해보자.
package io.spring.hevton.Hello.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) { // mvc 중에 model
model.addAttribute("data", "Good Morning"); // key가 'data', 값은 'Good Morning'
return "hello"; // templates 의 hello.html로 가라는 것. 이 작업은 viewResolver가 찾아서 랜더링을 해준다.
}
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model) {
model.addAttribute("name", name);
return "hello-template";
}
}
GetMapping으로 hello-mvc를 추가했다.
우리가 동적으로 페이지를 수정한다고 했는데, data의 value가 계속 Good Morning으로 고정시켜놓았으니
사실상 데이터가 변경되지 않고 있다.
그렇기 때문에 입력에 따라 정말 완벽히 동적으로 하기 위해서, 이 부분을 동적으로 변경해주기 위해
이번엔 @RequestParam을 추가했다. 사용자로부터 name 을 입력받아서 사용하려는 목적이다.
resources/templates/hello-template.html을 만들어준다.
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello, ' + ${name}">템플릿 엔진으로 동작 안할 땐 이게 보여짐</p>
</body>
</html>
이제 서버를 키고, 웹브라우저에 이렇게 입력해보자.
name을 변경함에 따라 동적으로 변경됨을 확인할 수 있다.
+
html 파일을 변경하면, 매번 서버를 재시작해주어야하는데
spring-boot-devtools 라이브러리를 추가하면, 'html' 파일을 컴파일만 해주면 서버 재시작 없이 View 파일 변경이 가능하다.
이번엔 세 번째인 Api방식으로 진행해본다.
이번엔 @GetMapping에 이어서 @ResponseBody를 추가하여, 이렇게 코드를 작성해본다.
@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name) {
return "hello " + name;
}
@ResponseBody는 데이터 그대로 넘겨준다는 특징이 있다. 그래서 이대로 실행해서 웹브라우저에서 소스를 보면
html 태그도 없이 그냥 이 문자, 글자 그대로가 보여지게 된다. Raw하게.
근데 이렇게 사용하려고 @ResponseBody를 사용하진 않는다.
그럼 어떤 이유로 사용할까?
이번엔 코드를 이렇게 작성해본다.
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name) {
Hello hello = new Hello();
hello.setName(name);
return hello;
}
@Getter
@Setter
static class Hello {
private String name;
}
그리고 서버를 실행해서, 브라우저에 다음과 같이 입력해본다.
@ResponseBody 하고 객체를 반환해주면, json 형태로 리턴되는 것을 확인할 수 있다.
@ResponseBody가 사용되면, viewResolver 대신에 HttpMessageConverter가 동작하는데
기본 문자는 StringHttpMessageConverter, 객체는 MappingJackson2HttpMessageConverter가 동작하는데
후자는 객체를 Json 형태로 변환해준다.
요즘에는 이렇게 하기 보다는,
아예 Controller 자체를 @Controller 대신에 @RestController로 하고, 객체를 리턴해주면 동일한 효과를 볼 수 있다.
@Controller + @ResponseBody = @RestController 라서, RESTful 기반 서비스를 구축할 때에는 아예 @RestController를 사용하면 된다.