λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Spring

Spring Boot profiles μ„€μ •ν•˜κΈ°

by 주발2 2022. 9. 5.
λ°˜μ‘ν˜•

πŸ“Ž 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 = local

 

profile = dev

 

profile = prod

 

참고둜, 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

 

λ°˜μ‘ν˜•

λŒ“κΈ€