이 글은 "스프링 인 액션 제5판 (크레이그 윌즈 지음)"을 읽고 주관적으로 작성된 글입니다.
※ 배우는 내용
1) 스프링과 스프링 부트 핵심사항
2) 스프링 프로젝트 생성하기
3) 스프링 개요
※ 요약
- 스프링의 목표는 개발자의 목표를 덜어주는 것
- 웹 어플리케이션 생성
- 데이터베이스 사용
- 어플리케이션 보안
- 마이크로서비스 등
- 스프링 부트의 역할
- 쉬운 의존성 관리
- autoconfiguration
- Actuator
- 스프링 Initializr
- 초기 설정을 해줌
- 대부분 자바 개발 환경을 지원
- Bean의 구성
- 스프링 어플리케이션에서 XML/자바 등으로 선언
- 또는 Component Scan이나 스프링 부트 autuconfiguration으로 자동 구성
- 애플리케이션 개발 유형의 변화
- 예전에는 RDBMS를 사용하는 웹 브라우저 기반 웹 애플리케이션 형태였음
- 지금은 DB에 데이터 저장하는 클라우드에 맞춰진 마이크로서비스로 구성된 애플리케이션
- 리액티브 프로그래밍도 새로운 관심사 : 더 큰 확장성, 향상된 성능
- 스프링은 이러한 개발 환경을 지원
- 마이크로서비스 / 리액티브 프로그래밍에 맞기 진화
- 스프링 부트(Spring boot)도 추가되어 스프링 자체도 간소화됨
1. 스프링이란?
- 보통 애플리케이션
- 애플리케이션의 구조
컴포넌트로 구성됨 : 애플리케이션 전체 기능 중 일부를 담당함 - 컴포넌트의 상호작용
컴포넌트는 다른 애플리케이션 구성 요소와 협력하여 작업 처리 - 컴포넌트의 Requirement
애플리케이션 실행시 컴포넌트 생성이 필요하고, 생성을 상호간 알려야함
- 애플리케이션의 구조
- 컨테이너
- 스프링 애플리케이션 컨텍스트(Spring application context)라는 컨테이너 제공
애플리케이션 컴포넌트들을 생성 / 관리
- 스프링 애플리케이션 컨텍스트(Spring application context)라는 컨테이너 제공
- Bean
- 컴포넌트를 빈(bean)이라 함
- Bean들은 컨테이너 내에서 서로 연결되어 완전한 애플리케이션을 구성
- Bean의 상호 연결
의존성 주입(Dependency Injection)이라는 패턴 기반으로 수행
- 컨테이너와 bean
- 애플리케이션이 의존성을 가지는 다른 bean의 생성 / 관리를 컨테이너가 대신 해줌
- (정리) 컨테이너의 역할
- 모든 컴포넌트(bean)을 생성하고 관리
- 이 컴포넌트에 필요한 bean을 주입
- 이는 생성자 or 속성 접근자 메서드로 처리
- 컴포넌트간의 관계 표현
- 기존에는 XML로 상호 bean의 연결을 컨테이너에 알림
각 bean이 가진 id로, 생성자 인자를 사용 -> < constructor-arg ref = $BEAN_ID /> - 그러나 최신 버전에서는 자바 기반으로 알림
- 기존에는 XML로 상호 bean의 연결을 컨테이너에 알림
@Configuration
pulic class ServiceConfigureation{
@Bean
public InventoryService inventoryService() {
return new InventoryService();
}
@Bean
public ProductService productService() {
return new ProductService(inventoryService());
}
}
- 어노테이션(Annotation)
- 클래스, 인터페이스, 함수, 매개변수, 속성, 생성자에 어떤 의미를 추가하는 기능, 자바 컴파일러에서 처리
- @Configuration
각 bean이 컨테이너에 제공하는 구성 클래스임을 알림 - @Bean
각 메서드에서 반환되는 객체가 컨테이너의 bean으로 추가되어야함을 나타냄
각 bean의 id가 해당 bean을 정의하는 메서드 이름 - 그러나 자바 기반 알림도 auto-configuration을 할 수 없는 경우에만 사용
- 자동-구성(Autoconfiguration)
- 자동 연결(Autowiring)과 컴포넌트 검색(Component Scanning)이라는 스프링 기법이 기반
- 애플리케이션의 classpath에 지정된 컴포넌트로 컨테이너의 bean을 생성
- 의존 관계의 컴포넌트를 자동으로 다른 bean에 주입
- 스프링 부트(Spring boot)
- 생산성 향상을 제공하는 스프링 프레임워크의 확장
- 향상된 Autoconfiguration
환경 변수인 classpath를 기준으로 컴포넌트 구성과 의존성을 인지 - 스프링 부트의 Autoconfiguration으로 애플리케이션 빌드에 필요한 별도 구성코드(XML, Java)가 현저히 줄어듬
2. 스프링 애플리케이션 초기 설정하기
- 스프링 Initializr
- 애플리케이션의 프로젝트 디렉터리 구조 생성 / 빌드 명세를 직접 정의할 수 있음
- 그러나 시간낭비이므로, 애플리케이션 초기설정을 해주는 스프링 Initializr 사용
- 스프링 Initializr
- 스프링 Initialzr는 REST API를 사용하는 브라우저 기반의 웹 애플리케이션
- 스프링 프로젝트의 구조를 생성해줌
- Spring Tool Suite(STS)
- 이클립스 기반 스프링 IDE
- 다른 IDE에 없는 스프링 부트 대시보드 기능 제공
(라고 되어있지만 내가 사용하는 Intellij도 제공하는 것으로 보임)
1) STS를 사용해서 스프링 프로젝트 초기 설정하기 (나에게 필요한 부분만 정리)
- WAR(Web application ARchive)와 JAR(Java ARchive)
- 기존 자바 웹 애플리케이션은 WAR로 패키징, JAR는 라이브러리와 데스크탑 UI 애플리케이션의 패키징
- JAR 패키징은 클라우드를 염두
- WAR는 기존 자바 애플리케이션 서버에 배포할 때 적합
- 그러나 대부분 클라우드 플랫폼에 맞음
- 추가하는 의존성
- Spring Boot DevTools
- Lombok
- Thymeleaf
- Spring Web
2) 스프링 프로젝트 구조 살펴보기
- 전형적인 Maven/Gradle 구조
- 애플리케이션 소스코드 (src/main/java)
- 테스트 코드 (src/test/java)
- 자바가 아닌 리소스 (src/main/resources)
- 그 외 알아둘 항목들
- mvnw / mvnw.cmd ( gradlew / gradle.bat )
- Maven(Gradle) Wrapper 스크립트로, PC에 Maven(Gradle)설치 없이 프로젝트 빌드 - pom.xml ( build.gradle )
- Maven(Gradle) 빌드 명세 : 빌드에 필요한 정보 및 지정한 파일 - src/main/resources/application.properties
- 구성 속성을 직접 지정할 수 있음 - src/main/resources/static
- 브라우저에 제공할 정적 콘텐츠(이미지, 스타일시트, 자바스크립트 등) - src/main/resources/templates
- 브라우저에 콘텐츠를 보여주는 템플릿 파일의 폴더, Thymeleaf 템플릿 추가하는 곳
- mvnw / mvnw.cmd ( gradlew / gradle.bat )
빌드 명세 (Gradle을 사용하지만, pom.xml을 살펴보는 것도 도움이 될듯)
- 스프링 initializr가 프로젝트 생성시 내가 정의한 내용을 pom.xml( build.gradle )에 저장
- <parent>
- 부모 POM(Project Object Model)으로 spring-boot-starter-parent를 갖는 것을 지정
(Gradle에서는 보이지 않음) - 이 POM은 스프링 프로젝트에 흔히 사용되는 여러 라이브러리의 의존성 관리를 제공
- <version>은 해당 스프링 부트 버전에 의해 정의된 의존성 관리를 계승
- 부모 POM(Project Object Model)으로 spring-boot-starter-parent를 갖는 것을 지정
- <dependencies>
- 의존성 정의
- <artifactId> 에 스프링 부트 스타터(starter) 의존성의 장점
- 우리가 필요로 하는 모든 라이브러리 의존성에 대한 선언 생략
- 빌드 파일 간소화 - 의존성을 라이브러리 이름이 아닌 기능 관점으로 파악 가능
- 스프링 부트에 포함되는 라이브러리의 버전 호환이 보장됨
- <plugin> 에 스프링 부트 플러그인 기능
- Maven을 사용하는 애플리케이션 실행을 가능하게 해줌
- 의존성에 지정된 라이브러리가 실행 가능 JAR에 포함되어 있는지, 런타임시 classpath에서 찾을 수 있는지 확인
- 실행 가능 JAR의 main class로 부트스트랩 class를 나타내는 매니페스트 파일을 JAR로 생성
애플리케이션의 부트스트랩(구동)
- 실행을 위해 JAR 파일에는 부트스트랩 class를 포함한 최소한의 스프링 구성을 필요로 함
- @SpringBootApplication
- 스프링 부트 애플리케이션임을 나타냄
- 아래 어노테이션들을 포함하는 개념
- @SpringBootConfiguration
- 현재 class를 구성 class로 지정 - @EnableAutoConfiguration
- Autoconfiguration 활성화 - @ComponentScan
- 컴포넌트 검색 활성화
- @Component, @Controller, @Service 등 어노테이션과 함께 class를 선언할 수 있게 해줌
- 스프링이 자동으로 이런 class를 찾아 컨테이너에 컴포넌트를 등록
- @SpringBootConfiguration
- 부트스트랩 class의 main 메서드
- JAR가 실행될 때 호출 : 대부분 이름만 다르고 같은 메서드를 가짐
- SpringApplication class의 run 메서드 실행
SpringApplication class : 실제로 애플리케이션을 시작시키고, 스프링 애플리케이션 컨텍스트(컨테이너)를 생성함
- 부트스트랩 Class의 수정
- 보통 내용을 변경할 필요가 없음
- 그러나 Autoconfiguration이 되지 않는 것을 고려하여, 별도의 구성 class를 생성하는 것이 좋음
애플리케이션 테스트하기
- 스프링 Initializr는 테스트 클래스를 제공
- 실행 코드가 없음
- 그럼에도 스프링 어플리케이션 컨텍스트가 정상적으로 로드되는지 확인
- @SpringBootTest
- 테스트를 시작하라는 것을 JUnit에게 알림
- main 메서드의 SpringApplication.run() 호출에 부합되는 테스트 class
- @Test
- 테스트 메서드
- 테스트 메서드가 없으면 아무 일도 하지 않음
3. 스프링 애플리케이션 작성하기
- 홈페이지를 추가하여, 다음 두가지 생성을 통해 스프링의 장점 확인하기
- 홈페이지의 웹 요청을 처리하는 컨트롤러
- 홈페이지의 모습을 정의하는 뷰 템플릿
1) 웹 요청 처리하기
- 스프링 MVC
- 웹 프레임워크
- 컨트롤러
- 웹 요청과 응답을 처리하는 컴포넌트 - 웹 브라우저를 상대하는 애플리케이션의 경우 내부 동작
- 컨트롤러는 모델 데이터를 채워서 응답
- 브라우저에 반환되는 HTML 생성 목적으로 응답의 웹 요청을 뷰에 전달
- 예제 컨트롤러 클래스
- 루트 경로(/)의 웹 요청을 처리
- 모델 데이터를 채우지 않음
- 웹 요청을 홈페이지 뷰에 전달
package tacos;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
// 컨트롤러
@Controller
public class HomeController{
// 루트 경로인 /의 웹 요청을 처리
@GetMappling("/")
public String home(){
// 뷰 이름을 반환
return "home";
}
}
- @Controller
- 컴포넌트 검색(Conponent Scanning)시 Home Controller를 컴포넌트로 식별하게 해줌
- 스프링의 컴포넌트 검색에서 자동으로 Home Controller 클래스를 찾음
- 찾은 후 스프링 애플리케이션 컨텍스트의 bean으로 인스턴스 생성
- @Component, @Service, @Repository 모두 같은 기능 (단지 역할이 명확해서 @Controller를 사용)
- home() 메서드의 @GetMapping
- 루트 경로인 /의 HTTP GET 요청이 수신되면 해당 메서드 처리
- 여기서 home 값을 갖는 String만 반환하고 다른 일은 하지 않는다. 이 값은 뷰의 논리적인 이름이다.
- [???] 뷰의 논리적 이름이 home -> 어디서 확인할 수 있는지? - Thymeleaf
- classpath에 지정되어있음
- 이를 이용해 뷰 템플릿 정의
- Thymeleaf
- JSP / FreeMarker 등을 선택하지 않고 Thymeleaf를 템플릿 엔진으로 선택
- 그 이유는 JSP를 스프링 부트와 사용시 고려할 것이 있기 때문 (2장에서 살펴볼 예정이라고 함)
- 논리적인 뷰 이름(home) 기반으로 파일이름 생성
- /src/main/resources/templates/home.html
2) 뷰 정의하기
- 예제 홈페이지 템플릿
- <img> 태그에서 Thymeleaf의 th:src 속성을 사용
- /images/TacoCloud.png의 위치는 /resouces/static/images/TacoCloud.png
<!DOCTYPE html>
<html xmln="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="EUC-KR">
<title>Taco Cloud</title>
</head>
<body>
<h1> Welcom to...</h1>
<img th:src="@{/images/TacoCloud.png}"/>
</body>
</html>
3) 컨트롤러 테스트하기
- 스프링은 웹 어플리케이션을 쉽게 테스트하는 강력한 테스트 지원 기능 제공
- HTML 페이지의 콘텐츠에 대한 assertion을 설정하기 어려움
- assertion : 우리가 원하는 것이 맞는지 테스트하기 위해 지정한 단언
- 테스트할 내용
- /의 HTTP GET 요청이 성공적인지 (status가 200인지)
- 뷰의 이름이 home인지
- "Wlecome to..." 메시지가 포함되어 있는지
- @WebMvcTest
- @SpringBootTest 대신 사용
- 스프링 MVC 어플리케이션 형태로 테스트가 진행
- HomeController가 스프링 MVC에 등록되어 웹 요청을 보낼 수 있음
- MockMvc 객체
- 실제 서버를 시작하지 않고 모의 테스트
- 스프링 MVC의 모의(mocking) 매커니즘 사용
- mockMvc.perform(get("/")
- /의 HTTP GET 요청을 MockMvc 객체로 수행 - andExpect
- 기대하는 결과를 설정
@WebMvcTest(HomeController.class)
public class HomeControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testHomePage() throws Exception {
mockMvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(view().name("home"))
.andExpect(content().string(
containsString("Welcome to...")));
}
}
4) 애플리케이션 빌드하고 실행하기
- 스프링 부트 대시보드
- IDE에서 실행중인 어플리케이션의 로그를 보여주는 기능을 말하는듯
- Intellij에서 services라는 tab이며, 실행시 자동으로 활성화되는 듯
- tomcat은 어플리케이션의 일부
- tomcat에 어플리케이션을 설치하지 않았는데 실행이 가능
- 스프링 부트 어플리케이션에 실행에 필요한 모든 것이 포함되기 때문
5) 스프링 부트 DevTools 알아보기
- 개발 시점에서 편리한 도구들을 제공
- 코드 변경시, 자동으로 어플리케이션 재시작
- 리소스 변경시, 자동으로 브라우저 새로고침 / 템플릿 캐시 비활성화
- H2 콘솔 활성화
- 자동 어플리케이션 재시작
- 자바 코드 / 속성 파일 변경시 감지하여 어플리케이션 재시작
- DevTools 사용 중일때는 JVM에 2개의 클래스 로더에 의해 로드
- src/main/ 경로에 있는 자바 코드 / 속성 파일를 포함
- 의존성 라이브러리를 포함
- 1번 클래스 로더만 다시 로드
- 시간이 조금이나마 단축
- 빌드 명세에 의존성 추가/변경/삭제 등 의존성 변경시 직접 새로 시작해야함
- 자동 브라우저 새로고침 / 템플릿 캐시 비활성화
- 성능 향상을 위해 템플릿의 파싱 결과를 캐시에 저장
- 개발 시점에서 이는 새로고침을 하더라도 변경사항이 적용되지 않으므로 불편함
- DevTools는 모든 템플릿 캐싱을 자동으로 비활성화 -> 새로고침시 변경내용이 적용
- LiveReload를 사용할 경우, 새로고침까지 자동
- H2 콘솔
- H2 DB를 사용할 시, H2 콘솔도 DevTools가 자동으로 활성화
- http://localhost:8080/h2-console에 접속하면 확인 가능
6) 리뷰하기
- 지금까지 만든 스프링 어플리케이션 작업 과정
- 스프링 Initializr로 프로젝트 구조 생성
- 컨트롤러 클래스 작성
- 홈페이지 웹 요청 처리 - 뷰 템플릿 정의
- 홈페이지를 보여주는 역할 - 테스트 클래스 작성
- 애플리케이션 테스트
- 스프링을 사용한 어플리케이션의 장점
- 어플리케이션의 요구를 충족하는 코드에 집중할 수 있음
- 작성한 코드가 간단함 - 스프링이 빌드명세에 따라 dependency injection을 함
- 빌드 명세(pom.xml)에 Web과 Thymeleaf 의존성을 선언
- 스프링 MVC 프레임워크 / 내장 tomcat / Thymeleaf, Thymeleaf 레이아웃 dialect 등 의존성을 포함시킴
- 이에 따라 관련된 bean / tomcat 서버를 스프링 어플리케이션 컨텍스트에 구성
- Thymeleaf 뷰 리졸버를 구성
- 어플리케이션의 요구를 충족하는 코드에 집중할 수 있음
4. 스프링 살펴보기
1) 핵심 스프링 프레임워크
- 스프링 MVC
- 웹 요청 처리 (REST API)
- JdbcTemplate
- JDBC 지원 (데이터 퍼시스턴스)
- WebFlux
- 리액티브 프로그래밍
2) 스프링 부트
- 스타터 의존성 / autuconfiguration
- 액추에이터(Actuator)
- 어플리케이션의 내부 동작을 runtime에 살펴볼 수 있는 기능
- metric / thread dump 정보 / 어플리케이션 상태 / 사용 환경 포함
- 환경 속성의 명세
- 테스트 지원
- 스프링 부트 CLI 제공
- 어플리케이션 전체를 그루비 스크립트로 작성하여 CLI에서 실행
3) 스프링 데이터
- 간단한 자바 인터페이스로 어플리케이션의 데이터 repository 정의 가능
- 서로 다른 종류이 DB와 함께 사용 가능
4) 스프링 시큐리티
- 인증(Authentication) / 허가(Authorization) / API 보안을 포함한 강력한 보안 프레임워크
5) 스프링 통합과 배치
- 다른 어플리케이션 / 다른 컴포넌트를 통합할 필요가 생김
- 이미 알려진 몇 가지 애플리케이션 통합 패턴이 있음
- 스프링 통합
- 데이터가 사용 가능한 즉시 처리되는 실시간 통합
- 스프링 배치
- 다량의 데이터가 처리되는 시점을 트리거가 알려줄 때 데이터가 수집 처리되는 배치 통합 처리
6) 스프링 클라우드
- 어플리케이션 개발 세계가 새로운 시대로 진입중
- 어플리케이션을 거대한 하나의 단일체 대신 여러 개의 개별적 단위들로 합성
- 스프링 클라우드는 클라우드 어플리케이션 개발을 위한 프로젝트 모음
'책읽기' 카테고리의 다른 글
[데이터 분석을 위한 SQL 레시피][2장] 이 책에서 다루는 도구와 데이터 (0) | 2021.07.18 |
---|---|
[쉽게 배우는 운영체제](요약)[Part-1][Ch-2] 컴퓨터의 구조와 성능 향상 (0) | 2021.07.17 |
[쉽게 배우는 운영체제][Part-1][Ch-1] 운영체제의 개요 (0) | 2021.07.16 |
[파이썬 알고리즘 인터뷰][문자열] 그룹 애너그램 (중요) (0) | 2021.07.16 |
[파이썬 알고리즘 인터뷰][문자열] 가장 흔한 단어 (중요) (0) | 2021.07.16 |