SPRING

[Spring] Custom AutoConfiguration 만들어보기

sagecode 2025. 4. 10. 17:23

AutoConfiguration이란?

Spring Legacy와 Spring Boot의 가장 큰 차이점 중 하나는 설정 방식입니다.  
기존의 Spring에서는 XML이나 Java Config를 통해 직접 모든 Bean을 등록해야 했지만,  Spring Boot는 AutoConfiguration을 통해 필요한 Bean을 상황에 맞게 자동으로 등록해줍니다.  

Auto-configuration을 사용하고 싶다면 @EnableAutoConfiguration 또는 @SpringBootApplication 어노테이션을 @Configuration 클래스 중 하나에 추가하면 됩니다.

 

간단한 AutoConfiguration 만들기

실제로 나만의 AutoConfiguration 클래스를 만들어보겠습니다. 한국말로 "안녕하세요"라는 인사말을 반환하는 'Greet' 클래스를 만들어보고,  이걸 다른 프로젝트에서 자동으로 빈으로 등록되도록 구성해보려고 합니다.

 

  • Greet 클래스
public class Greet {

    public String korean() {
        return "안녕하세요";
    }
}
  • GreetAutoConfig 클래스

@AutoConfiguration을 붙여서 Spring이 이 클래스를 설정으로 인식하게 합니다.

import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;

@AutoConfiguration
public class GreetAutoConfig {

    @Bean
    public Greet greet() {
        return new Greet();
    }
}
  • 자동설정 등록

마지막으로 이 설정이 Spring Boot에 자동으로 인식되게 하기 위해
resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 파일을 생성하고, 아래 내용을 추가합니다.

org.example.GreetAutoConfig
  • DB 연결 오류
Caused by: org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException

자동설정을 마친이후에 서버를 켜보았는데 이런 오류가 떴다.

 

현재 이 프로젝트는 AutoConfiguration 모듈을 만들고 있어서, Spring Boot가 자동으로 DataSource 등을 로드하려고 시도하고 실패한 것입니다.

 

@SpringBootApplication(exclude = {
    org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.class
})
public class CustomAutoconfigApplication {
    public static void main(String[] args) {
        SpringApplication.run(CustomAutoconfigApplication.class, args);
    }
}

만약 DB 관련 설정을 테스트하고 싶은 거라면 application.yml 또는 application.properties에 DB 설정을 추가하면 됩니다.

 

Local에서 다른 프로젝트에 Custom AutoConfiguration 적용해보기

1. 현재 프로젝트를 install 해두기

./gradlew clean build publishToMavenLocal

터미널에 이렇게 작성하게 되면  ~/.m2/repository에 로컬 Maven 저장소에 올라갑니다.

  • publishToMavenLocal 미 정의 오류
Task 'publishToMavenLocal' not found

maven-publish 플러그인이 설정되지 않았기 때문에 이런 오류가 발생합니다.

 

build.gradle 파일 plugins 블록에 플러그인 추가를 통해 오류를 해결합니다.

plugins {
    id 'java'
    id 'maven-publish' // 추가
}

group = 'org.example'
version = '1.0-SNAPSHOT'

publishing { // 추가
    publications {
        mavenJava(MavenPublication) {
            from components.java
        }
    }
}

<build.gradle>

 

성공하면 로컬 Maven 저장소(~/.m2/repository/org/example/custom-autoconfig/1.0-SNAPSHOT/)에 .jar파일로 저장됩니다.

 

2. 다른 Spring Boot 프로젝트에서 의존성 추가

다른 프로젝트의 build.gradle에 이렇게 추가

dependencies {
    implementation 'org.example:custom-autoconfig:1.0-SNAPSHOT'
}

<build.gradle>

 

repositories {
    mavenLocal() // 추가
    mavenCentral()
}

mavenLocal()을 추가해야 publishToMavenLocal로 배포된 로컬 라이브러리를 인식할 수 있습니다.

이게 의존성을 추가했으니 Controller에서 Custom한 autoConfiguration을 사용해 봅시다.

 

@RestController
public class HelloController {

    private final Greet greet;

    public HelloController(Greet greet) {
        this.greet = greet;
    }

    @GetMapping("/hello")
    public String hello() {
        return greet.korean();
    }
}

<HelloController.java>

3. HelloControllerTest 만들기

package com.example.common.controller;

import org.example.Greet;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;

import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@WebMvcTest(HelloController.class)
public class HelloControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private Greet greet;

    @Test
    void helloKorean_shouldReturnGreeting() throws Exception {
        // given
        given(greet.korean()).willReturn("안녕하세요");

        // when & then
        mockMvc.perform(get("/hello"))
                .andExpect(status().isOk())
                .andExpect(content().string("안녕하세요"));
    }
}

잘 연결이 되었다면 밑에 사진처럼 테스트 성공 알림이 뜬다.