# Chap1. 스프링 시작하기

## 스프링이란?

`스프링`은 `스프링 애플리케이션 컨텍스트`라는 `컨테이너`를 제공하는데, 이것은 애플리케이션 `컴포넌트`들을 생성하고 관리한다. 그리고 애플리케이션 컴포넌트 또는 `빈(bean)`들은 스프링 애플리케이션 컨텍스트 내부에서 서로 연결되어 완전한 애플리케이션을 만든다.

빈의 상호 연결은 `의존성 주입`이라고 알려진 패턴을 기반으로 수행된다. 즉, 애플리케이션 컴포넌트에서 의존(사용)하는 다른 빈의 생성과 관리를 자체적으로 하는 대신 별도의 대체(`컨테이너`)가 해주며, 이 개체에서는 모든 컴포넌트를 생성, 관리하고 해당 `컴포넌트`를 필요로 하는 빈에 `주입(연결)`한다. 일반적으로 이것은 `생성자` 인자 또는 속성의 `접근자 메서드`를 통해 처리된다.

지금까지의 스프링 버전에서는 컴포넌트 및 다른 컴포넌트 및 다른 컴포넌트와의 관계를 나타내는 하나 이상의 `XML` 파일을 사용해서 빈을 상호 연결하도록 `스프링 애플리케이션 컨텍스트`에 알려주었다.

```java
<bean id="inventoryService" class="com.example.InventoryService" />
<bean id="productService" class="com.example.ProductService">
	<constructor-arg ref="inventoryService" />
<bean>
```

그러나 최신 버전의 스프링에서는 자바 기반의 `구성(configuration)`이 더 많이 사용된다.

```java
@Configuration
public class ServiceConfiguration {
	@Bean
	public InventoryService inventoryService() {
		return new InventoryService();
	}

	@Bean
	public ProductService productSerivce() {
		return new ProductService(inventoryService());
	}
}
```

`@Configuration` 애노테이션은 각 빈을 스프링 애플리케이션 컨텍스트에 제공하는 구성 클래스라는 것을 스프링에게 알려준다. 구성 클래스의 메서드에는 `@Bean` 애노테이션이 지정되어 있으며, 이것은 각 메서드에서 반환되는 객체가 `애플리케이션 컨텍스트`의 빈으로 추가되어야 한다는 것을 나타낸다.

`스프링`은 자동으로 컴포넌트들을 구성할 수 있는 `자동-구성` 기능이 있다. 자동-구성은 자동 연결과 컴포넌트 검색이라는 스프링 기법을 기반으로 한다. 컴포넌트 검색을 사용하여 스프링은 자동으로 애플리케이션의 `classpath`에 지정된 `컴포넌트`를 찾은 후 스프링 애플리케이션 컨텍스트의 `빈`으로 생성할 수 있다. 또한, 스프링은 `자동 연결`을 사용하여 의존 관계가 있는 컴포넌트를 자동으로 다른 빈에 주입(연결)한다.

## 스프링 애플리케이션 초기 설정하기

기존의 자바 웹 애플리케이션은 `WAR` 파일로 패키징되며, `JAR` 파일은 라이브러리와 데스크톱 UI 애플리케이션의 패키징에 사용되기 때문이다.

`JAR` 패키징은 클라우드를 염두에 둔 선택이다. `WAR` 파일은 기존의 자바 애플리케이션 서버에 애플리케이션을 배포할 때는 적합하지만, 대부분의 클라우드 플랫폼에는 잘 맞지 않는다

### 왜 WAR 파일은 클라우드 플랫폼에는 잘 맞지 않을까?

확인해보기

### 빌드 명세하기

```java
<?xml version="1.0" encoding="UTF-8"?>
<product xmlns="<http://maven.aphache.org/POM/4.0.0>"
	...
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.6.RELEASE</version>
		<relativePath/>
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thyumeleaf</artifactId>
		</dependency>

		...
	</dependencies>
```

`<parent>` 태그는 우리 프로젝트가 부모 `POM(Product Object Model)`으로 `spring-boot-starter-parent`를 갖는다는 것을 지정한다. 이 부모 `POM`은 스프링 프로젝트에 흔히 사용되는 여러 라이브러리의 의존성 관리를 제공한다.

의존성은 `<dependencies>` 요소에 정의된다. `Spring web`, `Thymeleaf`, `Test` 의존성 항목은 `<artifactId>`에 `stater` 단어를 포함하고 있음을 알 수 있다. 스타터 의존성은 다음 세 가지 장점이 있다.

* 우리가 필요로 하는 모든 `라이브러리`의 의존성을 선언하지 않아도 되므로 빌드 파일이 훨씬 더 작아지고 관리하기 쉬어진다.
* `라이브러리` 이름이 아닌 기능의 관점으로 의존성을 생각할 수 있다. 따라서 만일 웹 애플리케이션을 개발한다면 웹 애플리케이션을 작성할 수 있게 해주는 `라이브러리`들을 일일이 지정하는 대신에 여기처럼 `웹 스타터 의존성`만 추가하면 된다.
* `라이브러리`들의 버전을 걱정하지 않아도 된다. `스프링 부트`에 포함되는 라이브러리들의 버전은 호환이 보장되므로 사용하려는 `스프링 부트`의 `버전`만 신경 쓰면 된다.

### 애플리케이션의 부트스트랩(구동)

실행 가능 `JAR` 파일에서 애플리케이션을 실행하므로 제일 먼저 시작되는 `부트스트랩 클래스`가 있어야 한다.

`@SpringBootApplication`은 다음 세개 에노테이션이 결합한 적이다.

