본문 바로가기
Spring

[Spring Boot] 다양한 외부 설정 방법 #1

by 개미가되고싶은사람 2024. 10. 13.

목차

     

    외부설정이란?

    외부 설정은 애플리케이션이 실행되거나 빌드될 때 외부에서 설정 값을 주입 받는 있는 기능을 의미합니다. 그렇다면 애플리케이션 실행에 필요한 설정값을 외부에서 어떻게 주입할 수 있는 것일까?

     

    외부 설정은 크게 아래와 같이 4개로 나눌 수 있습니다.

    • OS 환경 변수: OS에서 지원하는 외부 설정 , OS에서 사용되는 모든 프로세스에 적용 가능
    • 자바 시스템 속성: 자바에서 지원하는 외부 설정, 해당 JVM안에서 사용
    • 자바 커맨드 라인 인수: 커맨드 라인에서 실행시 main(args) 메서드에서 사용할 인자
    • 외부 파일(설정 데이터): 프로그램 외부의 파일을 읽어 사용 (application.properties)

     

     

     

    1. OS 환경 변수

    환경 변수(environment variables)는 애플리케이션 외부에서 설정된 값들로, 다른 외부 설정과 비교해서 사용 범위가 가장 넓습니다.

     

    조회 방법

    • 윈도우 OS: set
    • MAC, 리눅스 OS: printenv
    @Slf4j
    public class OsEnv {
        public static void main(String[] args) {
            Map<String, String> envMap = System.getenv();
            for (String key : envMap.keySet()) {
                log.info("env {}={}", key, System.getenv(key));
            }
    
            //DBURL = dev.db.com 개발 서버
            //DBURL = prod.db.com 운영 서버로 설정
            String dburl = System.getenv("DBURL");
            // 동일한 환경 변수로 데이터베이스 접근 URL를 OS에 따라 다르게 가져올 수 있습니다.
    
        }
    }

     

     

    2. 자바 시스템 속성

    자바 시스템 속성(Java System properties)은 실행한 JVM 안에서 접근 가능한 외부 설정입니다. 그리고 자바가 내부 에서 미리 설정해두고 사용하는 속성들도 존재합니다. 이때 -D명령어를 사용하여 시스템 속성을 설정할 수 있습니다.

     

    2-1 JAR 파일 실행 명령어

    java -DmyProperty=value -jar myapp.jar

    myProperty라는 key로 값을 설정하여 애플리케이션에서 사용할 수 있습니다.

     

     

    2-2 IDE에서 설정 방법(인텔리제이)

     

    Edit Configurations를 클릭

     

     2-1. Modify options를 선택
     2-2. Add VM options를 선택
     2-3. VM options에 다음을 추가

    예를 들어, 다음과 같은 형식으로 전달할 수 있습니다.

    -Durl=dev.db -Dusername=username_peel -Dpassword=pw_qwer

     

     

     

    2-3 자바 코드로 설정

    자바 코드로 자바 시스템 속성을 설정할 수 있지만, 외부에서 설정을 분리하는 효과는 없습니다.

    설정: System.setProperty("property_key", "property-value");
    조회: String propertyKey = System.getProperty("property_key");

     

     

    3. 커맨드 라인 인수

    커맨드 라인 인수(Command line arguments)는 애플리케이션 실행 시점에 외부 설정값을 main(args) 메서드의 args 파라미터로 전달하는 방법입니다.이 인수는 key=value 형식이 아닌 문자 그대로 전달되기 때문에, 실제로 사용할 때는 종종 Map과 같은 형식으로 변환해야 하는 경우가 많습니다. 스프링 부트에서는 이러한 문제를 해결하기 위해 커맨드 라인 옵션 인수 기능을 도입하였습니다. 

     

    3-1 JAR 파일 실행 명령어

    java -jar app.jar dataA dataB
    •  커맨드 라인에 전달하는 값은 형식이 없고, 단순히 띄어쓰기로 구분합니다.
    •  aaa bbb [aaa, bbb] 값 2개
    •  hello world [hello, world] 값 2개
    •  "hello world" [hello world] (공백을 연결하려면 " 를 사용하면 된다.) 값 1개
    •  test_key=test_value [ test_key = test_value  ] 값 1개

     

     

    3-2 IDE에서 설정 방법(인텔리제이)

    Edit Configurations를 들어갑니다. (2-2 방법 참고)

    • Program arguments에 값을 입력하면 됩니다.
    • 커맨드 라인 인수는 공백(space)으로 구분

    3-3 커맨드 라인 옵션 인수 

    Spring Boot는 커맨드 옵션 인수를 사용하여 설정 값을 key=value 형식으로 전달할 수 있도록 지원합니다. --key=value 형식으로 인수를 전달함으로써 환경 설정이나 사용자 지정 값을 손쉽게 설정할 수 있습니다. 

    예를 들어, 다음과 같이 여러 개의 인수를 key=value 형식으로 전달할 수 있습니다.

    --username=qwer--username=asdf

     

    인수 값 설정 (2-2 방법 참조)

     

    @Slf4j
    public class CommandLine {
        public static void main(String[] args) {
    
            ApplicationArguments appArgs = new DefaultApplicationArguments(args);
            log.info("SourceArgs = {}", List.of(appArgs.getSourceArgs()));
            log.info("NonOptionArgs = {}", appArgs.getNonOptionArgs());
            log.info("OptionNames = {}", appArgs.getOptionNames());
    
            Set<String> optionNames = appArgs.getOptionNames();
            for (String optionName : optionNames) {
                log.info("option args {}={}", optionName, appArgs.getOptionValues(optionName));
            }
    
            List<String> url = appArgs.getOptionValues("url");
            List<String> username = appArgs.getOptionValues("username");
            List<String> password = appArgs.getOptionValues("password");
            List<String> mode = appArgs.getOptionValues("mode");
            log.info("url={}", url);
            log.info("username={}", username);
            log.info("password={}", password);
            log.info("mode={}", mode);
        }
    }
    • DefaultApplicationArguments은 Spring Boot에서 커맨드 라인 인수를 처리하기 위한 클래스이며, ApplicationArguments 인터페이스의 구현체입니다.
    • getSourceArgs(): 애플리케이션에 전달된 모든 인수를 배열 형태로 반환
    • getNonOptionArgs(): 커맨드 라인 인수가 아닌 일반 인수(비옵션 인수) 목록을 반환
    • getOptionNames(): 커맨드 라인 인수만 반환

     

     

    결과

     

    외부 설정 일관성 문제

    위에 방법들을 살펴보면, 외부 설정 값을 가져오는 방식이 각각 다르다는 것을 알 수 있습니다. 예를 들어, 처음에는 OS 환경 변수를 사용해 외부 설정 값을 설정했지만, 나중에 자바 시스템 속성으로 변경해야 하는 상황이 발생할 수 있습니다. 이 경우, 외부 설정 값을 읽어오는 코드를 모두 수정해야 합니다. 이러한 문제를 해결하기 위해서는 추상화 작업이 필요하지만 스프링은 이미 Environment 와 PropertySource으로 추상화해 해당 문제를 해결했습니다.

     

    참고

    [1] 스프링 부트 핵심 원리와 활용 - 김영한