> For the complete documentation index, see [llms.txt](https://dodeon.gitbook.io/study/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dodeon.gitbook.io/study/keesunbaik-concepts-of-spring-boot/03-principle/auto-configuration.md).

# 자동 설정

## @SpringBootApplication

빈은 두 단계로 나눠서 읽힌다.

1. @ComponentScan
2. @EnableAutoConfiguration

### @SpringBootConfiguration

* 사실상의 @Configuration

### @ComponentScan

* 컴포넌트 애너테이션이 달린 클래스를 빈으로 등록한다.
* @Component, @Configuration, @Repository, @Service, @Controller, @RestController

### @EnableAutoConfiguration

* 컴포넌트 스캔으로 등록한 후 다시 한 번 빈을 읽어와 등록한다.
* 즉, 없어도 스프링 부트를 사용할 수 있다.
  * 단, 웹 애플리케이션 설정을 꺼줘야 가능
* 결국 이것도 @Configuration을 가지고 있다.
  1. spring.factories 라는 메타 파일을 읽어들인다.
  2. 메타 파일의 키 값을 보고 설정을 읽는다.
  3. 조건에 따라 빈이 생성되거나 생성되지 않는다.

## 예제

### 설정 만들기

우선 별도의 프로젝트를 새로 판다.

{% tabs %}
{% tab title="pom.xml" %}

```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>
</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>
```

{% endtab %}

{% tab title="Holoman.java" %}

```java
public class Holoman {

    String name;

    int howLong;

    @Override
    public String toString() {
        return "Holoman{" +
                "name='" + name + '\'' +
                ", howLong=" + howLong +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getHowLong() {
        return howLong;
    }

    public void setHowLong(int howLong) {
        this.howLong = howLong;
    }
}
```

{% endtab %}

{% tab title="HolomanConfiguration.java" %}

```java
@Configuration
public class HolomanConfiguration {

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

        return holoman;
    }
}
```

{% endtab %}

{% tab title="spring.factories" %}

```
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  me.whiteship.HolomanConfiguration
```

{% endtab %}
{% endtabs %}

1. 의존성을 추가한다.
2. @Configuration 파일을 작성한다.
3. `src/main/resource/META-INF`에 spring.factories를 생성한다.
4. 안에 자동 설정 파일을 추가한다.
5. `mvm install`을 실행한다.

### 설정 적용하기

{% tabs %}
{% tab title="pom.xml" %}

```xml
<dependency>
    <groupId>me.whiteship</groupId>
    <artifactId>keesunbaik-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
```

{% endtab %}
{% endtabs %}

![](/files/qdfKYzsEIKyRZPd9TgMQ)

기존 프로젝트로 돌아와 의존성을 적용하면 라이브러리가 나타난다.

{% tabs %}
{% tab title="HolomanRunner.java" %}

```java
@Component
public class HolomanRunner implements ApplicationRunner {

    @Autowired
    Holoman holoman;

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

{% endtab %}
{% endtabs %}

```
holoman = Holoman{name='Keesun', howLong=5}
```

Holoman을 어디서도 정의한 적이 없지만 사용할 수 있게 되었다.

### 설정 재정의 하기

```java
@SpringBootApplication
public class ConceptsOfSpringBootApplication {

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

    @Bean
    public Holoman holoman() {
        Holoman holoman = new Holoman();
        holoman.setName("whiteship");
        holoman.setHowLong(50);
        return holoman;
    }
}
```

하지만 빈을 다시 설정하려고 하면 기존 값 그대로 나온다

**스프링 부트 2.1부터는 오버라이딩 하지 못하고 에러가 뜬다.**

1. 컴포넌트 스캔이 먼저 동작한다
   * @Bean이 먼저 동작한다.
2. @AutoConfiguration으로 다시 등록한다.
   * @Bean 내용을 덮어 쓴다.

{% tabs %}
{% tab title="HolomanConfiguration.java" %}

```java
@Configuration
public class HolomanConfiguration {

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

        return holoman;
    }
}
```

{% endtab %}
{% endtabs %}

다시 설정 프로젝트 쪽으로 돌아가서 @ConditionalOnMissingBean을 달아준다.

* @ConditionalOnMissingBean
* 해당 타입의 빈이 없을 때만 이 빈을 등록하라는 뜻이 된다.

{% tabs %}
{% tab title="pom.xml" %}

```xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
```

{% endtab %}

{% tab title="application.properties" %}

```properties
holoman.name=whiteship
holoman.how-long=55
```

{% endtab %}

{% tab title="HolomanProperties.java" %}

```java
@ConfigurationProperties("holoman")
public class HolomanProperties {

    private String name;

    private int howLong;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getHowLong() {
        return howLong;
    }

    public void setHowLong(int howLong) {
        this.howLong = howLong;
    }
}
```

{% endtab %}

{% tab title="HolomanConfiguration.java" %}

```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;
    }
}
```

{% endtab %}
{% endtabs %}

* 설정 프로젝트에서 값을 설정할 때 빈에서 직접 하는 대신 properties에서 가져다 쓸 수도 있다.
* 본 프로젝트에서 properties에 값을 추가하면 그대로 반영된다.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dodeon.gitbook.io/study/keesunbaik-concepts-of-spring-boot/03-principle/auto-configuration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
