스프링 부트에서는 애플리케이션에서 필요한 속성을 "애플리케이션 구성파일" application.yml
(혹은 applicatoin.properties
) 에 작성하여 활용합니다.
Note
|
데이터구조를 계층형으로 표현할 수 있어서 개인적으로 |
.yaml |
.properties |
---|---|
environments:
dev:
url: "https://dev.example.com"
name: "Developer Setup"
prod:
url: "https://another.example.com"
name: "My Cool App" |
environments.dev.url=https://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=https://another.example.com
environments.prod.name=My Cool App |
my:
servers:
- "dev.example.com"
- "another.example.com" |
my.servers[0]=dev.example.com
my.servers[1]=another.example.com |
이렇게 표현식을 비교해봤을 때 보다 눈에 잘 들어오는 편입니다(가독성이 높다라고 생각합니다).
그리고 이런 표현식을 이용해서 application.yml
에 다음과 같이 활용할 수 있습니다. application-keycloak.yml
를 작성해보겠습니다.
Note
|
스프링 부트 2.4 부터 애플리케이션 구성파일( |
application.yml
spring:
profiles:
group:
local: "keycloak-local, db-local"
dev: "keycloak-deve, db-dev"
beta: "keycloak-beta, db-beta"
prod: "keycloak-prod, db-prod"
include: "keycloak"
application-keycloak.yml
spring:
config:
activate:
on-profile: "keycloak-local,keycloak-test"
keycloak:
url: "https://test-keycloak.localtest.com"
username: "honeymon-local"
password: "password-local"
store-maps:
"DEFAULT_REALM": "honeymon-local"
"DEFAULT_TOPIC": "topic"
---
spring:
config:
activate:
on-profile: "keycloak-dev"
keycloak:
url: "https://test-keycloak.devtest.com"
username: "honeymon-dev"
password: "password-dev"
store-maps:
"DEFAULT_REALM": "honeymon-dev"
"DEFAULT_TOPIC": "topic-dev"
---
spring:
config:
activate:
on-profile: "keycloak-beta"
keycloak:
url: "https://test-keycloak.betatest.com"
username: "honeymon-beta"
password: "password-beta"
store-maps:
"DEFAULT_REALM": "honeymon-beta"
"DEFAULT_TOPIC": "topic-beta"
---
spring:
config:
activate:
on-profile: "keycloak-prod"
keycloak:
url: "https://test-keycloak.test.com"
username: "honeymon-prod"
password: "password-prod"
store-maps:
"DEFAULT_REALM": "honeymon-prod"
"DEFAULT_TOPIC": "topic-prod"
다음과 같이 작성된 application-keycloak.yml
에 대응하는 @ConfigurationProperties
클래스를 다음과 같이 작성했습니다.
KeyCloakConfigurationProperties
@Getter
@ConfigurationProperties("keycloak")
public class KeyCloakConfigurationProperties {
private final String url;
private final String username;
private final String password;
private final Map<String, String> storeMaps;
@ConstructorBinding
public KeyCloakConfigurationProperties(String url, String username, String password, Map<String, String> storeMaps) {
this.url = url;
this.username = username;
this.password = password;
this.storeMaps = storeMaps;
}
}
이렇게 작성된 @ConfigurationProperties
클래스는 spring-boot-configuration-processor
를 이용하면 개발도구에서 자동완성에 이용할 수 있는 META-INF/spring-configuration-metadata.json
를 생성할 수 있습니다.
Note
|
보다 자세한 내용은 "스프링 부트 참고문서#Appendix B: Configuration Metadata"를 살펴시기 바랍니다. |
작성된 @ConfigurationProperties
클래스 KeyCloakConfigurationProperties
는 다음과 같은 방식으로 테스트할 수 있습니다.
//KeyCloakConfigurationPropertiesDevTest
@ActiveProfiles("dev")
@SpringBootTest
class KeyCloakConfigurationPropertiesDevTest {
@Autowired
KeyCloakConfigurationProperties keyCloakConfigurationProperties;
@Test
void testProperty() {
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(keyCloakConfigurationProperties.getUrl()).isEqualTo("https://test-keycloak.devtest.com");
softly.assertThat(keyCloakConfigurationProperties.getUsername()).isEqualTo("honeymon-dev");
softly.assertThat(keyCloakConfigurationProperties.getPassword()).isEqualTo("password-dev");
softly.assertThat(keyCloakConfigurationProperties.getStoreMaps().get("DEFAULT_REALM")).isEqualTo("honeymon-dev");
});
}
}
//KeyCloakConfigurationPropertiesBetaTest
@ActiveProfiles("beta")
@SpringBootTest
class KeyCloakConfigurationPropertiesBetaTest {
@Autowired
KeyCloakConfigurationProperties keyCloakConfigurationProperties;
@Test
void testProperty() {
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(keyCloakConfigurationProperties.getUrl()).isEqualTo("https://test-keycloak.betatest.com");
softly.assertThat(keyCloakConfigurationProperties.getUsername()).isEqualTo("honeymon-beta");
softly.assertThat(keyCloakConfigurationProperties.getPassword()).isEqualTo("password-beta");
softly.assertThat(keyCloakConfigurationProperties.getStoreMaps().get("DEFAULT_REALM")).isEqualTo("honeymon-beta");
});
}
}
////KeyCloakConfigurationPropertiesProdTest
@ActiveProfiles("prod")
@SpringBootTest
class KeyCloakConfigurationPropertiesProdTest {
@Autowired
KeyCloakConfigurationProperties keyCloakConfigurationProperties;
@Test
void testProperty() {
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(keyCloakConfigurationProperties.getUrl()).isEqualTo("https://test-keycloak.test.com");
softly.assertThat(keyCloakConfigurationProperties.getUsername()).isEqualTo("honeymon-prod");
softly.assertThat(keyCloakConfigurationProperties.getPassword()).isEqualTo("password-prod");
softly.assertThat(keyCloakConfigurationProperties.getStoreMaps().get("DEFAULT_REALM")).isEqualTo("honeymon-prod");
});
}
}
요런 식으로 해서 애플리케이션 구성파일을 작성하고 @ConfigurationProperties
빈을 작성하여 애플리케이션 구성파일 데이터를 활용할 수 있습니다.
"느슨한 연결(Relaxed Binding)"을 지원하기 때문에 다음과 같이 표현해도 스프링 부트가 SnakeYaml 로 읽어온 속성과 @ConfigurationProperties
빈의 필드를 매핑하여 주입합니다.
application-keycloak.yml`
keycloak:
url: "https://test-keycloak.localtest.com"
username: "honeymon-local"
password: "password-local"
store-maps: // 요렇게 해도!
"DEFAULT_REALM": "honeymon-local"
"DEFAULT_TOPIC": "topic"
---
keycloak:
url: "https://test-keycloak.localtest.com"
username: "honeymon-local"
password: "password-local"
storeMaps: // 요렇게 해도!
"DEFAULT_REALM": "honeymon-local"
"DEFAULT_TOPIC": "topic"
앞서 작성한 KeyCloakConfigurationProperties
를 스프링 애플리케이션 컨텍스트에 적재하는 방법은 다음과 같습니다.
@Configuration
@EnableConfigurationProperties({KeyCloakConfigurationProperties.class}) // (1)
public class AppConfiguration {}
@Configuration
@ConfigurationPropertiesScan // (2)
public class AppConfiguration {}
@Component // (3)
@ConfigurationProperties("keycloak")
public class KeyCloakConfigurationProperties {
// 코드 생략
}
-
활성화할
ConfigurationProperties
클래스를 명시적으로 지정하는 방법 -
@ComponentScan
과 유사한 방식으로@ConfigurationProperties
를 탐색하여 적재하는 방법 -
@Component
애노테이션을 선언하여 컴포넌트 빈으로 적재하도록 하는 방법
의존성 주입방식은 크게 3가지 방식이 있습니다.
-
@Autowired
선언 필드 주입방식 -
설정자(setter 메서드) 주입방식
-
생성자 주입방식
위 3가지 방법중에는 "생성자 주입방식"를 가장 높게 평가합니다. "`@Autowired` 선언 필드 주입방식" 은 권장하지 않습니다. 테스트 코드에서도 이런 방식으로 변경할 수 있습니다. 설정자 방식은 누락할 수 있다는 단점이 있습니다.
@ActiveProfiles("prod")
@SpringBootTest
class KeyCloakConfigurationPropertiesProdTest {
@Autowired KeyCloakConfigurationProperties keyCloakConfigurationProperties; // @Autowired 필드 주입
}
@ActiveProfiles("prod")
@SpringBootTest
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL) // 테스트에서 조차....
class KeyCloakConfigurationPropertiesProdTest {
private final KeyCloakConfigurationProperties keyCloakConfigurationProperties;
public KeyCloakConfigurationPropertiesProdTest(KeyCloakConfigurationProperties keyCloakConfigurationProperties) {
this.keyCloakConfigurationProperties = keyCloakConfigurationProperties;
}
}
기존에 @Value
애노테이션을 이용해서 Environment 에 등록된 값을 주입하던 방식도 다음과 같이 ConfigurationProperties 빈을 주입하여 사용할 수 있다.
@Service
public class SomeService {
@Value("${keycloak.username}")
private String username;
@Value("${keycloak.password}")
private String password;
public void print() {
System.out.println(username);
System.out.println(password);
}
}
적재된 @ConfigurationProperties
빈은 일반 스프링 빈과 동일하게 "의존성 주입(Dependency Injection)"을 활용할 수 있습니다.
@Service
public class SomeService {
private final KeyCloakConfigurationProperties keyCloakConfigurationProperties;
public SomeService(KeyCloakConfigurationProperties keyCloakConfigurationProperties) { // 생성자 주입방식 활용
this.keyCloakConfigurationProperties = keyCloakConfigurationProperties;
}
public void print() {
System.out.println(keyCloakConfigurationProperties.getUsername());
System.out.println(keyCloakConfigurationProperties.getPassword());
}
}
좋은 자료 감사합니다🙇