본문 바로가기

더 나은 엔지니어가 되기 위해/지금은 안쓰는 자바

[스프링 부트 개념과 활용] 의존성 관리, 자동 설정 이해

이 글은 인프런에서 백기선님의 스프링부트 개념과 활용 강의를 듣고, 개인적으로 공부하며 핵심만 정리한 글입니다.

의존성 관리

1) pom.xml 에서의 parent

pom.xml 내부를 살펴보면, 다음과 같은 부분이 있다.

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.2.4.RELEASE</version>
</parent>

spring-boot-starter-parent 는 스프링 프레임워크가 제공해주는 것으로, 여기에 활용할 수 있는 많은 라이브러리 정보가 '이미' 담겨져 있다.

정확히는 spring-boot-starter-parentdependency 로 들어오는 외부 라이브러리들의 버전 및 각 라이브러리들의 의존성을 관리한다.

어떻게 관리하냐면, spring-boot-starter-parent.pom 에 가보면 org.springframework.bootversion 에 따른 각 dependency 라이브러리들의 version 이 정의되어 있다.

따라서, 우리는 spring-boot-starter-parent 의 버전만 version 에 명시해주면, 해당 버전과 호환되는 dependecny 라이브러리들을 따로 version 을 명시해주지 않아도, spring-boot-starter-parent 에 이미 선언된 버전으로 가져온다.

물론 dependency 내부에 version 을 명시해주면 해당 version 으로 오버라이딩 된다.

2) pom.xml 에서의 dependencies

pom.xml 내부를 살펴보면, 다음과 같은 부분이 있다.

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

parentversion 에 해당하는 version 으로 spring-boot-starter-web 와 의존하는 라이브러리들 모두 임포트한다. 의존하는 라이브러리들 역시 spring-boot-starter-web.pom 에 이미 다 선언되어 있기 때문에 따로 version 을 명시해줄 필요는 없다.
(다만 외부 라이브러리, 즉 spring-boot-starter-parent) 가 가지고 있지않은 라이브러리 목록은 버전을 명시해줘야 한다.

3) pom.xml 기본 템플릿

공식 사이트의 Getting Started 페이지 에서 다음과 같이 기본 maven 템플릿을 제공해줌.
(Spring Initializr 으로 만들면 기본적으로 포함되어 있음)

자동 설정 이해

1) Application.java

스프링 부트 프로젝트는 별도의 설정없이 바로 실행 가능한데, 이 실행의 구동부인 Application.java 를 살펴보면 다음과 같다.

@SpringBootApplication
public class Application {

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }

위 코드에서 @SpringBootApplication 을 좀 더 풀어보면 다음과 같다.

@Configuration
@ComponentScan
@EnableAutoConfiguration
  1. Application.java 자체를 Config 파일로 인식시키고,
  2. 패키지 내 모든 Component 를 스캔하며,
  3. 필요한 자동 설정을 한다.

이 때, @EnableAutoConfiguration 에 대해서 좀 더 살펴보자.

2) @EnableAutoConfiguration

가져온 외부 라이브러리 목록을 보면 org.springframework.boot:spring-boot-autoconfigure 패키지가 있다.
해당 패키지 내 META-INF/spring.factories 를 보면 자동 설정 대상이 되는 클래스들이 정의되어 있다. 여기서 자동 설정이란, 조건에 따른 Bean 등록, Path 설정 등의 기본 설정을 말한다.
이는 미리 정의해놓은 값이다. (편의를 위해 스프링 부트가 미리 해놓은 설정)

# 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,\

...

즉 여기에 포함되는 라이브러리들은 기본 값 자동 설정이 지원된다.

자동 설정 만들어보기

별도의 자동설정 파일을 만들어, 기존 프로젝트의 @EnableAutoConfiguration 에 포함되도록 해보자.
먼저 별도의 maven 프로젝트, heumsi-spring-boot-starter 생성한다.

1) dependency 추가

