[Spring] 스프링 입문

kdkdhoho·2022년 2월 8일
2

Spring

목록 보기
1/26

스프링을 왜 어떻게 공부해야하는가?

왜?

=> 실무에서 제대로 동작하는 웹 어플리케이션을 개발하기 위해서

어떻게?

=> 스프링은 내용이 방대하고 깊이가 매우 깊은 프레임워크이다.
때문에 이론적인 부분들을 하나씩 공부하기보다 직접 코딩을 하며 어떻게 사용해야 하는지에 초점을 맞추자.


스프링 부트 스타터 사이트

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

    • Group: 보통 기업 도메인명을 명시한다.
    • Artifact: build되어 나올 때 결과물이라고 보면 된다. 일종의 프로젝트 명
    • Name: 여기서부터 따로 언급은 안하셨지만 프로젝트의 이름?
    • Description: 프로젝트를 부연설명하기 위한 공간
    • Package Name: 말 그대로 package name을 적으면 될 듯하다.
    • Packaging: IfUwanna IT - [Java] Jar War 차이점 및 특징 (+EAR) 글 참고
    • Java: java version
  • 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를 보면 우리가 맨 처음 선택한 라이브러리인 thymeleafweb, 자동으로 불러오는 test가 초기에 있을 것이다.

그 외로 External Libraries를 열어보면 굉장히 많다.

좀 더 자세히 알아보기 전에, 이전에 Maven이나 Gradle같은 build tool들은 요즘 의존 관계(Dependenciy)를 관리해준다.

간단히 얘기해서 우리가 선택한 web 라이브러리가 사용되기 위해 의존되는 다른 라이브러리를 가져오고, 그 라이브러리는 또 다른 필요한 라이브러리를 가져온다고 생각하면 된다.

Gradel에서 라이브러리 목록

위와 같이 1시 방향 Gradle에 들어가보면 Dependecies 폴더 아래 여러 Classpath가 있고, 그 중 compileClasspath를 열면 우리가 선택한 thymeleaf와 web 라이브러리가 들어있음을 확인할 수 있다.

그 중 web을 자세히 살펴보면 그 아래에 tomcat이라는 라이브러리가 있음을 확인할 수 있다.

이처럼 web만을 선택하여 가져왔지만, build tool이 알아서 의존관계에 있는 라이브러리들을 가져와준 것을 확인할 수 있다.

핵심 라이브러리

  1. 스프링 부트 라이브러리
  • 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
  1. 테스트 라이브러리
  • spring-boot-starter-test
    • junit: 테스트 프레임 워크
    • mockito: 목 라이브러리
    • assertj: 테스트 코드를 좀 더 편하게 작성하게 도와주는 라이브러리
    • spring-test: 스프링 통합 테스트 지원

log와 System.out.println()

실무에서 System.out.println()으로 출력을 하면 안되고 항상 log로 남겨야한다.

그래야 심각한 오류만 따로 모아 볼 수 있고, log파일을 관리할 수 있기 때문이다.


WelcomePage 만들기

Welcome Page란, http를 통해 접속하면 뜨는 첫 화면이다.

  1. src/resources/static에 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 Document

Spring.io - Project - Spring Boot - Learn - 버전에 맞는 Reference Doc. 선택

Spring 2.6.3 Reference Doc.


Controller

웹 어플리케이션에서 첫 번째 진입점이 컨트롤러이다.

  1. src/main/java/hello/hellosprin내에 controller 폴더 생성 후 그 안에, 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가 역할을 못하는 듯 하다.

  1. resources/tempaltes에 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>

동작 환경 순서

  1. 웹 브라우저에서 localhost:8080/hello (Get방식)로 접근하면, 스프링 부트 내에 내장된 톰켓 서버에서 요청을 받고, 그 요청을 스프링 컨테이너에 보낸다.

  2. 스프링 컨테이너 내에 helloController를 보면 어노테이션 @GetMapping("hello") 에 매칭되어 String hello(Model model)가 실행된다.

  3. 이러면 스프링이 파라미터로 model이라는 것을 만들어 넣어주고, 이 model에 (data:hello!!)로서 값을 전달한다.
    model(data:hello!!).
    그리고 hello를 return하는데, 이 코드는, resources/templates/hello.html을 찾아 값을 전달하고 렌더링하라는 의미이다.

  4. 찾았다면 viewResolver가 화면을 찾아서 처리한다. 즉, thymeleaf 템플릿 엔진이 처리(렌더링) 후, 웹브라우저에 hello.html을 전달한다.


참고로, `spring-boot-devtools` 라이브러리를 추가하면, `html`파일을 컴파일만해주면 서버 재시작 없이 View 파일 변경이 가능하다. IntelliJ 컴파일 방법: 메뉴 build - Recompile (단축키: Ctrl + Shift + F9)

