스프링 웹 개발의 기초 - 정적 컨텐츠, 웹 MVC, 그리고 api
스프링 웹 개발은 다음과 같은 3가지 방법이 있다.
- 정적 컨텐츠 : 서버에서 특별히 뭔가 하는 거 없이 단순히 html파일을 클라이언트 쪽으로 넘기는 방식이다.
- MVC & 템플릿 엔진 : 서버에서 특정한 작업을 통해 html파일을 동적으로 만들어 넘기는 방식이다. JSP, PHP 등의 템플릿 엔진이 사용되며 이걸 하기 위해 MVC패턴이 도입된다.
- API : JSON 포맷 등으로 '데이터'를 클라이언트에 전달하는 방식이다. 서버 간의 통신에도 활용되며, 요즘은 React같은 애들한테 API로 데이터를 넘기고 그걸 통해 화면을 클라이언트가 그리는 식으로도 활용된다.
정적 컨텐츠
resources폴더의 static폴더에 있는 파일을 찾아 넘긴다. 다음 순서로 동작한다고 이해할 수 있다.
- url를 입력
- 내장된 톰캣이 요청을 받고 스프링 컨테이너에게 요청을 넘김
- 컨트롤러가 url에 매핑되는 메서드가 있는지 먼저 찾음
- 없으면 내부의 resources/static에서 찾아서 넘김
MVC & 템플릿 엔진
MVC는 Model, View, Controller로 각자의 역할을 구분해 개발하는 방식을 일컫는다. Model과 Controller는 비즈니스 로직과 내부 로직을 처리하는 역할을 맡고, View는 화면을 그리는 역할을 맡는다. 옛날엔 JSP를 통해서 View에서 Controller의 역할도 수행했는데 이를 model 1방식이라 부르기도 함.
@Controller
public class HelloController {
@GetMapping("hello")
public String hello(Model model) {
model.addAttribute("data", "hello!!");
return "hello";
}
}
- GetMapping : GET POST 할 때의 get이며, /hello로 get요청이 들어왔을 때 hello라는 메서드를 실행한다는 거다.
- Model : View를 그리기 위해 사용되는 데이터들의 박스(?)로, key-value형태로 데이터들을 저장한다. 내부적으론 Map이 사용된다고 함.
- return "hello" : 데이터들을 보낼 View이름을 지정하는 거라고 보면 된다.
이 방식의 동작순서는 다음과 같다.
- url를 입력
- 내장된 톰캣이 요청을 받고 스프링 컨테이너에게 요청을 넘김
- 컨트롤러가 url에 매핑되는 메서드가 있는지 먼저 찾음
- 있으면 해당 메서드를 호출
- viewResolver가 지정된 이름의 View를 찾아주고 템플릿 엔진과 연결시켜줌
- 템플릿엔진이 렌더링한 html파일을 반환
API
이 방식은 html파일이 아니라 데이터를 넘기는 방식이라고 볼 수 있다. 결국 정적 컨텐츠를 넘기는게 아니라면
- html로 내려주든가
- api로 (즉 데이터로) 주든가
둘 중에 하나인 거다.
@Controller
public class HelloController {
@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name) {
return "hello" + name;
}
}
- GetMapping : GET POST 할 때의 get이며, /hello-string로 get요청이 들어왔을 때 helloString라는 메서드를 실행한다는 거다.
- @ResponseBody : 이 어노테이션을 쓰면 viewResolver를 쓰지 않고, 대신에 Http Response의 BODY에 데이터를 담게 된다.
- @RequestParam("name") String name : 쿼리에서 "name"에 해당하는 값을 name이란 파라미터로 받아온다는 거다.
- return "hello" + name : 이 문자열 자체를 데이터로 준다는거다.
참고로 객체를 반환하면 객체가 JSON으로 변환되서 보내진다!
@Controller
public class HelloController {
@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;
}
}
}
이 방식의 동작순서는 다음과 같다.
- url를 입력
- 내장된 톰캣이 요청을 받고 스프링 컨테이너에게 요청을 넘김
- 컨트롤러가 url에 매핑되는 메서드가 있는지 먼저 찾음
- 있으면 해당 메서드를 호출
- 근데 @ResponseBody가 있으면 viewResolver에게 전달하지 않고 httpMessageConverter에게 전달함
- 문자는 그대로 보내고, 객체는 JSON으로 바꿔서 전달한다.
용어 정리
Gradle : 라이브러리들을 버전 설정하고 가져와주는 빌드 도구. 은 의존관계가 있는 라이브러리들도 함께 다운해준다(A라이브러리가 B에 의존하면 자동으로 B도 땡겨줌).
resources폴더 : 자바 파일(*.java)를 제외한 나머지 파일들을 위한 폴더
템플릿 엔진 : 지정된 템플릿 양식과 데이터를 합쳐 HTML 문서를 출력하는 SW. 예를 들어 그냥 a.html을 작성하기만 하면 서버에선 그냥 걔를 클라이언트쪽으로 넘기기만 하는데, 템플릿 엔진을 쓰면 html에서 루프를 쓴다던가 어떤 데이터값을 넣는다든가 할 수 있는 것이다.
<html xmlns:th="http://wwww.thymeleaf.org">
html태그에 이렇게 작성해두면 해당 html파일에서 타임리프(템플릿 엔진) 문법을 사용 가능하다. 이를 활용해 서버에서 받아온 특정 데이터 값을 넣고 싶으면
<p th:text="'안녕하세요' + ${data}">안녕하세요.손님</p>
이런 식으로 하면 된다. 참고로 태그 사이엔 딱히 뭔가를 쓸 필욘 없음. 근데 템플릿 엔진을 거치지 않고 html파일을 열거나 할 때 태그 사이의 값이 나온다. 이미지 태그의 alt값과 비슷한 역할이라고 생각할 수 있겠다.