728x90
웹 개발 3가지 방법
- 정적 컨텐츠
- 서버가 작업을 하지 않은 채, 파일을 그대로를 웹 브라우저에 내려주는 것
- MVC 와 템플릿 엔진
- 템플릿 엔진 : 서버에서 작업을 거쳐서 동적인 HTTP 파일로 만드는 것
- 템플릿 엔진 예) JSP, PHH
- API
- 데이터 구조 포맷(format)으로 클라이언트한테 데이터를 전달하는 것
- 요새는 데이터를 JSON 형식으로 보낸다.
- 사용할 때
- API로 리액트나 뷰.js에게 데이터만 주고 화면은 클라이언트가 알아서 만들도록 하는 방식
- 서버끼리 통신할 때
정적 컨텐츠
- 스프링 부트는 정적 컨텐츠 기능을 제공한다.
📌 hello-static.html
<!DOCTYPE HTML>
<html>
<head>
<title>static content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
정적 컨텐츠 입니다.
</body>
</html>
- 스프링 부트는 정적 컨텐츠 기능을 제공하기 때문에 http://localhost:8080/hello-static.html 사이트로 접속하면 해당 정적 컨텐츠 파일이 뜬다.
🔍 동작원리
- 웹 브라우저에 url을 치면 내장 톰켓 서버로 요청이 간다.
- 톰켓은 먼저 스프링 컨테이너 안에 해당 파일인 hello-static 관련 컨트롤러가 있는지 없는지 찾는다.
- 컨트롤러의 우선권이 정적 컨텐츠보다 더 높다.
- 스프링 컨테이너 안에서 hello-static 관련 컨트롤러 파일을 못 찾을 경우 resources 폴더에 static/hello-static.html 파일을 찾는다.
- 있으면 다시 웹 브라우저에게 반환해준다.
MVC와 템플릿 엔진
- MVC : Model, View, Controller
- 사용자가 입력을 담당하는 View를 통해 요청을 보내면 해당 요청을 Controller가 받고, Controller는 Model을 통해 데이터를 가져온다. 해당 데이터를 바탕으로 출력을 담당하는 View를 제어해서 사용자에게 전달한다.
- MVC 패턴을 사용하면 Model과 View가 다른 컴포넌트들에 종속되지 않아 변경에 유리하다는 장점을 가질 수 있다.
- Model
- 애플리케이션이 무엇을 할 것인지 정의한다.
- 내부 비즈니스 로직을 처리하기 위한 역할을 한다.
- 즉, 데이터 저장소(DB)와 연동하여 사용자가 입력한 데이터나 사용자에게 출력할 데이터를 다룬다.
- 여러 개의 데이터 변경 작업(추가/변경/삭제)을 하나의 작업으로 묶는 트랜잭션을 다루는 일도 한다.
- View
- 최종 사용자에게 무엇을 화면(UI)으로 보여준다.
- 화면에 무엇을 보여주기 위한 역할을 한다.
- 즉, 모델이 처리한 데이터나 그 작업 결과를 가지고 사용자에게 출력할 화면을 만든다. 만든 화면은 웹 브라우저가 출력한다.
- Controller
- Model이 데이터를 어떻게 처리할지 알려주는 역할을 한다.
- 클라이언트의 요청을 받으면 해당 요청에 대한 실제 업무를 수행하는 Model을 호출한다.
- 클라이언트가 보낸 데이터가 있다면, Model을 호출할 때 전달하기 쉽게 가공한다.
- Model이 업무 수행이 완료하면 그 결과를 가지고 화면을 생성하도록 View에게 전달한다.
- 즉, 클라이언트의 요청에 대해 Model과 View를 결정하여 전달하는 일종의 조정자 역할을 한다.
🔍 Controller
📌 HelloController.java
package hello.hellospring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class HelloController {
@GetMapping("hello") // 주소명 적어 줄 것 → localhost:8080/hello 의미
public String hello(Model model) {
// ${data} 를 hello!! 로 변환
model.addAttribute("data" , "hello!!");
return "hello"; // html 파일 이름을 적어 줄 것 → hello.html 의미
}
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model) {
model.addAttribute("name", name); // 데이터를 뷰로 전달한다.
return "hello-template";
}
}
- @RequestParam
- @RequestParam 애노테이션은 HttpServletRequest 객체와 같은 역할을 한다.
- HttpServletRequest에서는 getParameter() 메서드를 이용하지만 @RequestParam을 이용해서 값을 받아 올 수 있다.
- value 값으로 단일 파라미터만 전달 받을 수 있다.
- @RequestParam("가져올_데이터_이름") [데이터타입] [가져온_데이터를_담을_변수]
- ex) @RequestParam("name") String name
- 애노테이션 value 속성 값인 "name"에 해당하는 부분은 URL 쿼리 파라미터에 해당한다.
- 그래서 URL 주소에 ?name="데이터" 이런 형태로 적어야 한다.
- 그러면 URL 주소에 적힌 쿼리파라미터 값이 String 타입의 name 변수에 들어가게 된다.
- @RequestParam 애노테이션으로 가져온 값을 Model 객체를 이용해서 뷰로 값을 넘겨준다.
- @RequestParam 애노테이션은 HttpServletRequest 객체와 같은 역할을 한다.
🔍 View
📌 hello-template.html
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>
- Model 객체를 통해서 ${name} 부분에 데이터가 들어온다.
- Model.addAttribute() 메서드를 통해서 해당하는 key 값에 value값을 넣어준다.
- URL 주소에 http://localhost:8080/hello-mvc?name=spring 이렇게 적으면 name 쿼리 파라미터값인 spring이 Model 객체를 통해서 View로 데이터가 넘어와서 ${name} 부분에 데이터가 들어간다.
🔍 동작원리
- 웹 브라우저가 톰켓에게 http://localhost:8080/hello-mvc 주소를 넘긴다.
- helloController 클래스에 hello-mvc 메서드가 매핑이 되어있어서 helloMvc() 메서드를 호출해준다.
- helloMvc() 메서드를 호출하고 스프링에게 반환 값인 hello-template 과 model 객체를 통해서 데이터를 전달한다.
- viewResolver가 hello-template.html 파일을 찾아서 템플릿 엔진에게 넘긴다.
- viewResolver는 사용자가 요청하는 것에 대한 응답 view를 렌더링하는 역할이다.
- 간단히 말하자면 view 이름으로부터 사용될 view 객체를 매핑하는 역할을 한다.
- viewResolver는 view를 찾아주고 템플릿 엔진을 연결시켜준다.
- 템플릿 엔진이 렌더링을 해서 HTML로 변환을 하고 웹 브라우저로 넘겨준다.
API
- MVC 방식은 화면에 렌더링하여 웹 브라우저에게 HTML로 전달한다.
- 그러나 API는 데이터 형태로 전달해준다.
📌 HelloController.java
package hello.hellospring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
@GetMapping("hello") // 주소명 적어 줄 것 → localhost:8080/hello 의미
public String hello(Model model) {
// ${data} 를 hello!! 로 변환
model.addAttribute("data", "hello!!");
return "hello"; // html 파일 이름을 적어 줄 것 → hello.html 의미
}
@GetMapping("hello-mvc") // localhost:8080/hello-mvc 의미미
public String helloMvc(@RequestParam("name") String name, Model model) {
model.addAttribute("name", name);
return "hello-template"; // hello-template.html 의미
}
@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name) {
return "hello " + name;
}
@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;
}
}
}
- @ResponseBody
- @ResponseBody가 붙은 파라미터에는 HTTP 요청의 본문 body 부분이 그대로 전달된다.
- 즉, HTTP 요청 body 부분을 자바 객체로 전달 받을 수 있다.
- HTTP 메시지에 헤더와 바디가 나눠어져 있다.
- 바디 부분에 이 데이터(리턴값)를 직접 넣어주겠다는 의미
- 반환값은 클라이언트에 그대로 간다.
- MVC 패턴과 달리 API 방식은 뷰가 없다. 그냥 데이터 형태로 날라간다.
- 웹 브라우저의 URL에 http://localhost:8080/hello-api?name=spring 를 입력하면쿼리파라미터인 키 값인 name과 value 값인 spring이 JSON 형태로 화면이 출력된다.
참고) @RequestBody
- 일반적인 GET/POST의 요청 파라미터라면 @ResquestBody 애노테이션을 사용할 일이 없다.
- 그러나 xml이나 JSON 기반의 메시지를 사용하는 요청의 경우에는 이 방법이 매우 유용하다.
- HTTP 요청의 바디 내용을 통째로 자바 객채로 변환해서 매핑된 메서드 파라미터로 전달해준다.
💡 @RequestBody 와 @ResponseBody 정리
- 클라이언트가 서버에게 필요한 데이터를 요청하기 위해 JSON 데이터를 요청 본문에 담아서 서버로 보낸다.
- 서버는 @ReqeustBody 애노테이션을 사용하여 HTTP 요청 본문에 담긴 값들을 자바 객체로 변환시켜, 객체에 저장한다.
- 서버가 클라이언트에게 응답 데이터를 전송하기 위해 @ResponseBody 애노테이션을 사용하여 자바 객체를 HTTP 응답 본문의 객체로 변환하여 클라이언트로 전송한다.
💡 클라이언트와 서버의 비동기 통신
- 클라이언트에서 서버로 통신하는 메시지를 요청(request) 메시지라고 하며, 서버에서 클라이언트로 통신하는 메시지를 응답(response) 메시지라고 한다.
- 웹에서 화면전환(새로고침) 없이 이루어지는 동작들은 대부분 비동기 통신으로 이루어진다.
- 비동기 통신을 하기 위해서는 클라이언트에서 서버로 요청 메시지를 보낼 때, 본문에 데이터를 담아서 보내야 하고, 서버에서 클라이언트로 응답을 보낼 때에도 본문에 데이터를 담아서 보내야 한다.
- 이 때 본문이 바로 body다.
- 즉 요청 본문 requestBody, 응답 본문 responseBody를 담아서 보내야 한다.
- 본문에 담기는 데이터 형식은 여러가지 형태가 있겠지만 대표적으로 사용 되는 것이 JSON이다.
- 즉, 비동기식 클라-서버 통신을 위해 JSON 형식의 데이터를 주고 받는 것이다.
🔍 동작 원리
- 웹 브라우저가 톰켓에게 url 주소를 던진다.
- 톰켓은 스프링에게 hello-api를 전달한다.
- 스프링은 helloController에 hello-api과 매핑된 메서드를 찾고 호출한다.
- 근데 @ResponseBody가 붙어있기 때문에 viewResolver 에게 넘기지 않고 HttpMessageConver에게 반환값을 넘긴다.
- 반환 타입이 기본 문자일 경우 : StringHtppMessageConverter가 처리한다.
- 반환 타입이 객체인 경우 : MappingJackson2HttpMessageConverter가 처리한다.
- Jackson2는 객체를 Json으로 변환해주는 라이브러리다.
- 참고로 HTTP Accept 헤더와 서버의 컨트롤러 반환 타입 정보를 토대로 HttpMessageConverter의 종류가 선택된다.
👀 참고 자료
https://hongku.tistory.com/119
https://januaryman.tistory.com/131?category=959308
https://cheershennah.tistory.com/179
https://tecoble.techcourse.co.kr/post/2021-04-26-mvc/
728x90
'[ Spring ] > Spring 입문' 카테고리의 다른 글
[Spring 입문] 컴포넌트 스캔과 자동 의존관계 설정 (0) | 2022.02.14 |
---|---|
[Spring 입문] 회원 관리 예제 (0) | 2022.02.14 |
[Spring 입문] Welcom page 만들기 (0) | 2022.02.12 |
[Spring] 스프링 부트 프로젝트 생성 (0) | 2022.02.12 |