Spring boot로 HTTP API를 만들기 전에, MVC 구조로 웹 애플리케이션이 어떠한 원리로 만들어지고 동작하는지 이해가 필요합니다.
이번 글에서는 간단한 API 1개와 웹페이지 1개를 만들어보고, 그 차이와 원리에 대해서 설명해보겠습니다.
1. 프로젝트 생성
인텔리제이를 기준으로 진행합니다.
[프로젝트 환경]
- Gradle
- Java 1.8
- Spring Boot 2.5.5
[Dependencies]
- Spring Boot DevTools
- 자동 재시작 기능 사용
- Spring Web
- 내장 톰캣, 웹, MVC, RESTful 등 대다수 기능 포함
- Thymeleaf
- 웹 개발을 위한 서버사이드 자바 템플릿 엔진
- API를 개발하는데 필요하지 않지만, 원리를 설명하고 비교하기 위함.
인텔리제이 얼티메이트 버전을 사용하시는 분들은 툴에 내장된 Spring Initalizr를 이용하여 프로젝트를 생성하면 되고,
커뮤니케이션 버전을 사용하시는 분들은, https://start.spring.io 에 접속하셔서 아래와 같이 설정 후, 프로젝트를 다운받아 압축해제하여 인텔리제이로 Import하면 됩니다.
2. Controller 생성
하위에 controller 패키지를 생성 하고 APIController.java, WebController.java 파일을 만듭니다.
APIController.java 작성
@Controller
public class APIController {
@ResponseBody
@GetMapping("/api/hello")
public String api(){
return "Hello World!";
}
}
WebController.java 작성
@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>
3. 실행
실행 후 크롬창을 열고 아래 각각 URL에 접속해봅니다.
localhost:8080/api/hello
localhost:8080/web/hello
크롬 개발자 도구 확인
F12을 눌러 개발자 도구를 연다음 Network 탭으로 들어갑니다.
그 다음 새로고침을 눌러서 한번 더 요청해봅니다. 해당 요청의 Response 탭으로 이동하면 서버로 부터 어떤 응답을 받았는지 확인할 수 있습니다.
localhost:8080/api/hello
localhost:8080/web/hello
차이점 및 원리
코드상의 공통점은
- 둘 다 @Controller 어노테이션을 사용하였고
차이점은
- /api/hello의 경우 @ResponseBody 어노테이션이 붙어있고
Hello World!
문자열을 반환합니다. - /web/hello의 경우
Hello World!
값을 Model 속성에 넣고, /hello 경로를 반환합니다.
Spring Boot를 Thymeleaf와 같은 템플릿 엔진을 이용하여 웹 애플리케이션을 개발하는 경우, 후자와 같이 컨트롤러 요청이 왔을 때, 템플릿 경로를 반환하게 됩니다.
그러면 ViewResolver를 통해 해당 템플릿을 찾아가서 문법을 해석하고 값을 바인딩 한 뒤, 최종적으로 html 코드 형태로 응답합니다.
반대로 뷰 페이지가 아닌 특정 값을 반환하려면 전자와 같이 @ResponseBody 어노테이션을 이용합니다. 이 경우에는 보통 ajax 요청에 대한 처리를 위해 사용합니다.
Spring MVC 구조 및 ViewResolver 와 HttpMessageConverters
Spring MVC 대략적인 흐름입니다. 해당 글에서 자세히 살펴볼 부분은 5번에 해당합니다.
앞서 말씀드렸다 싶이, 컨트롤러 요청이 오면 ViewResolver를 통해 템플릿을 해석한 후 view를 반환해 줍니다.
하지만, @ResponseBody를 사용하게 되면 어떻게 동작할까요?
Spring에서는 @ResponseBody 어노테이션을 사용하면 ViewResolver가 아닌 HttpMessageConverters에 뷰랜더링을 위임합니다.
HttpMessageConverters는 다양한 포맷의 데이터를 http 메시지에 알맞게 변환시켜주는 역할을 합니다. Spring에서는 컨버터를 데이터 종류에 따라서 자동으로 선택합니다.
대표적인 HttpMessageConverters 중 하나는 MappingJackson2HttpMessageConverter
이고, 자바 및 HashMap 객체를 Json으로 변환하거나 Json 데이터를 자바,HashMap 객체로 변환시켜줍니다.
- request => json 데이터를 자바 객체로 변환 (json read)
- response => 자바 객체 데이터를 json 데이터로 변환 (json write)
[번외]
@RestController 라는 어노테이션이 있습니다.
@Controller + @ResponseBody를 합친 어노테이션이며, 해당 컨트롤러로 들어오는 요청에 대한 응답에 대해 @ResponseBody 가 적용됩니다.
HttpMessageConverters 종류
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을 다루도록 하겠습니다.
'Java > Spring' 카테고리의 다른 글
spring boot h2 memtestdb not found 문제 (0) | 2020.07.13 |
---|
댓글