pom.xml 에 자동 설정을 위한 별도의 라이브러리를 다음과 같이 추가한다.

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure-processor</artifactId>
    <optional>true</optional>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
  </dependency>
</dependencies>
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>2.0.3.RELEASE</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

2) 추가할 Bean Class 작성 및 등록

src/main/java/me/heumsi/ 패키지 내에 사용할 Bean Class 를 작성하고, Bean 등록을 한다.

// Holoman.java

public class Holoman {

  String name;
  int howLong;

  public String getName() {
    return name;
  }

  ...
}
// HolomanConfiguration.java

@Configuration
public class HolomanConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public Holoman holoman() {
        Holoman holoman = new Holoman();
        holoman.setHowLong(5);
        holoman.setName("Heumsi");

        return holoman;
    }
}

3) EnableAutoConfiguration 에 등록

src/main/resources/META-INFspring.factories 를 만들고, 여기에 다음과 같이 우리가 만든 빈 설정파일을 등록한다.

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  me.heumsi.HolomanConfiguration

4) maven install 로 로컬 저장소에 패키지 저장

maven install 명령어로 (혹은 IDE) 이렇게 만든 패키지를 로컬 maven 저장소에 저장한다.

5) 기존 프로젝트에 추가

이제 이 설정을 자동으로 가져올 기존의 프로젝트로 돌아가자.
먼저 pom.xmldependency 에 위에서 만든 heumsi-spring-boot-starter 를 추가하자.

<dependency>
  <groupId>me.heumsi</groupId>
  <artifactId>heumsi-spring-boot-starter</artifactId>
  <version>1.0-SNAPSHOT</version>
</dependency>

6) 확인

Application.java 를 다음과 같이 바꾸고 ApplicationRunner 를 통해 자동설정이 잘 되었는지 직접 확인해볼 수 있다.

// Application.java

public static void main(String[] args) {
  SpringApplication application = new SpringApplication(Application.class);
  application.setWebApplicationType(WebApplicationType.NONE);
  application.run(args);
// HolomanRunner.java

@Component
public class HolomanRunner implements ApplicationRunner {

    @Autowired
    Holoman holoman;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(holoman);
    }
}

이제 Application.java 를 Run 하면 다음과 같이 Bean 설정한 대로, 잘 뜨는 것을 확인할 수 있다.

Holoman{name='heumsi', howLong=5}

Properties 을 통해 Bean 설정 쉽게 바꾸기

여기서 위에서 만든 Bean 설정을 기존 프로젝트의 properies 파일로 손쉽게 바꾸는 방법을 알아보자.
지금까지는 HolomanConfiguration.java 에서 Bean 설정을 했다면, 이제는 application.properties 에서 단 몇 줄의 코드로 Bean 설정 값을 바꿀 수 있다.

1) Properties 클래스 정의

heumsi-spring-boot-starter 프로젝트로가서, Holoman.java 와 같은 경로에 HolomanProperites.java 를 다음과 같이 추가하자.

@ConfigurationProperties("holoman")
public class HolomanProperties {
  private String name;
  private int howLong;

  public String getName() {
    return name;
  }
  ...
}

그리고 Bean 설정을 담당하고 있는 HolomanConfiguration.java 를 다음과 같이 수정하자.

@Configuration
@EnableConfigurationProperties(HolomanProperties.class)
public class HolomanConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public Holoman holoman(HolomanProperties properties) {
        Holoman holoman = new Holoman();
        holoman.setHowLong(properties.getHowLong());
        holoman.setName(properties.getName());

        return holoman;
    }
}

2) application.properties 에서 설정 값 입력

이제 다시 기존 프로젝트로 돌아와, src/main/resources/application.properties 파일을 다음과 같이 만들자.

holoman.name=heum
holman.how-long=2

3) 확인

다시 Application.java 을 구동하면 다음과 같이 application.properties 에서 정의한 대로 출력되는 것을 볼 수 있다.

Holoman{name='heum', howLong=2}