* @SpringBootConfiguration: 현재 클래스(`TacoCloudApplication`)를 구성 클래스로 지정한다. 아직은 구성이 많지 않지만, 필요하다면 자바 기반의 스프링 프레임워크 구성을 현재 클래스 추가할 수 있다. 실제로는 이 애노테이션이 `@Configuration:` 특화된 형태이다.
* @EnableAutoConfiguration : 스프링 부트 자동 구성을 활성화한다. 자동 구성은 나중에 더 자세히 알아볼 것이다. 일단 지금은 이 `애노테이션`이 우리가 필요로 하는 `컴포넌트`들을 자동으로 구성하도록 스프링 부트에 알려준다는 것만 알아 두자
* @ComponentScan : 컴포넌트 검색을 활성화한다. 이것은 `@Component`, `@Controller`, `@Serivce` 등의 애노테이션과 함께 클래스를 선언할 수 있게 해준다. 그러면 스프링은 자동으로 그런 클래스를 찾아 스프링 애플리케이션 컨텍스트에 `컴포넌트`로 등록한다.

### 애플리케이션 테스트하기

`@SpringBootTest`는 스프링 부트 기능으로 테스트를 시작하는 것을 `JUnit`에 알려준다.

#### SpringBootTest에 대해서 더 확인해보자

## 스프링 애플리케이션 작성하기

### 웹 요청 처리하기

`@Component`, `@Service`, `@Repository`를 포함해서 소수의 다른 애노테이션들도 `@Controller`와 동일한 기능을 제공하므로 이런 애노테이션들 중 어느 것을 사용해도 된다. 그러나 `@Controller`를 선택한 이유는 애플리케이션에서의 컴포넌트 역할을 더 잘 설명해 주기 때문이다.

#### @Controller를 @Service로 대체할 수 있을까?

### 컨트롤러 테스트하기

```java
@WebMvcTest(HomeController.class)
public class HomeControllerTest {
	...
}
```

`@SpringBootTest` 대신 `@WebMvcTest` 애노테이션을 사용하면 스프링 MVC 애플리케이션의 형태로 테스트가 실행되도록 한다. 즉, `HomeController`가 스프링 `MVC`에 등록되므로 우리가 스프링 `MVC`에 웹 요청을 보낼 수 있다.

`@WebMvcTest`는 또한 스프링 `MVC`를 테스트하기 위한 스프링 지원을 설정한다. 이때 우리 테스트에서는 실제 서버를 시작하는 대신 스프링 `MVC`의 모킹(`mocking`) 매커니즘을 사용해도 충분하므로 모의 테스트를 하기 위해 우리 테스트 클래스에 `MockMvc` 객체를 주입(`연결`)한다.

### 스프링 부트 DevTools 알아보기

`DevTools`는 스프링 개발자에게 다음과 같은 개발 시점의 편리한 도구를 제공한다.

* 코드가 변경될 때 자동으로 애플리케이션을 다시 시작시킨다. (`**단점`은 애플리케이션이 자동으로 가시 시작될 때 의존성 변경이 적용될 수 없다\*\*)
* 브라우저로 전송되는 리소스(예를 들어, `템플릿`, `자바스크립트`, `스타일시트`)가 변경될 때 자동으로 브라우저를 새로고침한다.
* `템플릿 캐시`를 자동으로 `비활성화`한다.
* 만일 `H2` 데이터베이스가 사용 중이라면 자동으로 `H2 콘솔`을 `활성화`한다.

## 스프링 살펴보기

### 스프링 부트

`스타터 의존성`과 `자동-구성` 외에도 스프링 부트는 다음의 다른 편리한 기능도 제공한다.

* `액추에이터`는 애플리케이션의 내부 작동을 런타임 시에 살펴볼 수 있는 기능을 제공하며, 여기에는 `메트릭`, `스레드 덤프 정보`, `애플리케이션의 상태`, `애플리케이션`에서 사용할 수 있는 환경 속성이 포함된다.
* `환경 속성`의 명세
* 핵심 프레임워크에 추가되는 `테스트` 지원

### 스프링 데이터

간단한 `자바 인터페이스`로 애플리케이션의 데이터 `리파지터리`를 정의할 수 있다. 스프링 데이터는 서로 다른 종류의 `데이터베이스`와 함께 사용될 수 있다.

### 스프링 시큐리티

`스프링 시큐리티`는 `인증`, `허가`, `API 보안`을 포함하는 폭넓은 범위의 애플리케이션 보안 요구를 다룬다.

### 스프링 통합과 배치

`스프링 통합`은 데이터가 사용 가능한 즉시 처리되는 `실시간 통합`을 한다. 반면에 `스프링 배치`에서는 다량의 데이터가 처리되는 시점을 `트리거`가 알려줄 때 데이터가 수집 처리되는 `배치 통합`을 처리해 준다.

### 요약

* `웹 애플리케이션 생성`, `데이터베이스 사용`, `애플리케이션 보안`, `마이크로서비스` 등에서 개발자의 노력을 덜어주는 것이 스프링의 목표다
* 스프링 부트는 `손쉬운 의존성 관리`, `자동-구성`, 런타임 시의 애플리케이션 내부 작동 파악을 스프링에서 할 수 있게 한다.
* 스프링 애플리케이션은 스프링 `Initializer`를 사용해서 초기 설정할 수 있다.
* `빈`이라고 하는 컴포넌트는 스프링 애플리케이션 컨텍스트에서 자바나 `XML`로 선언할 수 있으며, 컴포넌트 탐색으로 찾거나 스프링 부트 `자동-구성`에서 자동으로 구성할 수도 있다.
