Rev Notebook

[Spring Boot] 1. 정적 컨텐츠, MVC, API

by Rev_

Spring 웹 개발에서 기초적인 개념 3가지로는,

  1. 정적 컨텐츠
  2. MVC와 템플릿엔진
  3. API

가 있다. 3가지 방법으로의 Spring 웹 페이지 동작을 알아보도록 하자.

 

정적 컨텐츠

먼저 정적 컨텐츠는 서버에서 하는 일 없이 그냥 파일을 그대로 보여주는 것이다.

스프링 부트는 정적 컨텐츠 기능을 자동으로 제공한다.

<!DOCTYPE HTML>
<html>
<head>
    <title>static content</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
정적 컨텐츠 입니다.
</body>
</html>

정적 컨텐츠의 실행에는 따로 컨트롤러가 필요하지 않다.

localhost:8080/hello-static.html을 실행하면 html 웹 페이지를 실행할 수 있다.

위와 같은 정적 컨텐츠의 실행과정은 다음과 같다.

  1. 웹 브라우저 -> 서버 localhost:8080/hello-static.html 호출
  2. 스프링 컨테이너에서 hello-static 관련 컨트롤러가 있는지 확인 -> 없음
  3. resources 내의 static/hello-static.html 찾음
  4. 웹 브라우저에 반환

 

MVC와 템플릿 엔진

html을 그냥 주는 것이 아니라 서버에서 동적으로 바꿔주는 것템플릿 엔진이라고 한다.

과거에는 View과 Controller의 구분이 따로 되어있지 않아 View에서 대부분 작업을 했었지만 오늘날에는 명확히 구분되어 있다.

View는 화면을 그리는데에 모든 역량을 집중하고, 비즈니스 로직과 서버 관련은 컨트롤러에서 동작하며, 모델에 화면에 필요한 요소들을 담아둬서 동작한다. 이를 MVC(mddel, view, controller)라고 한다.

@GetMapping("hello-mvc")  // hello-mvc
public String helloMvc(@RequestParam("name") String name, Model model) {
    model.addAttribute("name", name);
    return "hello-template";
}

먼저 컨트롤러의 동작을 알아보자. 

return을 통해 templates에 있는 "hello-template" 파일을 찾는다.

컨트롤러에서 리턴 값으로 변수를 반환하면 viewResolver가 화면을 찾아서 처리한다.

<!--hello-template.html-->
<!--이를 작성해주어야 타임리프 문법이 에러를 일으키지 않고 동작할 수 있음-->
<!--thymeleaf 템플릿 엔진 선언-->
<html xmlns:th="http://www.thymeleaf.org">
<body>
Hello
<!-- 서버가 동작되면 text 요소가 실행 되지만 그냥 타임리프에서 실행하면 hello! empty 가 실행되어
 서버를 실행하지 않고도 html 파일을 볼 수 있음-->
<p th:text="'hello ' + ${name}" >hello! empty</p>
</body>
</html>

hello-template.html 파일이다.

웹 페이지에서 실행할 때에는 p 태그에 있는 name 변수를 받아오기 위해 localhost:8080/hello-mvc?name=spring!를 요청해준다.

spring! 값을 받아와서 화면에 올바르게 나타났다.

 

MVC와 템플릿 엔진의 실행과정은 다음과 같다.

  1. 웹브라우저에서 서버에 localhost:8080/hello-mvc를 넘겨줌
  2. helloController에 매핑이 되어있기 때문에 메서드 호출
  3. return 값은 hello-template, model(name:spring!)으로 넘겨줌
  4. viewResolver 작동 -> templates/hello-template.html을 찾아서 웹 브라우저에 넘김 (Thymeleaf 템플릿 엔진 처리)

Thymeleaf의 장점은 html 파일로만 열어도 오류 없이 열 수 있다는 것이다.

위처럼 서버를 실행하지 않아도 웹 페이지의 껍데기만 열어 볼 수 있다. 대신 hello-template.html 파일에서 받아온 변수 대신 기존에 있던 "hello! empty" 구문이 출력된다.

 

@GetMapping

우리는 GetMapping을 통해 Controller가 특정 View를 반환하도록 만들었다. 이는 무엇을 의미하는 것일까?

@Controller
public class HelloController {
    @GetMapping("hello-mvc")
        public String helloMvc(@RequestParam("name") String name, Model model) {
            model.addAttribute("name", name);
            return "hello-template";
        }
 }

먼저 컨트롤러의 전체적인 구조를 살펴보도록 하자.

해당 자바 클래스가 Controller인지 알려주는 방법은 @Controller를 적어주는 것이다. 그러면 spring이 자동으로 인식하여 작업해준다. 그리고 클래스 안에 @GetMapping("hello-mvc")를 적어줬다. 이는 localhost:8080/hello-mvc 요청이 들어오면 아래의 메서드를 실행하라는 명령이라고 생각하면 된다.

참고로 이 메서드에는 "hello-template"를 리턴하라고 명하고 있다. 그러면 spring이 자동으로 src/main/resources의 templates에서 hello-template라는 이름의 View를 찾아서 반환해준다.

참고로 위에서 배웠듯이 GetMapping 해주는 컨트롤러가 없다면 static에서 찾도록 설계되어 있다.

 

@RequestParam

이는 helloMvc 메서드의 파라미터 값을 얻어오는 역할을 한다.

구조는 @RequestParam("가져올 데이터 이름") [데이터타입] [가져온 데이터를 담을 변수] 로 구성된다.

그리고 뒤의 Model 객체를 이용해서 View로 값을 넘겨주게 된다.

도메인에 값을 넘겨줄 때는 주소창 뒤에 ?로 구분하여 써주고, 여러개의 값을 넘겨줄 때는 &로 구분한다.

 

API

과거에는 xml 데이터를 많이 사용했지만, 최근에는 대부분 JSON을 사용한다.

일단 html 파일을 불러오지 않고 다른 방법으로 데이터를 내려주는 방법을 살펴보자. 

@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name) {
    return "hello " + name;  // "hello spring"
}

이는 html 소스 없이 데이터를 그대로 내려준다.

이 페이지의 소스를 살펴보면 hello spring이라는 텍스트만을 지닌 것을 알 수 있다.

 

그 다음으로 JSON으로 데이터를 얻어오는 방법을 살펴보자.

@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;
    }
}

여기서 localhost:8080/hello-api?name=spring을 받아온다면,

위와 같은 JSON 데이터를 반환하게 된다.

 

@ResponseBody

만일 View 페이지가 아닌 반환값 그대로 전송하고 싶은 경우에 이를 사용한다.

return값은 문자열이 될 수도 있고, 객체를 반환해도 된다. 객체를 반환할 경우에는 json 형태로 반환한다.

따라서 GetMapping("hello-string")에서는 문자열을 반환해주었고, GetMapping("hello-api")에서는 Hello 객체를 생성해주었기 때문에 json 형태로 반환되었다.

 

@ResponseBody 사용 원리는 다음과 같다.

  1. 웹 브라우저에서 localhost:8080/hello-api를 넘겨줌
  2. @ResponseBody를 만나면 http의 body에 문자 내용을 직접 반환
  3. viewResolver 대신 HttpMessageConverter 동작 
    => 만일 문자라면 바로 넘겨주고(StringHttpMessageConverter), 
    응답이 객체라면 json 방식으로 데이터를 만들어서 전달(MappingJackson2HttpMessageConverter)

 

 

[Referance]

김영한님의 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8#

 

https://coding-nyan.tistory.com/71

https://memostack.tistory.com/243

 

블로그의 정보

Hi Rev

Rev_

활동하기