catsridingCATSRIDING|OCEANWAVES
Dev

Spring Boot 애플리케이션 macOS 환경변수 활용하기

jynn@catsriding.com
Mar 29, 2024
Published byJynn
999
Spring Boot 애플리케이션 macOS 환경변수 활용하기

OS Environment Variables with Spring on macOS

환경변수는 운영체제 레벨에서 설정하고 관리되는 값을 말합니다. 이러한 환경변수들은 애플리케이션의 실행 환경을 설정하거나, 시스템의 행동을 조절하는 등 다양한 목적으로 사용될 수 있습니다. 특히 개발 환경에서는 데이터베이스 연결 정보, 외부 서비스의 API 키 등과 같이 보안이 중요한 정보를 저장하는 데 환경변수가 활용됩니다.

소스 코드에 직접 민감한 정보를 추가하는 것은 여러 측면에서 위험합니다. 코드베이스가 Git & GitHub와 같은 버전 관리 시스템에 저장될 경우 민감한 정보가 노출될 수 있으며, 소스 코드가 공유되거나 유출될 경우에도 외부로 유출될 위험이 있습니다. 환경 변수를 사용하면 이러한 위험을 줄이고 보안성을 높일 수 있습니다.

이번 글에서는 macOS에서 환경 변수를 설정하고, 이를 Spring Boot 애플리케이션에서 활용하는 방법에 대해 알아보겠습니다.

Setting Up Environment Variables

Spring Boot 프로젝트에서 환경 변수를 사용하려면 먼저 환경 변수를 설정해야 합니다. 이를 통해 데이터베이스 연결 정보나 API 키와 같은 민감한 정보를 안전하게 관리할 수 있습니다. macOS와 IntelliJ IDEA에서 환경 변수를 설정하는 방법을 살펴보겠습니다.

Environment Variables in OS

Spring Boot 프로젝트에서 환경 변수를 활용하려면 먼저 운영 체제에서 해당 변수를 설정해야 합니다. macOS에서는 터미널을 통해 export 명령어를 사용하여 환경 변수를 설정할 수 있습니다.

Terminal
$ export DATABASE_USERNAME=ongs
$ export DATABASE_PASSWORD=mongs

하지만, 위와 같이 설정하면 현재 터미널 세션에서만 변수가 유효하며, 세션을 종료하면 설정한 환경 변수가 사라집니다. 이를 방지하기 위해 환경 변수를 셸 설정 파일에 저장할 수 있습니다.

1. Zsh 설정 파일 열기

터미널에서 환경 변수를 모든 세션에 걸쳐 유지하려면 .zshrc 파일에 변수를 추가해야 합니다. .zshrc 파일은 Zsh 셸의 설정 파일로, 터미널 세션이 시작될 때마다 자동으로 로드되어 환경 변수를 적용합니다. 아래 명령어를 사용해 .zshrc 파일을 텍스트 에디터로 열 수 있습니다:

Terminal
# Vim 에디터로 .zshrc 파일 열기
$ vim ~/.zshrc 

# Vi 에디터로 .zshrc 파일 열기
$ vi ~/.zshrc 
2. 환경 변수 추가

.zshrc 파일이 텍스트 에디터에 열리면, 파일 하단에 다음과 같이 환경 변수를 추가합니다:

.zshrc
# DATABASE CREDENTIALS
export DATABASE_USERNAME=ongs
export DATABASE_PASSWORD=mongs

이렇게 환경 변수를 추가하면, 터미널 세션이 시작될 때마다 자동으로 이 변수가 설정됩니다.

3. 셸 변경 사항 반영

환경 변수를 .zshrc 파일에 추가한 후, 변경 사항을 현재 셸 세션에 반영하려면 다음 명령어를 실행합니다:

Terminal
$ source ~/.zshrc

이 명령어를 실행하면, 터미널 세션을 종료하지 않고도 설정한 환경 변수를 즉시 사용할 수 있습니다.

4. 환경 변수 설정 확인

설정한 환경 변수가 제대로 적용되었는지 확인하려면, 아래 명령어를 사용하여 환경 변수의 값을 출력해 봅니다.

Terminal
$ echo $DATABASE_USERNAME
ongs
$ echo $DATABASE_PASSWORD
mongs

출력된 값이 설정한 값과 일치하면, 환경 변수가 성공적으로 설정된 것입니다.

이제 설정한 환경 변수는 터미널 세션을 종료하거나 새로운 터미널을 열어도 계속 유지됩니다. 이를 통해 중요한 정보를 안전하게 관리할 수 있으며, 프로젝트 간에 공통 설정을 쉽게 유지할 수 있습니다.

Environment Variables in IntelliJ IDEA

IntelliJ IDEA는 애플리케이션을 실행할 때 자체적인 셸 환경을 사용합니다. 또한, 셸 스크립트를 통해 설정한 환경 변수는 하위 프로세스에만 상속되는 특징이 있습니다. 따라서 IntelliJ IDEA에서 실행하는 애플리케이션은 상위 시스템의 환경 변수를 직접 읽지 못할 수 있습니다.

