스프링 부트 스타터
스프링 부트를 구성하는 핵심요소 3가지 : 스타터, 자동설정, 액추에이터
스타터(starter) : 스프링이 제공하는 특정 모듈을 사용할 수 있도록 관련된 라이브러리 의존성을 해결
자동설정(AutoConfiguration) : 스타터를 통해 추가한 모듈을 사용할 수 있도록 관련된 빈 설정을 자동으로 처리
액추에이터(Actuator) : 스프링 부트로 개발된 시스템을 모니터링할 수 있는 다양한 기능 제공
[스타터로 의존성 관리]
스타터는 필요한 라이브러리들을 관련된 것끼리 묶어서 마치 패키지처럼 제공한다.
프로젝트에서 사용하고 싶은 모듈이 있으면 그 모듈에 해당하는 스타터만 의존성으로 추가하면 된다.
1. 프로젝트에 의존성 추가하기
- pom.xml 파일에 <dependency> 설정 추가
2. 스타터로 의존성 추가하기
스프링부트는 다양한 스타터를 제공하며 spring-boot-start-모듈명 형태를 갖는다.
스타터를 이용하면 프로젝트의 라이브러리 의존성 문제를 간단하게 해결 가능.
3. 이클립스에서 스타터 추가하기
진행중인 프로젝트에서 새로운 스타터를 추가할 때는 직접 타이핑하거나 ctrl + space 사용 가능.
[스타터 사용하기]
기본스타터 (프로젝트 생성시 체크한 web, devTools, Lomomk에 대한 의존성, 테스트 관련 의존성은 기본적으로 추가 되어있다.)
- spring-boot-starter-web, spring-boot-devtools, lombok, spring-boot-starter-test
스프링 MVC를 이용해서 웹 애플리케이션을 개발할 때에는 아무리 간단하더라도 기본적으로 사용하는 라이브러리는 수십개가 넘는다.
이 의존성을 일일이 설정하지 않고 스타터로 처리 가능. 스타터는 관련된 라이브러리들을 묶음으로 관리하는 역할
[스타터 설정 이해하기]
스타터는 최소한의 설정으로 수많은 라이브러리를 자동으로 관리.
특정 모듈과 관련된 의존성을 패키지처럼 관리하기 때문에 프로젝트에 새로운 모듈을 쉽게 등록하거나 제거할 수 있다.
[POM 파일 상속 구조]
메이븐은 상속을 통해 복잡한 설정을 재사용 가능
<parent> 엘리먼트 : 다른 POM 설정을 부모로 지정하여 부모로부터 모든 설정을 상속받을때 사용
해당 스타터에 어떠한 모듈이 설정되어 있는지 궁금하다면 Ctrl + Space 로 조회해보자 !!
복잡한 의존성을 숨길 수 있어서 쉽게 프로젝트를 관리 가능하다
[의존성 재정의]
- 스타터 재정의
부모로부터 상속받은 프로퍼티를 사용하지 않고 재정의 가능
프로젝트의 pom.xml 을 열어서 <version>태그를 변경하면 버전만 변경된 것이 아니라 스타터가 관리하는 수많은 의존성 역시 호환 가능한 버전으로 자동 변경된다.
- 프로퍼티 재정의
스타터가 제공하는 라이브러리중에 특정 프레임워크의 버전만 변경하고 싶은 경우 부모로부터 상속받은 프로퍼티만 재정의 하면 된다.
<properties> 하위에 바꾸고 싶은 속성태그를 재정의
스프링 부트의 자동설정
[자동설정 이란?]
@SpringBootApplication : 복잡한 환경설정 없이도 웹 애플리케이션을 만들고 실행시켜주는 어노테이션. 자동설정 기능이 동작하여 수많은 빈들이 등록되고 동작한다.
SpringBootApplication.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
//생략
}
@EnableAutoConfiguration, @ComponentScan 스프링 컨테이너 초기화와 관련된 어노테이션
@ComponentScan
@Configuration, @Repository, @Service, @Controller, @RestController가 붙은 객체를 메모리에 올리는 역할을 한다. excludeFilters에 해당하는 클래스를 제외하고 나머지 객체들을 스캔해서 초기화하도록 설정. 내가 만든 컨트롤러 객체를 메모리에 올리는 작업
@EnableAutoConfiguration
자동설정과 관련된 어노테이션. 스프링부트는 스프링 컨테이너를 구동시 두단계로 나누어 객체를 생성함. 스프링부트의 meta 파일(spring.factories)을 읽어서 미리 정의된 자바 설정 파일(@Configuration)들을 빈으로 등록하는 역할.
- spring.factories : 스프링부트의 메타데이터가 저장된 파일
- 자동 설정 기능 제공 모듈: 설정을 제공하는 @Configuration 적용 클래스 구현
- 자동 설정 기능 제공 모듈: spring.factories 파일 작성
- 적용: 자동 설정이 필요한 프로젝트에서 모듈에 대한 의존 추가
- Maven Dependencies > spring-boot-autoconfigure-2.2.2.RELEASE.jar 에 @EnableAutoConfiguration이 포함되어 있다.
이 jar 파일안에 있는 spring.factories를 열면 보이는 # Auto Configure 설정이 있다.
수많은 환경설정 클래스들은 모두 스프링 빈 설정파일로서 @Configuration 을 가지고 있다.
각 클래스에는 스프링부트가 지원하는 기능들이 모듈별로 설정되어 있다.
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
… 생략
이 중에서 WebMvcAutoConfiguration 클래스를 분석해보자
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
//생략
}
@Configuration 어노테이션은 클래스가 스프링 빈 설정 클래스임을 의미한다.
@ComponentScan이 처리될 때 자신뿐만아니라 이 클래스에 @Bean으로 설정된 모든 빈들도 초기화 진행
@SpringBootConfiguration = @Configuration
환경설정 빈 클래스를 표현하기 위해 사용. 스프링부트 환경설정 클래스임을 표현하기 위해 이름만 변경.
@SpringBootConfiguration를 @Configuration로 변경하여 실행해도 결과 동일
@ConditionalOnWebApplication(type = Type.SERVLET)
웹 어플리케이션 타입이 어떻게 설정되어 있느냐를 확인하는 어노테이션. type 속성값이 SERVLET일때만 설정 적용
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
특정 클래스가 클래스 패스에 존재할 때, 현재 설정 클래스를 적용하라는 의미.
Servlet, DispatcherServlet, WebMvcConfigurer 클래스가 있을 경우 현재 애플리케이션이 웹 기반.
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
특정 클래스 객체가 메모리에 없을때 현재 설정 클래스를 적용하라는 의미.
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
자동 설정 클래스들으 우선순위를 지정할때 사용. 현재 가장 높은 우선순위에서 10단계 더 높여 설정
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class })
현재의 자동설정 클래스가 다른 자동설정 클래스 다음에 적용되도록 지정.
[사용자 정의 스타터]
스프링부트의는 범용적인 프로젝트 개발을 목표로 설계되어, 특정 도메인이나 비즈니스에 특화되어 있지 않다.
스프링 부트가 사용하는 기존 스타터나 자동설정과 동일한 네이밍룰을 따르는 게 좋다.
사용자 정의 스타터를 만들기위해 Maven project 생성 > pom.xml에 자동설정을 하기위한 라이브러리 추가.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
추가되는 라이브러리들의 버전을 일괄적으로 관리하고 싶으면 dependencyManagement 설정을 추가한다. 부모 pom파일에 정의된 설정정보를 상속받을 수 있다. dependency설정의 version을 제거해도 자동으로 부모 파일에서 속된 프로퍼티 정보들이 적용된다.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
자동설정을 구현해보자.
1. BoardConfiguration 객체 생성
package com.studyboot.jdbc.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.studyboot.jdbc.util.JDBCConnectionManager;
// @Configuration을 가지고 있으므로 자동으로 빈 등록. 빈 등록시 @Bean설정들도 객체로 등록
@Configuration
// 활성화할 프로퍼티 클래스를 지정할 때 사용
@EnableConfigurationProperties(JDBCConncetionManagerProperties.class)
public class BoardAutoConfiguration {
@Autowired // 의존성 주입하여 사용가능
private JDBCConncetionManagerProperties properties;
@Bean
public JDBCConnectionManager getJdbcConnectionManager() {
JDBCConnectionManager manager = new JDBCConnectionManager();
manager.setDriverClass("oracle.jdbc.driver.OracleDriver");
manager.setUrl("jdbc:oracle:thin:@localhost:1521:xe");
manager.setUsername("friday");
manager.setPassword("friday");
return manager;
}
}
2. JDBCJDBCConnectionManager 객체 생성
package com.studyboot.jdbc.util;
import java.sql.Connection;
import java.sql.DriverManager;
// 특정 데이터베이스와 커넥션을 관리하기 위한 멤버변수 소유
public class JDBCConnectionManager {
private String driverClass;
private String url;
private String username;
private String password;
public void setDriverClass(String driverClass) {
this.driverClass = driverClass;
}
public void setUrl(String url) {
this.url = url;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
// 커넥션 객체를 리턴
public Connection getConnection() {
try {
Class.forName(driverClass);
return DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer("JDBCConnectionManager [driverClass=");
sb.append(driverClass)
.append(",url=").append(url)
.append(",username=").append(username)
.append(",password=").append(password)
.append("]");
return sb.toString();
}
}
3. sping.factories 파일 생성
메이븐 프로젝트 빌드하기 : Run As > Maven Install
메이븐으로 프로젝트를 빌드할 때 package나 install을 실행할 수 있다.
- package : target 폴더에 jar파일 생성
- install : 다른프로젝트에서 현재 프로젝트를 사용할 수 있도록 메이븐 로컬 리포지터리에도 등록해준다.
- 생성경로 : C:\Users\사용자이름\.m2\repository\com\studyboot\board-spring-boot-starter
다른 프로젝트에 적용시 POM파일에 dependency를 입력하고 메이븐 업데이트를 진행해보자. 내가 정의한 스타터가 반영되어 모듈이 추가된것을 확인 가능하다.
<dependency>
<groupId>com.studyboot</groupId>
<artifactId>board-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
컨테이너가 컴포넌트 스캔할 수 있도록 @Service 어노테이션을 추가하자. ApplicationRunner를 구현했으므로 객체가 생성되자마자 run 메소드를 수행한다.
package com.studyboot.jdbc.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service;
@Service
public class JDBCConnectionManagerRunner implements ApplicationRunner {
@Autowired
private JDBCConnectionManager connectionManager;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("커넥션 매니저" + connectionManager.toString());
}
}
[자동설정 재정의하기]
- 빈 재설정
자동설정의 내용을 변경하고 싶으면 해당 프로젝트안에서 설정 클래스를 생성한다(@Configuration).
package com.studyboot.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.studyboot.jdbc.util.JDBCConnectionManager;
@Configuration
public class BoardConfiguration {
// 자동설정한 내용이 아닌 프로젝트내에서 DB설정을 특정값으로 변경하고 싶을 경우
@Bean
public JDBCConnectionManager getJDBConnectionManager() {
JDBCConnectionManager manager = new JDBCConnectionManager();
manager.setDriverClass("org.h2.Driver");
manager.setUrl("jdbc:h2:tcp://localhost/~/test");
manager.setUsername("h2");
manager.setPassword("h2");
return manager;
}
}
이전에 생성된 빈을 새로게 생성한 빈이 덮어 쓸수 있도록 application.properties 파일에 아래와 같이 설정을 추가하면 된다.
메모리에 동일한 타입의 빈이 등록되어 있으면 새로운 빈이 기존의 빈을 덮어쓰도록 하는 설정이다.
spring.main.allow-bean-definition-overriding=true
빈 중복 등록으로 인한 오류 발생 메세지
Field connectionManager in com.studyboot.jdbc.util.JDBCConnectionManagerRunner required a single bean, but 2 were found:
- getJDBConnectionManager: defined by method 'getJDBConnectionManager' in class path resource [com/studyboot/config/BoardConfiguration.class]
- getJdbcConnectionManager: defined by method 'getJdbcConnectionManager' in class path resource [com/studyboot/jdbc/config/BoardAutoConfiguration.class]
- @Conditional 어노테이션 활용하기
@Conditional
조건에 따라 새로운 객체를 생성할지 말지 결정할 수 있다.
@ConditionalOnMissingBean
등록하려는 빈이 메모리에 없는 경우에만 현재의 빈을 처리하도록 한다. 자동설정 클래스에 해당 어노테이션을 붙여주면 프로젝트내에 동일한 타입 빈이 없을때 자동등록시 빈을 생성.
1. 사용자가 정의한 @Configuration은 @ComponentScan에 의해 먼저 등록된다.
2. 자동설정인 @EnableAutoConfiguration이 동작하는 시점에는 이미 등록된 빈을 사용하고 새롭게 빈 생성 진행하지않음
사용자 정의한 스타터에 있는 BoardAutoConfiguration 클래스에 @ConditionalOnMissingBean 어노테이션을 작성한다.
BoardAutoConfiguration.java
@Configuration
public class BoardAutoConfiguration {
@Autowired
private JDBCConncetionManagerProperties properties;
@Bean
@ConditionalOnMissingBean
public JDBCConnectionManager getJdbcConnectionManager() {
//생략
}
}
-프로퍼티 파일 이용하기
<context:place-holder> 태그는 외부 프로퍼티를 이용하여 객체를 생성 가능하게 한다. 외부 설정 파일을 주입해서 객체 생성하는 방법을 실행해보자. 먼저 프로젝트의 프로퍼타 파일에 데이터베이스 관련 프로퍼티를 추가한다.
# Bean overriding 설정
spring.main.allow-bean-definition-overriding=true
# 데이터 소스 : h2
board.jdbc.driverClass=org.h2.Driver
board.jdbc.url=jdbc:h2:tcp://localhost/~/test
board.jdbc.username=h2
board.jdbc.password=h2
프로젝트내에 환경설정 객체가 생성되지 않도록 어노테이션을 주석처리한다.
//@Configuration
public class BoardConfiguration {
// 자동설정한 내용이 아닌 프로젝트내에서 DB설정을 특정값으로 변경하고 싶을 경우
//@Bean
public JDBCConnectionManager getJDBConnectionManager() {
//생략
}
}
스타터 프로젝트에 프로퍼티 클래스를 추가로 작성한다. @ConfigurationProperties(prefix = "board.jdbc")
package com.studyboot.jdbc.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "board.jdbc")
public class JDBCConncetionManagerProperties {
private String driverClass;
private String url;
private String username;
private String password;
//getter, setter 생략
}
When using @ConfigurationProperties it is recommended to add 'spring-boot-configuration-processor' to your classpath to generate configuration metadata [@ConfigurationProperties를 사용하려면 해당 모듈에 대한 의존성 주입 필요하다.]
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
<version>2.2.2.RELEASE</version>
</dependency>
@EnableConfigurationProperties(JDBCConncetionManagerProperties.class)
스타터 프로젝트에 있는 BoardAutoConfiguration 클래스에 해당 어노테이션을 작성해준다. 이 어노테이션은 활성화할 프로퍼티 클래스를 지정할 때 사용한다.
BoardAutoConfiguration.java
@Configuration
@EnableConfigurationProperties(JDBCConncetionManagerProperties.class)
public class BoardAutoConfiguration {
@Autowired
private JDBCConncetionManagerProperties properties;
@Bean
@ConditionalOnMissingBean
public JDBCConnectionManager getJdbcConnectionManager() {
manager.setDriverClass(properties.getDriverClass());
manager.setUrl(properties.getUrl());
manager.setUsername(properties.getUsername());
manager.setPassword(properties.getPassword());
return manager;
}
}
요약
자동설정기능은 기본적인 설정은 자동으로 진행하고 필요한 만큼의 기능은 재정의해서 사용가능하다
사용자 정의 스타터를 통해 특정 환경에서만 사용하는 기능들을 자동으로 처리가능하다
참고 서적 : 누구나 끝까지 따라 할 수 있는 스프링 부트 퀵스타트
https://cornswrold.tistory.com/314
https://javacan.tistory.com/entry/spring-boot-auto-configuration
'Dev > SpringBoot' 카테고리의 다른 글
[Springboot] 스프링부트 화면 개발 (0) | 2020.01.01 |
---|---|
[SpringBoot] 스프링 데이터 JPA (0) | 2019.12.28 |
[SpringBoot] JPA 퀵 스타트 (0) | 2019.12.23 |
[SpringBoot] 테스트와 로깅 (0) | 2019.12.18 |
[SpringBoot] 스프링부트 시작하기 (0) | 2019.12.11 |