지금은 다양한 데이터 베이스에 데이터를 저장하는 클라우드에 맞춰진 마이크로서비스로
구성된 애플리케이션의 개발에 관심이 높다.
그리고 더 큰 확장성과 향상된 성능을 제공하는 리액티브 프로그래밍도 새로운 관심사가 되었다.
마이크로서비스와 리액티브 프로그래밍을 포함하는 최신 소프트웨어 개발의 관심사를 다루기 위해
스프링 프레임워크도 진화하였다.
또한, 스프링 부트도 추가되어 스프링 자체의 개발 모델이 간소화하였다.
1-1. 스프링이란?
스프링 프레임워크는 스프링 애플리케이션 컨텍스트 라는 컨테이너를 제공하는데
이것은 애플리케이션 컴포넌트(Bean)들을 생성하고 관리한다.
그리고 애플리케이션 컴포넌트 또는 빈들은 스프링 애플리케이션 컨텍스트 내부에서
서로 연결되어 완전한 애플리케이션을 만든다.
즉, 애플리케이션 컴포넌트에서 의존하는 다른 빈의 생성과 관리를 자체적으로 하는 대신
별도의 개체(컨테이너)가 해주며 이 개체에서는 모든 컴포넌트를 생성, 관리하고
해당 컴포넌트를 필요로 하는 빈에 주입(연결)한다.
일반적으로 이것은 생성자 인자 또는 속성의 접근자 메서드를 통해 처리한다.
B 객체를 A 객체에서 직접 생성하는 경우
public class A {
private B b = new B(); // 객체를 직접 생성
// main
public static void main(String[] args) {
A a = new A();
}
}
외부에서 생성된 B객체를 생성자를 통해 의존 관계를 주입하는 경우 => DI
public class A {
private B b;
public A(B b) {
this.b = b;
}
// main
public static void main(String[] args) {
B b = new B(); //외부에서 생성 후
A a = new A(b); // 의존 관계를 주입.
}
}
이렇게 DI를 통해서 런타임 시에 의존 오브젝트를 사용할 수 있어, 모듈 간의 결합도가 낮아지고 유연성이 높아진다.
객체의 의존성을 역전시켜 객체 간의 결합도를 줄이고 유연한 코드를 작성할 수 있게 하여
가독성 및 코드 중복, 유지 보수를 편하게 할 수 있게 한다.
기존에는 다음과 순서로 객체가 만들어지고 실행되었다.
1. 객체 생성
2. 의존성 객체 생성
클래스 내부에서 생성
3. 의존성 객체 메소드 호출
하지만, 스프링에서는 다음과 같은 순서로 객체가 만들어지고 실행된다.
1. 객체 생성
2. 의존성 객체 주입
스스로가 만드는것이 아니라 제어권을 스프링에게 위임하여 스프링이 만들어놓은 객체를 주입한다.
3. 의존성 객체 메소드 호출
스프링이 모든 의존성 객체를 스프링이 실행될때 다 만들어주고 필요한곳에 주입시켜줌으로써
Bean들은 싱글턴 패턴의 특징을 가지며, 제어의 흐름을 사용자가 컨트롤 하는 것이 아니라
스프링에게 맡겨 작업을 처리하게 된다.
Bean 객체
Spring IoC 컨테이너가 관리하는 자바 객체 / IoC 컨테이너에서 싱글톤 스코프로 객체를 관리
스프링 자동 구성
@Configuration
최신 버전의 스프링에서는 xml 보다는 자바 기반 configuration을 사용하여 빈을 상호연결한다.
@Configuration
public class ServiceConfiguration {
@Bean
public InventoryService inventoryService() {
return new InventoryService();
}
@Bean
public ProductService productService() {
return new ProductService(inventoryService());
}
}
@Configuration 애노테이션은 이것이 각 빈을 스프링 애플리케이션 컨텍스트에 제공하는
구성 클래스 라는 것을 스프링에 알려준다.
구성 클래스의 메서드에는 @Bean 애노테이션이 지정되어 있으며,
이것은 각 메서드에서 반환되는 객체가 애플리케이션 컨텍스트의 빈으로 추가되어야 한다는 것을 나타낸다.
자동 구성은 자동연결(Autowired)와 컴포넌트 검색(Component Scanning)이라는 스프링 기법을 기반으로 한다.
Component Scanning을 사용해서 스프링은 자동으로 애플리케이션의 classpath에 지정된 컴포넌트를
찾은 후 스프링 애플리케이션 컨텍스트의 빈으로 생성할 수 있다. 또한 스프링은 Autowired를 사용해서
의존 관계가 있는 컴포넌트를 자동으로 다른 빈에 주입한다.
자동-구성은 바람처럼 휙 지나간다. 따라서 자동-구성의 효과는 알 수 있지만, '바로 이것이 자동-구성의 한 예야!'
라고 보여주고 말할 수 있는 코드가 없다. 우리가 코드를 작성하지 않아도 컴포넌트가 활성화되고 자동-구성이
작동하기 때문이다. 바로 이것이 자동-구성의 매력이다.
1.2 스프링 애플리케이션 초기 설정하기
[ 주요 항목 ]
mvnw, mvnw.cmd : 메이븐 래퍼 스크립트
메이븐이 설치 되어 있지 않더라도 이 스크립트로 프로젝트 빌드 가능
pom.xml : 메이블 빌드 명세
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
이 태그에는 프로젝트가 부모 POM 으로 spring-boot-starter-parent를 갖는다는 것을 지정한다.
부모 POM 은 스프링 프로젝트에서 흔히 사용되는 여러 라이브러리의 의존성 관리를 제공한다.
=> 이런 라이브러리들의 경우는 버전을 지정할 필요가 없다.
TacoCloudApplication.java : 스프링부트 메인 클래스
application.properties : 구성 속성 지정
static : 브라우저에 제공할 정적인 콘텐츠(이미지, 스타일시트, 자바스크립트 등) 저장 폴더
templates : 브라우저에 콘텐츠를 보여주는 템플릿 파일 폴더 - 예) Thymeleaf 템플릿
Spring boot starter 의존성 관리
Spring Web, thymeleaf, Test 의존성 항목은 spring-boot-starter를 에 포함한다.
필요로 하는 모든 라이브러리 의존성을 선언하지 않아도 되므로 관리가 쉽다.
라이브러리 이름이 아닌 기능 관점으로 의존성 생각 가능해준다.
부트 스트랩 클래스(TacoCloudApplication)가 실행 가능 JAR 파일에서 애플리케이션을 실행한다.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication // 스프링부트 애플리케이션
public class TacoCloudApplication {
public static void main(String[] args) {
// 애플리케이션 실행
SpringApplication.run(TacoCloudApplication.class, args);
}
}
@SpringBootApplication 은 3개의 어노테이션이 결합한 것이다.
@SpringBootConfiguration
현재 클래스 (TacoCloudApplication) 를 구성 클래스로 지정한다.
@EnableAutoConfiguration
스프링 부트 자동-구성을 활성화 한다.
@ComponentScan
컴포넌트 검색을 활성화 한다.
@Component, @Controller, @Service 등의 애노테이션과 함께 클래스를 선언할 수 있게 한다.
@SpringBootTest 가 스프링부트 기능으로 테스트 시작하라고 Junit 에게 알려준다.
package tacos;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SlaApplicationTests {
@Test
void contextLoads() {
}
}
1.3 스프링 애플리케이션 작성하기
컨트롤러
웹요청과 응답을 처리하는 컴포넌트이다.
웹브라우저 요청을 상대할 경우 컨트롤러는 선택적으로 모델데이터를 채워 응답하며
브라우저에 반환되는 HTML 을 생성하기 위해 응답의 웹요청을 뷰에 전달한다.
@Controller
public class HomeController {
@GetMapping("/") // 루트 경로 / 의 웹 요청 처리
public String home() {
return "home"; // 뷰 이름 반환
}
}
1.3.2 뷰 정의하기
src/main/resources/templates 에 html file 생성
1.3.3 컨트롤러 테스트하기
@WebMvcTest(HomeController.class)
public class HomeControllerTest {
@Autowired
private MockMvc mockMvc; // MockMvc 주입
@Test
public void testHomepage() throws Exception {
mockMvc.perform(get("/")) // get 수행
.andExpect(status().isOk()) // HTTP 200 OK 리턴
.andExpect(view().name("home")) // home.html view
.andExpect(content().string(containsString("Welcome to..."))); // Welcome to... 텍스트 포함
}
}
빌드 명세
Web, Thymeleaf 의존성은 일부 다른 의존성도 포함 시킨다.
스프링부트 자동-구성 라이브러리 개입
1.4 스프링 살펴보기
스타터 의존성과 자동-구성 외에도 스프링 부트는 다음의 다른 편리한 기능도 제공한다.
간단한 자바 인터페이스로 애플리케이션의 데이터 리파지터리를 정의할 수 있다.
스프링 데이터는 서로 다른 종류의 데이터베이스와 함께 사용될 수 있다
스프링 시큐리티는 인증, 허가, API 보안을 포함하는 폭넓은 범위의 애플리케이션 보안 요구를 다룬다.
스프링 통합은 데이터가 사용 가능한 즉시 처리되는 실시간 통합을 한다.
반면에 스프링 배치에서는 다량의 데이터가 처리되는 시점을 트리거가 알려줄 때 데이터가 수집 처리되는 배치 통합을 처리해 준다.
마이크로서비스 관련하여 스프링을 사용해서 클라우드 애플리케이션을 개발하기 위한 프로젝트들의 모음인 스프링 클라우드를 사용한다.
요약
웹 애플리케이션 생성, 데이터베이스 사용, 애플리케이션 보안, 마이크로서비스 등에서 개발자 노력을 줄여주는 것이 스프링의 목표이다.
스프링부트는 손쉬운 의존성관리, 자동-구성, 런타임 시의 애플리케이션 내부 작동 파악을 스프링에서 할수 있게 한다.
스프링 애플리케이션은 스프링 initializer 를 사용해서 초기 설정 가능하다.
빈(bean) 이라고 하는 컴포넌트는 스프핑 애플리케이션 컨텍스트에서 자바나 xml 로 선언 가능하다.
빈은 컴포넌트 탐색으로 찾거나 스프링 부트 자동-구성에서 자동으로 구성 가능하다.