이 문제를 해결하기 위해서는 OS 환경 변수 설정과는 별개로, IDE 수준에서 직접 환경 변수를 추가해야 합니다. 다음과 같이 IntelliJ IDEA의 Run Configurations에서 환경 변수를 추가할 수 있습니다:

  1. IntelliJ IDEA 메뉴에서 Edit Configurations... 버튼을 선택합니다.
  2. 왼쪽 패널에서 애플리케이션 구성을 선택합니다.
  3. Environment variables 필드를 찾아 설정하려는 환경 변수를 입력합니다. 만약 해당 필드가 보이지 않는다면 Modify options 버튼을 클릭하여 필드를 활성화합니다. 여러 개의 환경 변수를 추가하려면 콤마로 구분하거나 다이얼로그박스를 활용하면 됩니다.
  4. 모든 설정이 완료되면 OK 버튼을 눌러 저장합니다.

IntelliJ IDEA Environment Variables

이렇게 설정하면 IntelliJ IDEA에서 애플리케이션을 실행할 때, IDE에서 구성한 환경 변수를 사용할 수 있습니다. 즉, 애플리케이션은 실행 시에 IDE에서 설정한 환경 변수 값을 확인하고 활용할 수 있게 됩니다.

Utilizing Environment Variables in Spring

 Spring Boot 프로젝트에서는 환경 변수를 효과적으로 활용하여 애플리케이션 설정을 관리할 수 있습니다. 환경 변수를 Spring Boot 애플리케이션에 바인딩하고 사용하는 다양한 방법을 살펴보겠습니다.

Using application.yml

application.yml 파일은 Spring Boot 애플리케이션의 다양한 속성 값을 정의하는 중요한 구성 파일입니다. 이 파일은 데이터베이스 연결 정보 등 핵심 설정을 포함하며, 환경 변수를 참조하여 동적으로 값을 조정할 수 있는 유연성을 제공합니다.

아래는 application.yml 파일에서 환경 변수를 참조하는 예시 입니다:

application.yml
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/catsriding
    username: ${DATABASE_USERNAME}
    password: ${DATABASE_PASSWORD}

  • ${VARIABLE_NAME}: 이 형태의 구문은 운영 체제의 환경 변수를 참조합니다. Spring은 애플리케이션 실행 시 해당 환경 변수의 값을 자동으로 로드합니다. 이때 VARIABLE_NAME은 실제 OS 환경 변수의 이름과 일치해야 합니다.

이렇게 application.yml 파일에 설정된 속성은 @ConfigurationProperties 어노테이션을 사용하여 Java 객체로 자동 바인딩할 수 있습니다. 이 어노테이션은 spring.datasource와 같이 특정 접두사가 붙은 속성들을 Java 객체로 자동으로 매핑합니다. 이를 통해 설정된 속성들을 객체 지향적으로 관리할 수 있으며, 코드의 재사용성과 가독성을 높일 수 있습니다.

다음은 Spring에서 제공하는 DataSourceProperties 클래스입니다:

DataSourceProperties.java
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties {

    private String driverClassName;
    private String url;
    private String username;
    private String password;

    ...
}

이 클래스는 application.yml 파일의 spring.datasource 섹션에 명시된 설정값들을 자동으로 해당 필드에 연결합니다. 이러한 자동화된 바인딩은 애플리케이션의 데이터베이스 설정을 효과적으로 관리할 수 있도록 도와줍니다.

바인딩된 속성들은 애플리케이션 내에서 다음과 같이 활용할 수 있습니다:

Application.java
@SpringBootApplication
public class Application {

    @Autowired
    private final DataSourceProperties properties;

