본 포스팅은 인프런의 '스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술' 강의를 수강하며 정리한 내용입니다.
웹을 개발할때는 크게 정적 콘텐츠, MVC와 템플릿 엔진, API 이렇게 3가지 방법이 있습니다.
첫 번째로 정적 콘텐츠는 이전 포스팅에서 웰컴페이지를 제작했던 것처럼 파일을 웹브라우저에 그대로 내려주는 방식입니다.
두 번째로 MVC와 템플릿 엔진 방식은 예를들어 과거 JSP, PHP(템플릿 엔진)처럼 HTML을 그대로 내려주지 않고, 서버에서 프로그래밍하여 동적으로 내려주는데 모델, 뷰, 컨트롤러로 모듈화하여 처리하는 방식입니다. 요즘엔 이 패턴으로 개발을 많이 한다고 합니다.
마지막으로 API 방식은 예를들어, Vue js, React, 모바일 등의 클라이언트와 함께 개발해야 할때, 요즘에는 JSON 포맷으로 클라이언트에게 데이터를 전달해주는 방식입니다. 또, 서버끼리 통신할 때도 html이 필요 없으므로 이 방식을 사용합니다.
1. 정적 콘텐츠
스프링에서는 정적 콘텐츠 기능을 제공합니다. 사이트를 보면, 스프링 부트는 기본적으로 /static이라는 폴더에서 정적 콘텐츠를 찾아 제공한다는 것을 알 수 있습니다.
Code
resource/static/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>
localhost:8080/hello-static.html (생성한 파일이름.확장자 그대로) 실행화면
[페이지 소스 보기] 하면 작성한 html 파일이 보입니다.
정적 콘텐츠 작동 원리
1. 웹브라우저에서 localhost:8080/hello-static.html 입력
2. 내장 톰캣 서버가 요청을 받아 스프링 부트에게 전달
3. 스프링은 Controller에 hello-static이 있는지 검색
4. 매핑된 컨트롤러가 없다면, resource 폴더에서 hello-static.html을 검색
5. 브라우저에 html 파일 렌더링
2. MVC 템플릿 엔진
MVC : Model, View, Controller
과거에는 Controller와 View가 분리되어 있지 않고 View에 모두 작성했습니다. (JSP) 최근에는 MVC 단위로 나누어 개발을 합니다. View는 화면을 그리는 데에 역할을 다하고, Controller에서는 비지니스 로직이나 내부적인 처리의 역할에 집중해야 합니다. JSP 파일 하나에 수천라인이 모여 있다면, 유지보수를 하기 어렵기 때문입니다.
Code
HelloController.java 에 코드 추가
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model){
// @ReuqestParam : url에서 받은 데이터 ?name=value
model.addAttribute("name", name);
return "hello-template"; // templates 폴더에 있는 html 검색
}
templates/hello-template.html 파일 생성
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
// $ 표시 : model의 key 가 name 인 것의 value를 참조합니다.
// 실제 서버 구동해서 타임리프엔진을 통해 데이터가 생기면, 태그 안에 있는 hello! empty가 치환됩니다.
</body>
</html>
http://localhost:8080/hello-mvc 실행화면
warn : org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'name' is not present]
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam(value="name", required = false) String name, Model model){
// required = false 지정하면, name값을 url에 입력하지 않아도 오류가 나지 않습니다.
// required 속성의 디폴트 값은 true 입니다.
model.addAttribute("name", name);
return "hello-template";
}
http://localhost:8080/hello-mvc?name=지야니 실행화면
동작 원리
1. 브라우저에서 localhost:8080/hello-mvc?name=지야니
2. 내장 톰캣서버가 url을 스프링에게 전달
3. 매핑된 컨트롤러에게 전달
4. 모델에 데이터를 처리한 뒤, 템플릿 이름을 리턴
5. 뷰 리졸버는 해당하는 템플릿을 찾아 템플릿 엔진인 타임리프에게 전달
6. html 형식으로 변환 된 값을 브라우저에게 리턴 (정적 콘텐츠일때는 html로 변환하는 과정이 없음)
cf) 타임리프 엔진의 장점은 서버없이 페이지소스를 봤을 때도, 코드를 확인할 수 있습니다. copy absolute path를 하면 서버없이 html 페이지를 띄울 수 있습니다. 페이지 소스를 확인하면 아래와 같습니다.
3. API
정적 컨텐츠방식을 제외하면, view 를 찾아 HTML을 렌더링해 웹 브라우저에게 넘겨주는 방식이 있고, API를 사용하는 방식이 있습니다.
Code
1. @ResponseBody 문자 반환 예제
HelloController.java 에 코드 추가
@GetMapping("hello-string") // url : hello-stirng 이 들어오면 아래 함수 실행
@ResponseBody // http 통신 프로토콜에서 body 데이터를 직접 넣어주겠다 선언
public String helloString(@RequestParam("name") String name){
return "hello " + name;
}
localhost:8080/hello-string?name=jiyeon 실행 결과
마우스 우클릭 - [페이지 소스보기]
html 태그 없이 데이터만 존재하는 모습입니다. 템플릿 엔진에서는 view html을 찾는 과정을 가지고 조작을 하는 방식이었지만, 이 API 방식은 이런 과정 없이 param 데이터를 그대로 내려주는 방식입니다.
2. @ResponseBody 객체 반환 예제
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name){
Hello hello = new Hello(); // ctrl shift enter 하면 ; 자동으로 생성
hello.setName(name);
return hello;
}
static class Hello {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
http://localhost:8080/hello-api?name=jiyeon 실행 결과
JSON 형식으로 반환된 모습입니다. JSON이란 key와 value로 이루어진 구조입니다. Hello 클래스의 멤버변수 hello가 key 로 사용된 것을 확인할 수 있습니다.
과거에는 XML 방식(HTML 태그)이 많이 쓰였습니다. 이 방식은 매우 무겁고, 태그를 열고 닫고 하는 과정이 필요합니다. 그래서 최근에는, 심플하게 key, value가 나오는 JSON 방식을 사용하는 추세입니다. 스프링도 @ResponseBody로 객체를 반환할 때, 디폴트로 JSON으로 반환하도록 세팅되어 있습니다. 물론 XML 방식으로 변경도 가능하다고 합니다.
getter/setter ?
getter/setter 을 두는 것은 Java bean 표준 규약입니다. private 접근지정자가 설정된 멤버변수 name에 접근하기 위해 getter/setter을 사용합니다. 그래서 getter/setter의 접근지정자는 public 으로 설정해야 합니다. 또 위와 같은 방식은 property 접근 방식이라고 합니다.
@ResponseBody 동작 원리
1. 브라우저에서 localhost:8080/hello-api 입력
2. 내장된 톰캣 서버가 스프링에게 url 이 왔다는 것을 전달
3. @GetMapping()을 통해 helloController 을 찾고, @ResponseBody가 있는지 확인
3-1. @ResponseBody 가 없다면, 템플릿 엔진 활용하도록 view 탐색 (viewResolver)
3-2. @ResponseBody 가 있다면, Http response 할 때, 템플릿 엔진 활용 없이 그대로 데이터를 response
( HTTP의 BODY에 문자 내용을 직접 반환 )
4-1. 문자열을 반환하는 경우, 그대로 response
4-2. 객체를 반환하는 경우, JSON 방식으로 데이터를 만들어 response 하는 것이 기본 정책
5. @ResponseBody인 경우 viewResolver가 동작하지 않고 HttpMessageConverter가 동작합니다.
5-1. 문자열 반환이라면, StringConverter(StringHttpMessageConverter)가,
5-2. 객체 반환이라면 JsonConverter(MappingJackson2HttpMessageConverter)가 동작합니다.
JsonConverter은 객체를 JSON 형태로 바꿔주고 웹브라우저로 전달해줍니다.
cf) 객체를 json으로 바꿔주는 유명한 라이브러리 2가지
Jackson 버전 2(디폴트라 범용성이 좋음), Gson 라이브러리
cf) byte 처리 등등 기타 여러 HttpMessageConverter가 기본으로 등록되어 있음
cf) 참고: 클라이언트의 HTTP Accept 해더(Request 할때, 응답을 이런 포맷으로 받고 싶다) 와 서버의 컨트롤러 반환 타입 정보 둘을 조합해서 HttpMessageConverter 가 선택됩니다.
'Dev > Spring Boot' 카테고리의 다른 글
[코드로 배우는 스프링 부트] 회원 관리 예제(2) (0) | 2021.02.22 |
---|---|
[코드로 배우는 스프링 부트] 회원 관리 예제(1) (1) | 2021.02.22 |
[코드로 배우는 스프링 부트] 빌드하고 실행하기 (0) | 2021.02.18 |
[코드로 배우는 스프링 부트] View 환경설정 (0) | 2021.02.17 |
[코드로 배우는 스프링 부트] 라이브러리 살펴보기 (0) | 2021.02.17 |