Build 하는 방법

윈10 기준으로

  1. 명령 프롬프트에서 기존 hellospring 폴더 내로 접근하고,
  2. gradlew.bat build 입력
  3. build/libs 접근
  4. java -jar hello~~.jar 입력 (용량 큰 거)

build 삭제

기존 hellospring 폴더 내에서 gradlew clean build 입력


스프링 웹 개발 기초

아래 세 가지 방식은 스프링의 큰 그림이라고 생각하면 된다.


1. 정적 컨텐츠

서버에서 웹브라우저로 파일을 그대로 내려주는 방식

  1. resources/static/hello-static.html 생성
<!DOCTYPE html>
<html>
<head>
    <title>Test</title>
    <meta charset="UTF-8">
</head>
<body>
<h1>정적 컨텐츠입니다.</h1>
</body>
</html>
  1. url: localhost:8080/hello-static.html로 접속

동작 원리

  1. 웹브라우저에서 localhost:8080/hello-static.html로 서버에 접근
  2. 내장 톰캣 서버가 요청 수용 후, 스프링 컨테이너에서 hello-static 관련 컨트롤러 존재 유무 확인
  3. 없으므로 resources/static/hello-static.html 존재 유무 확인.
  4. 있으므로 웹브라우저에 hello-static.html 전달

2. MVC(Model-View-Controller)와 템플릿 엔진

서버에서 프로그래밍해서, html을 동적으로 바꾸어 웹브라우저로 전달하는 방식

과거에는 Controller와 View라는 개념이 따로 분리되어 있지 않았다. 소위 Model 1 방식.

View는 화면을 그리는 데에 모든 역량을 집중.
Controller와 Model은 비즈니스 로직이나 내부적인 것을 처리하는 데에 집중해야 함.

  1. 외부에서 파라미터를 받아서 value값 지정
@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
}
  1. resources/templates/hello-template.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${data}">hello! empty</p> <!-- data에 해당하는 value(input) 출력 -->
</body>
</html>
  1. url localhost:8080/hello-mvc?name=spring 접근.
    여기서 ?name= 뒤에 값을 주는 데로 출력이 바뀔 것이다.

참고로, @RequestParam("name", required = false)로 설정하면 값을 건네주지 않아도 null이 전달되면서 html 페이지가 열린다.
default는 true이다.

그리고 @RequestParam("data")로 바꿔주면, url에 ?data=spring 이런 식으로 바꿔줘야한다.
즉, 어노테이션의 매개변수에 매칭되어 값을 받는다고 보면 된다.

동작 원리

  1. 웹브라우저에서 localhost:8080/hello-mvc로 서버에 요청

  2. 스프링 부트 내의 내장 톰켓 서버가 요청을 받아서 스프링 컨테이너의 helloController로 전달

  3. @GetMapping("hello-mvc")와 Mapping되어 해당 메소드 실행
    model(name:spring) 생성

  4. resources/templates에서 return 값인 hello-template. + .html 파일 찾아서 model 값 전달

  5. viewResolver가 해당 html 파일 렌더링 처리 후, 웹브라우저에 전달


3. API

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 식으로 쓰는 것이 자바빈 규약이라고 한다. 그리고 프로퍼티 접근방식이라고도 부른다.
이 부분은 따로 찾아볼 것!

동작 원리

  1. 웹브라우저에서 localhost:8080/hello-api로 접근

  2. 내장 톰켓서버에서 요청 받아서 스프링 컨테이너로 전달

  3. helloController 내의 @GetMapping("hello-api") 찾음

  4. 있으면, 해당 메소드 실행. (참고로 없으면 에러 페이지 뜬다.)
    근데 @ResponseBody가 붙어있으면, 데이터 형식에 따른 HttpMessageConverter가 동작한다.
    가령, 문자열이면 StringHttpMessageConverter가. 객체면 MappingJackson2HttpMessageConverter가.
    (byte처리 등 기타 여러 HttpMessageConveter가 기본으로 등록되어 있다.)
    (클라이언트의 HTTP Accept 헤더와 서버의 컨트롤러 반환 타입 정보 둘을 조합해서 HttpMessageConverter가 선택된다.
    HTTP Accept 헤더에서 "나 이런 format으로 받고 싶어"라고 요청이 오면 해당 format으로 보내주고, 아무것도 안보내면 spring이 알아서 보낸다.)

  5. HttpMessageConveter를 통해 바뀐 데이터를 웹브라우저에 전달.
    (객체면 json 방식으로 전달)

참조: 인프런 - 스프링 입문

profile
newBlog == https://kdkdhoho.github.io

0개의 댓글