    @PostConstruct
    public void printDatabaseCredentials() {
        String username = properties.getUsername();
        String password = properties.getPassword();
        
        System.out.println("⚙️ application.yml - username: " + username);
        System.out.println("⚙️ application.yml - password: " + password);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

이 코드를 실행하면, 콘솔에 데이터베이스의 사용자 이름과 비밀번호가 출력되어 환경 변수가 정상적으로 추출되어 바인딩 되었는지 확인할 수 있습니다:

console
⚙️ application.yml - username: ongs
⚙️ application.yml - password: mongs

이와 같이 application.yml 파일에서 환경 변수를 참조하고, @ConfigurationProperties 어노테이션을 활용하면 설정값을 객체 지향적으로 통합 관리할 수 있어 코드를 더 간결하고 명확하게 작성할 수 있습니다. 이 접근법은 설정값을 효과적으로 분류하고 관리하며, 재사용성과 가독성을 높이는 동시에, 설정 변경에도 유연하게 대응할 수 있어 유지보수성을 크게 향상시킵니다.

여기서 한 가지 주의할 점은, DataSourceProperties 클래스는 Spring Boot의 자동 설정 덕분에 별도의 추가 설정 없이도 바인딩된다는 것입니다. 그러나, 이러한 자동 설정이 항상 예상대로 작동하지 않을 수 있으므로, 직접 정의한 프로퍼티 클래스를 바인딩하려면 @ConfigurationPropertiesScan 어노테이션을 사용하는 것이 좋습니다. 이 어노테이션은 Spring Boot 2.2 버전부터 도입되어, 프로퍼티 클래스를 자동으로 스캔하고 바인딩할 수 있게 합니다.

예를 들어, 다음과 같이 @ConfigurationPropertiesScan 어노테이션을 사용하여 @ConfigurationProperties가 적용된 클래스를 자동으로 스캔할 수 있습니다:

Application.java
@SpringBootApplication
@ConfigurationPropertiesScan
public class Application {

    @Autowired
    private final CustomProperties properties;

    ...
}
  • @ConfigurationPropertiesScan: 이 어노테이션은 지정된 패키지 내에서 @ConfigurationProperties가 적용된 클래스를 자동으로 스캔하고 바인딩합니다. 패키지를 지정하지 않으면, 기본적으로 @SpringBootApplication 클래스가 속한 패키지와 그 하위 패키지를 스캔합니다.

Using @Value Annotation

Spring Framework에서 @Value 어노테이션은 클래스 내 필드에 프로퍼티 값을 직접 주입하는 편리한 방법을 제공합니다. 이 방법은 다양한 필드에 서로 다른 환경 변수 값을 주입해야 할 때 유용하며, 사용이 간편하다는 장점이 있습니다. 아래는 @Value 어노테이션을 사용하여 환경 변수를 주입하는 예제입니다:

Application.java
@SpringBootApplication
public class Application {

    @Value("${DATABASE_USERNAME}") 
    private String username;

    @Value("${DATABASE_PASSWORD}") 
    private String password;

    @PostConstruct
    public void printDatabaseCredentials() {
        System.out.println("🌀 @Value Annotation - username: " + username);
        System.out.println("🌀 @Value Annotation - password: " + password);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

위 코드에서는 다음과 같이 환경 변수 값을 주입합니다:

  • @Value("${DATABASE_USERNAME}"): 데이터베이스 사용자 이름
  • @Value("${DATABASE_PASSWORD}"): 데이터베이스 비밀번호

애플리케이션이 구동되면, 주입된 환경 변수 값들은 다음과 같이 콘솔에 출력됩니다:

console
🌀 @Value Annotation - username: ongs
🌀 @Value Annotation - password: mongs

이 방식은 간단하고 직관적이지만, 환경 변수가 많아질 경우 관리가 복잡해질 수 있습니다. 많은 수의 환경 변수를 다뤄야 한다면, application.yml 파일과 @ConfigurationProperties 어노테이션을 활용하여 보다 체계적으로 관리하는 것이 좋습니다. 그러나 간단한 설정의 경우, @Value 어노테이션은 여전히 매우 유용한 도구입니다.

Using Environment Interface

Spring Framework에서는 Environment 인터페이스를 통해 다양한 소스에서 유연하게 속성 값을 가져올 수 있습니다. 이 인터페이스는 프로퍼티 파일, JVM 시스템 프로퍼티, 환경 변수 등 여러 소스에서 값을 추출할 수 있는 추상화된 방법을 제공합니다. 이를 통해 애플리케이션은 다양한 환경에서 일관된 방식으로 설정 값을 관리할 수 있습니다.

환경 변수에 접근하기 위해 Environment 인터페이스의 getProperty(String key) 메서드를 사용할 수 있습니다. 예를 들어, 다음과 같이 Environment 객체를 활용하여 DATABASE_USERNAMEDATABASE_PASSWORD 같은 환경 변수 값을 추출할 수 있습니다:

Application.java
@SpringBootApplication
public class Application {

    @Autowired
    private Environment env;

    @PostConstruct
    public void printDatabaseCredentials() {
        String username = env.getProperty("DATABASE_USERNAME");
        String password = env.getProperty("DATABASE_PASSWORD");

        System.out.println("🌏 Environment Object - username: " + username);
        System.out.println("🌏 Environment Object - password: " + password);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

위 코드에서는 Environment 인터페이스를 사용하여 다음과 같이 환경 변수 값을 가져옵니다:

  • env.getProperty("DATABASE_USERNAME"): 데이터베이스 사용자 이름
  • env.getProperty("DATABASE_PASSWORD"): 데이터베이스 비밀번호

애플리케이션을 실행하면, 추출된 환경 변수 값이 콘솔에 출력됩니다:

console
🌏 Environment Object - username: ongs
🌏 Environment Object - password: mongs

Environment 인터페이스를 사용하면 환경 변수 외에도 다양한 설정 소스에서 값을 가져올 수 있습니다. 이를 통해 애플리케이션의 환경 설정을 보다 일관되고 유연하게 관리할 수 있습니다. 특히, 복잡한 애플리케이션에서는 여러 설정 소스를 통합하여 관리할 때 이 방법이 매우 유용합니다. 이 접근 방식은 설정 관리를 단순화하고, 다양한 환경에서 쉽게 설정을 가져올 수 있도록 하여 유지보수를 용이하게 합니다.

  • macOS
  • Spring