본문 바로가기
Spring

환경변수 @ConfigurationProperties로 간단히 관리하기 (with Kotlin)

by 이숴 2024. 1. 30.
반응형

 

환경 변수를 효율적으로 관리하는 것은 모든 스프링 부트 애플리케이션에서 중요한 부분입니다.

 

저는 이부분에서 @Value 어노테이션을 사용해서 환경변수를 매핑해서 변수로 사용하곤 했었는데요.

하지만 지금은 @ConfigurationProperties를 써서 환경변수 추가/수정/제거 등 관리하고 있습니다.

 

이 글에서는  @ConfigurationProperties가 @Value보다 왜 더 효율적인지를 알아보겠습니다.

 

@Value

@Value 어노테이션은 환경 변수를 주입하기에 아주 간단한 방법입니다. 하지만 매번 하드코딩으로 환경 변수의 주소를 작성해야하고, 해당 변수를 사용하는 여러 곳에 중복 코드가 발생하게 됩니다.

 

또, 이러한 프로퍼티가 많아질수록 관리가 어려워집니다.

// jwtProvider
@Component
class JwtTokenProvider(
    @Value("\${custom.jwt.token.access-expiration-time}")
    private var accessExpirationTime: Long,
    @Value("\${custom.jwt.token.refresh-expiration-time}")
    private var refreshExpirationTime: Long,
)

// jwtUtil
@Component
class JwtTokenUtil(
    @Value("\${custom.jwt.token.access-expiration-time}")
    private var accessExpirationTime: Long,
    @Value("\${custom.jwt.token.refresh-expiration-time}")
    private var refreshExpirationTime: Long,
)

 

@ConfigurationProperties

@ConfigurationProperties 어노테이션은 프로퍼티를 하나의 클래스에 저장하여 관리할 수 있게 할 수 있습니다. 프로퍼티를 다음과 같이 관리했을 때 얻는 이점은 다음과 같습니다.

 

1. 여러 클래스에서 하드코딩으로 수정해야했던 경로나 타입들을 하나의 클래스에서 자동으로 관리할 수 있음

2. 도메인 별로 관련된 프로퍼티를 클래스를 나누어 묶어서 관리할 수 있게되면서, 코드의 가독성과 구조가 향상된

3. IDE에서 자동완성으로 사용할 수 있음

 

 하지만 작성시에 매우 유의해야할 부분이 있습니다. yml이나 properties 파일에 작성된 경로에 맞게 변수 이름을 설정해야 환경변수를 알맞게 매핑할 수 있습니다. 다음과 같이 말입니다.

@ConfigurationProperties(prefix = "custom")
data class AccountProperties @ConstructorBinding constructor(
    val jwt: JwtProperties
) {

    val nameJson: String
        get() = "account-api/src/main/resources/names/names.json"

    data class JwtProperties(
        val accessExpirationTime: Long,
        val refreshExpirationTime: Long,
        val secret: String,
    )
}

// application.yml
custom:
  jwt:
    secret: 시크릿 코드
    access-expiration-time: 900000 # 15분 -> 15 * 60 * 1000
    refresh-expiration-time: 1296000000 # 15일 -> 15 * 24 * 60 * 60 * 1000

 

하지만 이렇게 작성했다고 해서 이 프로퍼티 클래스르는 자체적으로 스프링 빈에 등록되지 않습니다.

 

이클래스를 빈에 등록하고, 프로퍼티가 외부 값을 바인딩 받을 수 있도록 하려면 추가적인 설정이 필요합니다. 

이를 위해 따로 클래스를 생성해주도록 하겠습니다.

 

 

@Configuration
@EnableConfigurationProperties(AccountProperties::class)
class AccountConfig

이렇게 @Configuration 어노테이션이 붙은 클래스는 빈으로 정의가 됩니다. 그리고 이전에 작성한 프로퍼티 클래스를 Enable 하면서 설정값을 바인딩할 수 있도록 하여 최종적으로 환경변수를 사용할 수 있게 됩니다. 여기서 문제가 발생하셨다면 yml에 작성된 이름과 다른 변수 이름으로 설정하셨는지 꼭 확인하셔야합니다!!!

 

실제 사용은 다음과 같이 의존성을 추가하여 사용합니다.

@Component
class JwtTokenProvider(
    private val accountProperties: AccountProperties,
) {

	...
    
    fun createdJwtToken(username: String, authorities: String): JwtTokenResponse {
		
        ...
        
        val accessToken: String = createdAccessToken(claims, 
        	Date(createdTime.time + accountProperties.jwt.accessExpirationTime)
        )
}

 

이렇게해 설정 클래스를 작성하면, 프로퍼티 클래스에 정의된 프로퍼티들은 자동으로 설정 파일의 값으로 채워지며, 이를 전체 애플리케이션에서 재사용할 수 있습니다.

반응형

댓글