π Spring Boot profiles μ€μ νκΈ°
μλ νμΈμ, μ΄λ² ν¬μ€ν μμλ μ€νλ§ λΆνΈμμ μ¬λ¬ profileμ μ€μ νκ³ , μ€μ κ°λ€μ κ°μ²΄μ λ°μΈλ©νλ λ°©λ²μ λν΄ μ΄ν΄λ³΄κ² μ΅λλ€.
μ€μ κ°λ°μ μ§ννκ³ μ΄μμ νλ€λ³΄λ©΄ κ°λ°(dev), ν μ€νΈ(stage), μν(alpha), μμ©(prod) λ± μ΄μνκ²½μ λ°λΌ μλ²λ μ€μ κ°λ€μ΄ μ¬λ¬κ°λ‘ λλ μ μλλ°μ, μ€νλ§ λΆνΈμμλ μ΄λ¬ν μ€μ μ κ°λ¨ν ν μ μμ΅λλ€.
ν΄λΉ ν¬μ€ν μμλ yml νμΌμ κΈ°μ€μΌλ‘ μ€μ μ ν΄λ³΄κ² μ΅λλ€. π€―
π yml νμΌ μμ±νκΈ°
resource νμ ν΄λμ μμ±ν yml νμΌμ λ€μκ³Ό κ°μ΅λλ€.
π application.yml
spring:
profiles:
active:
- local
group:
local:
- site-local
- db-local
dev:
- site-dev
- db-dev
include:
- db
- my-service
- site
μ ν리μΌμ΄μ μ΄ μ€νλ λ κΈ°λ³Έμ μΌλ‘ μ°Έμ‘°νλ νμΌμΈλ°μ, κ° μ€μ λ€μ λ€μκ³Ό κ°μ΅λλ€.
- spring-profiles-active : κΈ°λ³Έμ μΌλ‘ νμ±νν profileμ localλ‘ μ€μ ν©λλ€.
- spring-profiles-group : profile groupμ μ μν μ μμ΅λλ€.
- local : profileμ΄ localμΌ κ²½μ° site-local, db-local μ profileκ³Ό κ·Έλ£Ήμ μ μν©λλ€.
- dev : profileμ΄ localμΌ κ²½μ° site-dev, db-dev μ profileκ³Ό κ·Έλ£Ήμ μ μν©λλ€.
- ν΄λΉ κ°λ€μ μλμμ λ€μ μ€λͺ λλ¦¬κ² μ΅λλ€.
- spring-profiles-include μ€μ μ ν΅ν΄ μ΄ν리μΌμ΄μ
μ μ€νν λ profileμ ν¬ν¨νμ¬ μ€νν μ μμ΅λλ€.
- μ¦ application-db.yml, application-my-site.yml, application-site.yml νμΌμ ν¨κ» profileμ ν¬ν¨νμ¬ μ΄ν리μΌμ΄μ μ΄ κ΅¬λλ©λλ€.
μ°Έκ³ λ‘, profile κ° λ³κ²½μ IntelliJ κΈ°μ€μΌλ‘ μλμ κ°μ΄ μ€μ ν μ μμ΅λλ€. π·
Run > Edit Configurations... > Active profiles
π application-db.yml
#default 곡ν΅μ€μ
spring:
jpa:
show-sql: false
open-in-view: false
database-platform: MYSQL
hibernate:
ddl-auto: none
use-new-id-generator-mappings: true
properties:
hibernate.format_sql: true
hibernate.show_sql: false
hibernate.dialect: org.hibernate.dialect.MySQL57Dialect
hibernate.default_fetch_size: ${chunkSize:100}
hibernate.connection.provider_disables_autocommit: true
hibernate.jdbc.batch_size: ${chunkSize:100}
hibernate.order_inserts: true
hibernate.order_updates: true
--- # local μ€μ
spring:
config:
activate:
on-profile: "db-local"
jpa:
show-sql: true
database-platform: H2
hibernate:
ddl-auto: create-drop
datasource:
hikari:
driver-class-name: org.h2.Driver
jdbc-url: jdbc:h2:mem://localhost/~/divelog;MODE=MySQL;DATABASE_TO_LOWER=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE;
username: sa
password:
--- # dev μ€μ
spring:
config:
activate:
on-profile: "db-dev"
jpa:
hibernate:
ddl-auto: update
datasource:
hikari:
driver-class-name: org.mariadb.jdbc.Driver
...
.yml νμΌμ μμ κ°μ΄ --- λ₯Ό ν΅ν΄ νμΌ λΆν μ΄ κ°λ₯ν©λλ€. μ΄λ‘ μΈν΄ μ¬λ¬ νκ²½μμ μ¬μ©λ κ°μ νλμ νμΌμ μμ±ν μ μμ΅λλ€. π
- #default : νλ‘μ νΈμ κ³΅ν΅ κ°μ μ€μ ν©λλ€.
- spring-config-active-on-profile : application.yml νμΌμμ μμ±ν groupμ profile μ
λλ€. μμμ local, devμΌ λ 맀νλλ db-local, db-dev μ΄λ λμΌν λ€μ΄λ°μΌλ‘ μ€μ ν©λλ€.
- μ°Έκ³ λ‘ Spring Boot 2.4 λ²μ λΆν° μ€μ νμΌμ λ°©λ²μ΄ μλμ κ°μ΄ λ³κ²½λμμ΅λλ€.
# before
spring:
profiles: "prod"
secret: "production-password"
# after
spring:
config:
activate:
on-profile: "prod"
secret: "production-password"
- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.4-Release-Notes
- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Config-Data-Migration-Guide
π application-site.yml
site:
author-name: JuHyun
author-email: a@a.com
--- # local μ€μ
spring:
config:
activate:
on-profile: "site-local"
site:
author-name: JuHyun-local
author-email: a.local@a.com
--- # dev μ€μ
spring:
config:
activate:
on-profile: "site-dev"
site:
author-name: JuHyun-dev
author-email: a.dev@a.com
- spring-config-active-on-profile : dbμ λ§μ°¬κ°μ§λ‘ application.yml νμΌμμ μμ±ν groupμ profileμ λλ€.
π Binding
λ€μμΌλ‘ yml νμΌμ μ€μ ν κ°λ€μ μ½λμ λ°μΈλ©νλ λ°©λ²μ λν΄ μ΄ν΄λ³΄κ² μ΅λλ€.
μμ±ν νμΌμ λ€μκ³Ό κ°μ΅λλ€.
(@Value μ΄λ Έν μ΄μ μ ν΅ν΄ λ°μΈλ©νλ λ°©λ²λ μ‘΄μ¬νμ§λ§, ν¬μ€ν μμλ Spring Boot 2.2 λ²μ λΆν° κ°λ₯ν @ConstructorBindg μ΄λ Έν μ΄μ μ ν΅ν΄ Immutable Properties μ€μ μΌλ‘ ν΄λ³΄κ² μ΅λλ€.)
π AppConfiguration
1 2 3 4 5 6 7 8 9 | import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import org.springframework.context.annotation.Configuration; @Configuration @EnableConfigurationProperties({SiteProperties.class}) public class AppConfiguration { } | cs |
λ°μΈλ© μ€μ μ μν΄ AppConfiguration μ΄λΌλ ν΄λμ€ νμΌμ νλ μμ±ν΄μ£Όμμ΅λλ€.
κ·Έλ¦¬κ³ μ¬κΈ°μ @Configuration , @EnableConfigurationProperties μ΄λ Έν μ΄μ μ ν΅ν΄ μ€μ μ ν©λλ€.
(μ΄λ¬ν λ°©λ² μΈμλ main λ©μλκ° μ‘΄μ¬νλ μ€νλ§ λΆνΈ μ ν리μΌμ΄μ μ ν΄λμ€μ @EnableConfigurationProperties μ΄λ Έν μ΄μ μ μ€μ ν΄μ£Όμ΄λ λμΌνκ² μλν©λλ€. π€―)
π SiteProperties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import lombok.Getter; import lombok.ToString; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConstructorBinding; @Getter @ToString @ConfigurationProperties(prefix = "site") public class SiteProperties { private final String authorName; private final String authorEmail; @ConstructorBinding public SiteProperties(String authorName, String authorEmail) { this.authorName = authorName; this.authorEmail = authorEmail; } } | cs |
μ€μ .ymlμ μ€μ κ°μ΄ λ°μΈλ©λ ν΄λμ€μ λλ€.
@EnableConfigurationProperties μ @ConstructorBinding μ΄λ Έν μ΄μ μ μΆκ°νμ¬ λ°μΈλ©ν©λλ€.
@EnableConfigurationProperties μ μ½λλ₯Ό μ΄ν΄λ³΄λ©΄ μ£Όμμ setterλ₯Ό μ¬μ©νκ±°λ @ConstructorBindingμ ν΅ν΄ λ°μΈλ©μ΄ κ°λ₯νλ€κ³ μ€λͺ λμ΄μμ΅λλ€.
Setterμ κ²½μ° κ°λ³κ²½μ΄ κ°λ₯νμ¬ Immutableν μνκ° μλλ―λ‘ @ConstructorBindingλ₯Ό ν΅ν΄ λ°μΈλ©μ ν΄μ£Όμμ΅λλ€.
π Binding ν μ€νΈνκΈ°
application-site.yml νμΌμ μμ±ν κ°λ€μ λν΄ local, dev μ€μ μ ν΅ν΄ λ°μΈλ©μ΄ μ λλμ§ ν μ€νΈν΄λ³΄κ² μ΅λλ€.
π SitePropertiesTest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package com.fastcompus.springrunner.divelog.config; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest class SitePropertiesTest { @Test void test(@Autowired SiteProperties properties) { assertThat(properties.getAuthorName()).isEqualTo("JuHyun-local"); assertThat(properties.getAuthorEmail()).isEqualTo("a.local@a.com"); } } | cs |
π SitePropertiesDevTest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.fastcompus.springrunner.divelog.config; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import static org.assertj.core.api.Assertions.assertThat; @ActiveProfiles("dev") @SpringBootTest class SitePropertiesDevTest { @Test void test(@Autowired SiteProperties properties) { assertThat(properties.getAuthorName()).isEqualTo("JuHyun-dev"); assertThat(properties.getAuthorEmail()).isEqualTo("a.dev@a.com"); } } | cs |
application.yml νμΌμμ κΈ°λ³Έ profileμ localλ‘ μ€μ νκΈ° λλ¬Έμ dev profileμ ν μ€νΈνκΈ° μν΄ @ActiveProfiles("dev") λ₯Ό ν΅ν΄ λͺ μμ μΌλ‘ μ μΈνμ¬ ν μ€νΈν©λλ€.
π References
- https://fastcampus.co.kr/dev_academy_springrunner201
- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.2-Release-Notes#configurationproperties-scanning
- https://cheese10yun.github.io/immutable-properties/
- http://honeymon.io/tech/2021/01/16/spring-boot-config-data-migration.html
- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.4-Release-Notes
- https://www.baeldung.com/configuration-properties-in-spring-boot
'Spring' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
Spring + MyBatisμμ 쿼리μ κ²°κ³Όμ κ°μ²΄κ° 맀νμ΄ λλ κ³Όμ (1) | 2022.10.03 |
---|---|
JUnit5 assertThat vs assertAll vs assertSoftly (3) | 2022.09.17 |
Spring Thread, Transaction, Connection κ΄κ³ (0) | 2022.09.03 |
Spring Data MongoDB Array field $elemMatch(MongoRepository Custom) (2) | 2022.08.20 |
Spring Boot SQL μ€μ (hibernate, logging) (4) | 2022.03.12 |
λκΈ