Spring boot로 HTTP API를 만들기 전에, MVC 구조로 웹 애플리케이션이 어떠한 원리로 만들어지고 동작하는지 이해가 필요합니다.
이번 글에서는 간단한 API 1개와 웹페이지 1개를 만들어보고, 그 차이와 원리에 대해서 설명해보겠습니다.
인텔리제이를 기준으로 진행합니다.
[프로젝트 환경]
[Dependencies]
인텔리제이 얼티메이트 버전을 사용하시는 분들은 툴에 내장된 Spring Initalizr를 이용하여 프로젝트를 생성하면 되고,
커뮤니케이션 버전을 사용하시는 분들은, https://start.spring.io 에 접속하셔서 아래와 같이 설정 후, 프로젝트를 다운받아 압축해제하여 인텔리제이로 Import하면 됩니다.
하위에 controller 패키지를 생성 하고 APIController.java, WebController.java 파일을 만듭니다.
@Controller
public class APIController {
@ResponseBody
@GetMapping("/api/hello")
public String api(){
return "Hello World!";
}
}
@Controller
public class WebController {
@GetMapping("/web/hello")
public String web(Model model){
model.addAttribute("msg","Hello World!");
return "/hello";
}
}
프로젝트 resources/templates 폴더에 hello.html 파일을 하나 생성합니다.
hello.html 작성
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
[[ ${msg} ]]
</body>
</html>
실행 후 크롬창을 열고 아래 각각 URL에 접속해봅니다.
localhost:8080/api/hello
localhost:8080/web/hello
F12을 눌러 개발자 도구를 연다음 Network 탭으로 들어갑니다.
그 다음 새로고침을 눌러서 한번 더 요청해봅니다. 해당 요청의 Response 탭으로 이동하면 서버로 부터 어떤 응답을 받았는지 확인할 수 있습니다.
localhost:8080/api/hello
localhost:8080/web/hello
코드상의 공통점은
차이점은
Hello World!
문자열을 반환합니다.Hello World!
값을 Model 속성에 넣고, /hello 경로를 반환합니다.Spring Boot를 Thymeleaf와 같은 템플릿 엔진을 이용하여 웹 애플리케이션을 개발하는 경우, 후자와 같이 컨트롤러 요청이 왔을 때, 템플릿 경로를 반환하게 됩니다.
그러면 ViewResolver를 통해 해당 템플릿을 찾아가서 문법을 해석하고 값을 바인딩 한 뒤, 최종적으로 html 코드 형태로 응답합니다.
반대로 뷰 페이지가 아닌 특정 값을 body에 담아 반환하려면 전자와 같이 @ResponseBody 어노테이션을 이용합니다. 이 경우에는 보통 ajax 요청에 대한 처리를 위해 사용합니다.
출처: https://www.javatpoint.com/spring-mvc-tutorial
Spring MVC 대략적인 흐름입니다. 해당 글에서 자세히 살펴볼 부분은 5번에 해당합니다.
앞서 말씀드렸다 싶이, 컨트롤러 요청이 오면 ViewResolver를 통해 템플릿을 해석한 후 view를 반환해 줍니다.
하지만, @ResponseBody를 사용하게 되면 어떻게 동작할까요?
Spring에서는 @ResponseBody 어노테이션을 사용하면 ViewResolver가 아닌 HttpMessageConverters에 뷰랜더링을 위임합니다.
HttpMessageConverters는 다양한 포맷의 데이터를 http 메시지에 알맞게 변환시켜주는 역할을 합니다. Spring에서는 컨버터를 데이터 종류에 따라서 자동으로 선택합니다.
대표적인 HttpMessageConverters 중 하나는 MappingJackson2HttpMessageConverter
이고, 자바 및 HashMap 객체를 Json으로 변환하거나 Json 데이터를 자바,HashMap 객체로 변환시켜줍니다.
[번외]
@RestController 라는 어노테이션이 있습니다.
@Controller + @ResponseBody를 합친 어노테이션이며, 해당 컨트롤러로 들어오는 요청에 대한 응답에 대해 @ResponseBody 가 적용됩니다.
HttpMessageConverters을 상속받아서 구현된 컨버터는 아래 문서에서 확인할 수 있습니다.
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/converter/HttpMessageConverter.html
종류가 굉장히 많은데, 이름만 읽어도 대략 어떤역할을 하는 컨버터인지 알수있습니다. 해당 컨버터로 이동하면 아래와 같이 간략한 설명이 있으니, 참고하시면 되겠습니다.
Hello World!
문자열을 반환하는 API 1개와 Hello World!
가 적혀있는 웹페이지 1개를 만들어보았습니다.
API는 @ReponseBody 어노테이션을 이용하여 HttpMessageConverters를 통해 String 형태의 문자열을 반환하였고, 웹페이지는 Thymeleaf라는 템플릿 엔진을 이용하여 ViewResolver를 통해 html이 반환되었습니다.
다음 글에서는 Content-type을 다루도록 하겠습니다.