=> 실무에서 제대로 동작하는 웹 어플리케이션을 개발하기 위해서
=> 스프링은 내용이 방대하고 깊이가 매우 깊은 프레임워크이다.
때문에 이론적인 부분들을 하나씩 공부하기보다 직접 코딩을 하며 어떻게 사용해야 하는지에 초점을 맞추자.
https://start.spring.io를 통해 간편하게 스프링 프로젝트를 생성할 수 있다.
사이트로 들어가면 Project
, Language
, Spring Boot
, Project Metadata
, Dependecies
의 항목들이 있다.
Project
에서 Maven과 Gradle이 있는데, 이 둘은 필요한 라이브러리를 import하고 build하는 라이프사이클을 관리해주는 tool이다.
과거엔 Maven을 사용했지만, 최근엔 Gradle을 사용한다. 따라서 Gradle
을 선택하면 된다.
(둘의 차이점은 HyoJun Blog - Maven과 Gradle의 차이 글을 참고)
Language
는 Java를 선택
Spring Boot에는 여러 숫자들과 SNAPSHOT, M1이 적혀있다.
여기서 숫자는 버전을 뜻하며, SNAPSHOT은 아직 개발중인 버전이고, M1은 아직 정식 출시된 버전이 아니라는 의미를 가진다.
Project Metadata
Dependencies
는 어떤 라이브러리를 가져와 사용할 것인지를 선택한다.
웹페이지를 만들 것이므로, Spring Web
과 템플릿 엔진 종류 중 하나인 thymeleaf
를 선택한다.
외에도, H2 database
, Lombok
, devtools
등이 있다.
템플릿 엔진이란, 지정된 템플릿 양식과 데이터가 합쳐져 HTML문서를 출력하는 소프트웨어이다.
출처: 나의 IT 블로그 - 10. 서버/클라이언트 템플릿 엔진의 차이, 머스테치
모두 선택 후 GENERATE
를 선택하면 로컬저장소에 새로운 폴더가 생기면서 프로젝트가 생성된다.
디렉터리에서 src - main - java - hello - hellospring - HelloSpringApplication.java를 실행하면 된다.
그 후 웹브라우저에서 locahost:8080
을 입력하면, Error Page가 뜨는데 이것이 바로 성공한 것이다.
위와 같이 바로 SpringBootApplication을 실행하면, 스스로 Spring을 띄우면서? 밑에 Tomcat이라는 내장 웹서버를 자체적으로 띄우면서 SpringBoot가 같이 올라오는 원리이다.
아파치 톰캣(Apache Tomcat)은 서블릿 컨테이너(또는 웹 컨테이너)만 있는 웹 어플리케이션 서버이다.
톰캣은 웹 서버와 연동하여 실행할 수 있는 자바 환경을 제공하여 자바 서버 페이지(JSP)와 자바 서블릿이 실행할 수 있는 환경을 제공하고 있다.
출처: 위키백과 - 아파치 톰캣
build.gradle에서 dependecies를 보면 우리가 맨 처음 선택한 라이브러리인 thymeleaf와 web, 자동으로 불러오는 test가 초기에 있을 것이다.
그 외로 External Libraries
를 열어보면 굉장히 많다.
좀 더 자세히 알아보기 전에, 이전에 Maven이나 Gradle같은 build tool들은 요즘 의존 관계(Dependenciy)를 관리해준다.
간단히 얘기해서 우리가 선택한 web 라이브러리가 사용되기 위해 의존되는 다른 라이브러리를 가져오고, 그 라이브러리는 또 다른 필요한 라이브러리를 가져온다고 생각하면 된다.
위와 같이 1시 방향 Gradle에 들어가보면 Dependecies 폴더 아래 여러 Classpath가 있고, 그 중 compileClasspath를 열면 우리가 선택한 thymeleaf와 web 라이브러리가 들어있음을 확인할 수 있다.
그 중 web을 자세히 살펴보면 그 아래에 tomcat이라는 라이브러리가 있음을 확인할 수 있다.
이처럼 web만을 선택하여 가져왔지만, build tool이 알아서 의존관계에 있는 라이브러리들을 가져와준 것을 확인할 수 있다.
spring-boot-starter-web
spring-boot-starter-thymeleaf: 타임리프 템플릿 엔진(View)
spring-boot-starter(공통): 스프링 부트 + 스프링 코어 + 로깅
실무에서 System.out.println()
으로 출력을 하면 안되고 항상 log로 남겨야한다.
그래야 심각한 오류만 따로 모아 볼 수 있고, log파일을 관리할 수 있기 때문이다.
Welcome Page란, http를 통해 접속하면 뜨는 첫 화면이다.
index.html
을 만들어준다.<!DOCTYPE HTML>
<html>
<head>
<title>Hello</title>
<meta htpp-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
Hello
<a href="/hello">hello</a>
</body>
</html>
끝이다.
다시 서버를 열고 접속하면 index.html 페이지가 열릴 것이다.
Spring.io - Project - Spring Boot - Learn - 버전에 맞는 Reference Doc. 선택
웹 어플리케이션에서 첫 번째 진입점이 컨트롤러이다.
HelloController.java
생성@Controller
public class HelloController {
@GetMapping("hello") // 웹 어플리케이션에서 `/hello` 로 들어오면 해당 메소드 호출
public String hello(Model model) { // 여기서 Model은 MVC(Model, View, Controller)에서의 Model
model.addAttribute("data", "hello!!"); // key는 data, value는 hello!! 로 model에 넘긴다.
return "hello"; // hello.html로 return
}
}
※ 여기서 @Controller
빼고 실행하면 Controller가 역할을 못하는 듯 하다.
hello.html
생성<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"> <!-- thymeleaf 템플릿 엔진 선언 -->
<head>
<meta charset="UTF-8" content="text/html" http-equiv="Content-Type">
<title>Hello</title>
</head>
<body>
<p th:text="안녕하세요. + ${data}">안녕하세요. 손님</p> <!-- 정적으로 html 페이지 생성 시 안녕하세요. 손님 출력.
렌더링을 통해 html 페이지 생성 시, 안녕하세요. [data의 value값] 으로 출력 -->
</body>
</html>
웹 브라우저에서 localhost:8080/hello
(Get방식)로 접근하면, 스프링 부트 내에 내장된 톰켓 서버에서 요청을 받고, 그 요청을 스프링 컨테이너에 보낸다.
스프링 컨테이너 내에 helloController를 보면 어노테이션 @GetMapping("hello")
에 매칭되어 String hello(Model model)가 실행된다.
이러면 스프링이 파라미터로 model이라는 것을 만들어 넣어주고, 이 model에 (data:hello!!)로서 값을 전달한다.
model(data:hello!!).
그리고 hello를 return하는데, 이 코드는, resources/templates/hello.html
을 찾아 값을 전달하고 렌더링하라는 의미이다.
찾았다면 viewResolver
가 화면을 찾아서 처리한다. 즉, thymeleaf 템플릿 엔진이 처리(렌더링) 후, 웹브라우저에 hello.html을 전달한다.
윈10 기준으로
gradlew.bat build
입력java -jar hello~~.jar
입력 (용량 큰 거)기존 hellospring 폴더 내에서 gradlew clean build
입력
아래 세 가지 방식은 스프링의 큰 그림이라고 생각하면 된다.
서버에서 웹브라우저로 파일을 그대로 내려주는 방식
hello-static.html
생성<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta charset="UTF-8">
</head>
<body>
<h1>정적 컨텐츠입니다.</h1>
</body>
</html>
localhost:8080/hello-static.html
로 접속localhost:8080/hello-static.html
로 서버에 접근hello-static
관련 컨트롤러 존재 유무 확인resources/static/hello-static.html
존재 유무 확인.hello-static.html
전달서버에서 프로그래밍해서, html을 동적으로 바꾸어 웹브라우저로 전달하는 방식
과거에는 Controller와 View라는 개념이 따로 분리되어 있지 않았다. 소위 Model 1 방식.
View는 화면을 그리는 데에 모든 역량을 집중.
Controller와 Model은 비즈니스 로직이나 내부적인 것을 처리하는 데에 집중해야 함.
@GetMapping("hello-mvc") // Get방식 데이터 hello-mvc와 Mapping하는 Annotation
public String helloMvc(@RequestParam("name") String input, Model model) { // name에 저장되어 오는 값을 input에 저장하겠다는 Annotation
model.addAttribute("name", input); // model(name:input)로 저장
return "hello-template"; // resources/templates/hello-template.html에 return
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${data}">hello! empty</p> <!-- data에 해당하는 value(input) 출력 -->
</body>
</html>
localhost:8080/hello-mvc?name=spring
접근.?name=
뒤에 값을 주는 데로 출력이 바뀔 것이다.참고로, @RequestParam("name", required = false)
로 설정하면 값을 건네주지 않아도 null
이 전달되면서 html 페이지가 열린다.
default는 true이다.
그리고 @RequestParam("data")
로 바꿔주면, url에 ?data=spring
이런 식으로 바꿔줘야한다.
즉, 어노테이션의 매개변수에 매칭되어 값을 받는다고 보면 된다.
웹브라우저에서 localhost:8080/hello-mvc
로 서버에 요청
스프링 부트 내의 내장 톰켓 서버가 요청을 받아서 스프링 컨테이너의 helloController로 전달
@GetMapping("hello-mvc")
와 Mapping되어 해당 메소드 실행
model(name:spring) 생성
resources/templates에서 return 값인 hello-template.
+ .html
파일 찾아서 model 값 전달
viewResolver가 해당 html 파일 렌더링 처리 후, 웹브라우저에 전달
json 데이터 형식으로 클라이언트에 값을 전달하는 방식
화면은 클라이언트가 알아서 그리거나, 서버끼리 통신할 때 주로 사용
@GetMapping("hello-string")
@ResponseBody // html의 body태그가 아닌, http의 body 부분을 의미한다. 그 body부에 데이터를 직접 return하기 위한 annotation
public String helloString(@RequestParam("name") String name) {
return "hello " + name; // HTTP 응답 Body 부분에 "hello spring" 전달.
}
그 후 url: localhost:8080/hello-string?name=spring"
입력하면 hello spring이 뜬다.
다만 위와 차이점은, 페이지 소스보기 누르면 글자만 그대로 나오는 것을 확인할 수 있다.
또한
@GetMapping("hello-api")
@ResponseBody
public String helloApi(@RequestParam("name") String name) {
Hello hello = new Hello();
hello.setName(name);
return hello;
}
static class Hello {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
이런 식으로 객체를 전달하게 되면, {"name":"spring"}
으로 값이 전달되는 것을 볼 수 있다.
json 형식
으로 값이 전달되는 것이다.
꿀팁: 인텔리제이 한정, class내에서 쉬프트 두 번 누르고 getter 및 setter
누르면 해당 클래스 내 필드에 대한 getter, setter 메소드 자동으로 만들어줌
추가) Alt+Insert 누르면 됨
참고: getter & setter 식으로 쓰는 것이 자바빈 규약이라고 한다. 그리고 프로퍼티 접근방식이라고도 부른다.
이 부분은 따로 찾아볼 것!
웹브라우저에서 localhost:8080/hello-api
로 접근
내장 톰켓서버에서 요청 받아서 스프링 컨테이너로 전달
helloController 내의 @GetMapping("hello-api")
찾음
있으면, 해당 메소드 실행. (참고로 없으면 에러 페이지 뜬다.)
근데 @ResponseBody
가 붙어있으면, 데이터 형식에 따른 HttpMessageConverter
가 동작한다.
가령, 문자열이면 StringHttpMessageConverter
가. 객체면 MappingJackson2HttpMessageConverter
가.
(byte처리 등 기타 여러 HttpMessageConveter
가 기본으로 등록되어 있다.)
(클라이언트의 HTTP Accept 헤더와 서버의 컨트롤러 반환 타입 정보 둘을 조합해서 HttpMessageConverter
가 선택된다.
HTTP Accept 헤더에서 "나 이런 format으로 받고 싶어"라고 요청이 오면 해당 format으로 보내주고, 아무것도 안보내면 spring이 알아서 보낸다.)
HttpMessageConveter
를 통해 바뀐 데이터를 웹브라우저에 전달.
(객체면 json 방식으로 전달)
참조: 인프런 - 스프링 입문