✋ 정적 컨텐츠란?
- 클라이언트의 요청을 받고 서버에 미리 저장된 HTML, CSS, JS 등의 파일을 그대로 응답해 보여주는 것을 말합니다.
- 모든 클라이언트들의 요청에 대해 동일한 결과를 보여줍니다.
스프링 부트는 기본적으로 정적 컨텐츠 기능을 제공하므로 /main/resources/static
하위에 hello-static.html
파일을 생성하고 다음과 같이 작성해줍니다.
hello-static.html
<!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>
클라이언트로부터 localhost:8080/hello-static.html
요청이 들어오게 되면 우선 Tomcat 서버를 거치고 그 다음 컨트롤러에서 hello-static
에 매핑하는 동작이있는지 확인합니다.
이후 해당 동작이 없을 경우 /resources/static
하위에서 해당하는 파일을 찾아 반환해줍니다.
프로젝트를 실행시키고 localhost:8080/hello-static.html 링크를 통해서 요청한 정적 컨텐츠를 확인할 수 있습니다.
✋ 동적 컨텐츠란?
- 어떤 클라이언트가 언제, 어디서, 어떻게 서버에 요청했는지에 따라 각기 다른 결과를 보여줍니다.
- MVC와 템플릿 엔진을 사용하는 방식과 API를 사용하는 방식으로 나뉩니다.
MVC 패턴을 이용해 Model, View, Cotroller로 나누어 웹을 개발하면 클라이언트가 서버에 웹 문서를 요청할 경우, HTML을 동적으로 바꾸어 응답해줍니다.
- Model: 데이터와 비즈니스 로직을 관리합니다.
- View: 레이아웃과 화면을 처리합니다.
- Controller: 명령을 모델과 뷰 부분으로 라우팅합니다.
자, 그럼 MVC와 템플릿 엔진을 이용해서 간단한 웹페이지를 만들어보기 위해 우선 HelloController
에 "hello-mvc"
라는 요청이 들어왔을 경우 동작하는 다음과 같은 메소드를 작성해줍니다.
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model) {
model.addAttribute("name", name);
return "hello-template";
}
@GetMapping("hello-mvc")
는 /hello-mvc 와 같은 GET 요청이 들어오면 helloMvc()
메소드를 호출해줍니다.helloMvc()
메소드의 파라미터값으로 @RequestParam
어노테이션을 넣어서 클라이언트가 요청한 URL의 쿼리 파라미터에 대한 값을 받아올 수 있습니다.@RequestParam("가져올 데이터의 이름") [데이터타입] [가져온 데이터를 담을 변수]
addAttribute()
메소드를 이용하여 View에 전달할 데이터를 key, value 형태로 model
에 저장합니다."hello-template"
를 반환하면 뷰 리졸버가 해당 템플릿을 찾아서 Thymeleaf에게 처리해달라고 넘기고, Thymeleaf는 model
에 저장된 데이터를 가져와 값을 변환하고 변환된 HTML을 웹 브라우저에게 반환합니다.HTML 파일은 hello-template.html
이라는 이름으로 /resources/templates
하위에 생성하고 다음과 같이 작성해주었습니다.
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>
작성된 프로젝트를 실행시키고 localhost:8080/hello-mvc?name=Gerry 와 같이 /hello-mvc
요청 뒤에 ?name=Gerry
라고 쿼리 파리미터를 넣어주면 전달받은 데이터를 모델에 저장하고 화면에 출력시킵니다.
- 서버에 요청이 들어오면 뷰를 거치지 않고 컨트롤러에서 직접 JSON 형식의 데이터를 클라이언트에게 리턴해줍니다.
- 주로 React단에서 화면을 그리는 것과 같이 다른 애플리케이션을 통해 웹 문서를 재생성하여 제공할 때 사용됩니다.
첫번째로는 그냥 문자를 반환해주는 코드를 작성해보겠습니다.
HelloController
에 "hello-string"
라는 요청이 들어왔을 경우 동작하는 메소드를 작성해줍니다.
@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name) {
return "hello " + name;
}
@ResponseBody
어노테이션을 적어주면 위와 같이 viewResolver
를 거쳐 View 템플릿을 찾아 반환해주는 것이 아니라, viewResolver
대신에 HttpMessageConverter
가 동작해서 반환한 문자 또는 객체를 처리한 후 클라이언트에게 리턴합니다.@ResponseBody
에서의 'Body'는 반환값을 HTTP요청의 바디내용으로 매핑하여 클라이언트에게 전송하는 것을 의미합니다./hello-string?name=Spring!! 링크로 /hello-string
요청을 Spring!!
이라는 파라미터와 같이 보내게 되면, 아래처럼 페이지에 해당 문자값이 반환되어 있습니다.
개발자도구를 열어서 한번 살펴보면 View 템플릿(HTML 문서)에 문자값이 적혀있는 것이 아니라 오직 문자값만 반환된것을 확인할 수 있습니다.
두번째로는 주로 사용되는 방식인 객체를 반환하는 코드를 작성해보겠습니다.
HelloController
에 "hello-api"
라는 요청이 들어왔을 경우 동작하는 메소드와 Hello 객체를 작성해줍니다.
@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;
}
}
helloApi()
메소드가 실행되면 hello
라는 객체를 새로 생성하고 setName()
을 통해서 파라미터로 전달받은 값을 이름으로 설정합니다.hello
객체를 반환합니다./hello-api?name=Spring!! 링크로 /hello-api
요청을 Spring!!
이라는 파라미터와 같이 보내게 되면, 반환된 객체가 MappingJackson2HttpMessageConverter
를 통해 JSON 형식으로 변환되어 아래처럼 출력된 것을 확인할 수 있습니다.
⚠️ MVC 방식과 RESTful API 방식의 차이점
- MVC 방식은
DispatcherServlet
을 거치고viewResolver
를 통해 View로 결과를 보여줍니다.- RESTful API 방식은
DispatcherServlet
을 거치지 않고HttpMessageConverter
를 통해 형식만 변환해서(주로 JSON형식) 데이터를 넘겨줍니다.
🙏 이 포스트는 김영한 개발자님의 <스프링 입문 강의> 를 듣고 공부한 내용을 바탕으로 작성되었습니다.
감사합니다..!