스프링 부트 스타터 사이트 start.spring.io에 들어가서 스프링 프로젝트 생성
자동으로 만들어줌
Project
Maven -> 과거
Gradle -> 요즘 추세, 많이씀 (추천)
Language -> Java
Spring Boot
SNAPSHOT -> 만들고 있는 버전, M1 -> 정식 release된 버전이 아님
정식 release 중에서 가장 높은 버전 선택하기
Project Metadata
Group -> 기업 도메인명같은걸 적어줌 (처음은 상관없으니 hello라 함)
Artifact -> Build된 뒤 나오는 어떤 결과물
Dependencies
스프링 기반으로 프로젝트를 생성을 할건데, 어떤 라이브러리를 땡겨 쓸거냐 하는 것
Spring Web, Thymeleaf (html을 만들어주는 Template Engines) 선택
GENERATE 누르면 다운 후 IntelliJ에서 build.gradle로 열기
열고 파일안에 src -> main, test가 있음
Maven, Gradle 어떤걸 써도 main, test로 나눠져 있음
test밑에는 test코드가 들어있음
-> 있는 이유는 test코드가 정말 중요하기 때문에
main의 resources파일은 java파일을 제외한 모든 파일은 다 여기 존재
build.gradle의 dependencies에 있는 것들을 다운받아서 사용하는데, repositories의 mavenCentral에서 다운받아서 써라는 얘기
.gitignore파일 -> git에는 소스코드를 제외한 결과물은 올라가면 안되는데 그걸 제외해주는 파일
환경설정의 compact middle packages 체크시에 폴더이름을 hello, hellospring에서 합쳐줌
HelloSpringApplication에서 run시키면 port번호 8080(http)뜸
그럼 웹페이지에서 localhost:8080 들어가면 Whitelabel Error Page라고 뜸
중지버튼 누르면 없어짐
-> IntelliJ 설정도 gradle -> IntelliJ IDEA로 바꿔줘야지 동작
main을 run 시키면 OssProjectApplication 톰캣 서버를 내장하고 있는데 같이 띄워서 build 됨
spring-boot-starter-web이 필요하지만 의존관계에 있는 것들을 땡겨옴
오른쪽버튼에서 Gradle을 눌러보면 의존관계 확인가능
현업에서는 sysout말고 로그를 이용함
spring-boot-starter-web
spring-boot-starter-tomcat: 톰캣 (웹서버)
spring-webmvc: 스프링 웹 MVC
spring-boot-starter-thymeleaf: 타임리프 템플릿 엔진(View)
spring-boot-starter(공통): 스프링 부트 + 스프링 코어 + 로깅
spring-boot
spring-core
spring-boot-starter-logging
logback, slf4j
resources/static 폴더에서 index.html파일을 만들어주면 static은 정적인 것이니 변하지 않는 Welcome Page(홈)를 만들 수 있다.
head가 설명
bod
<!DOCTYPE HTML>
<html>
<head>
<title>Hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
Hello
<a href="/hello">hello</a>
</body>
</html>
치고 중지하고 키면 만들어짐
Welcome Page는 index.html에서 찾고 없다면 index 템플릿에서 찾는다.
hello.hellospring 밑의 폴더 controller폴더를 만들고 hellocontroller파일 생성
@GetMapping("hello") -> "hello"가 들어오면 밑의 메소드를 호출해준다.
public String hello(Model model) {
model.addAttribute("data", "hello!!");
return "hello";
localhost:8080/hello 로 호출
@Controller
public class HelloController {
@GetMapping("hello")
public String hello(Model model) {
model.addAttribute("data", "hello!!"); -> data 변수에 hello!! 값을 넣어놓는 것
return "hello";
}
}
결과 : localhost:8080/hello 로 들어가보면
뒤에 붙은 hello가 @GetMapping("hello")에 맵핑이 되서 hello를 return
컨트롤러에서 리턴 값으로 문자를 반환하면 뷰 리졸버( viewResolver )가 화면을 찾아서 처리한다.
스프링 부트 템플릿엔진 기본 viewName 매핑
resources:templates/ +{ViewName}+ .html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'안녕하세요. ' + ${data}" >안녕하세요. 손님</p> -> ${data}가 위의 95라인의 attributeValue인 hello!!로 치환됨
</body>
</html>
<html xmlns:th="http://www.thymeleaf.org">
위의 코드가 있어야 thymeleaf 문법을 쓸 수 있음
동작 환경 그림
스프링 부트는 내장 톰캣 서버를 내장하고 있어서 받으면 helloController에 있는 return값이 hello니까 resources/templates폴더에서 hello.html로 찾아가서 실행해라는 의미
빌드하고 실행하기
https://www.inflearn.com/questions/397942 -> 나와 동일한 오류로 안됨
or
잘안될 시 빌드할때
./gradlew clean build로 해보기
./gradlew clean 하면 build 폴더가 없어짐
터미널이나 cmd에서 실행하고 IntelliJ에서 동시 실행하면 안됨
8080 Port를 동시에 못띄우니까
Port 8080 was already in use. 에러 뜸
크게 3가지가 있음
1. 정적 컨텐츠 -> 파일을 고대로 전달해 주는 것, 위에서 hello 띄우는 것 처럼 고정되있는 것
2. MVC(Model, View, Controller)와 템플릿 엔진 -> 서버에서 html을 동적으로 바꿔서 내리는 것
3. API -> JSON이라는 데이터 구조 포맷으로 클라이언트한테 데이터를 전달하는 방식
resources/static 폴더에서 찾아서 실행
파일을 그대로 내려준다
hello-static.html 라는 이름으로 파일을 만들면 localhost:8080 뒤에 파일이름 작성하여
localhost:8080/hello-static.html 로 들어갈 수 있음
주소로 들어가면
첫번째로 컨트롤러에서 찾는다.
관련 컨트롤러가 없으니 resources/static 폴더에서 찾음
MVC : Model, View, Controller
view와 controller를 쪼개는게 일반적
Controller와 resources/template 폴더에서 찾아서 실행
view -> 화면과 관련된 일만
controller -> 서버뒷단에 관련된건 다 controller에서 처리
다 처리하고 화면에서 필요한 것들을 담아 model에게 넘겨주는 패턴을 사용
1 에서는 html 자체를 여는 것
2 에서는 controller를 통해서 html로 연결이 되서 여는 것?
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>
view에 있는 hello! empty는 없어도 되지만, 파일 자체의 absolute path를 copy해서 인터넷에 쳐보면 파일을 그냥 여는 것.
thymeleaf 템플릿의 장점은 html을 쓰고 서버없이 파일을 열어봐도 껍데기를 볼 수 있다( hello! empty)
근데 템플릿 엔진으로써 동작을 하면, 실제로 서버를 타고 돌면 hello + ${name} 값으로 바뀜
<p th:text="'hello ' + ${name}">hello! empty</p>
@Controller
public class HelloController {
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model) {
model.addAttribute("name", name);
return "hello-template"; -> hello-template으로 간다
}
}
207라인에서 @RequestParam에서 required 기본값이 true여서 무조건 인자를 넘겨야함
http://localhost:8080/hello-mvc?name=sring
이번엔 helloController에 hello-mvc가 mapping이 되어있어서 그 메소드를 호출해줌, 넘긴 인자를 토대로 viewResolver라는 화면 관리자가 동작을 한다.
templates에서 return값인 hello-template와 동일한 이름을 찾아서 실행, html 변환 후 넘겨줌
정적은 변환하지 않았음
API
정적 컨텐츠를 제외하면 MVC나 API 둘 중 하나라고 생각
*템플릿 엔진과의 차이는 view가 없이 저 문자 그대로 내려감
Controller 폴더 안에서
localhost:8080/hello-api?name=spring!!!!!
@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name) {
return "hello" + name; // name에 string을 넣으면 hello string
}
@ResponseBody -> http는 헤더부와 body부가 있는데, body에 이 데이터를 직접 넣어주겠다는 의미
페이지 소스보기를 해보면 앞에서는 html태그가 있었는데, 저 문자 하나만 그대로 전달됨
@ResponseBody 객체 반환 -> 기본이 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;
}
}
}
localhost:8080/hello-api?name=spring 으로 실행해보면 객체 자체를 return 함(251라인의 return 타입이 Hello임)
결과값이 json방식으로 나옴 key : value 형식으로
{ hello : spring }
@ResponseBody가 없으면, viewResolver에게 던져줘서 작동하는데,
@ResponseBody가 있으면, HttpMessageConverter가 동작해서
단순 문자면 -> StringConverter(기본 문자처리)
hello-spring처럼
name으로 문자로 들어오면 http응답에 넣어서 바로 주면 끝인데,
객체 형태면 -> JsonConverter
hello-api처럼
객체로 들어오면 기본 default값으로 데이터를 만들어서 http응답에 반환하는 것이 기본 방식