스프링 부트(핵심 원리와 활용)

Ch05. 외부설정과 프로필(1) - 외부 설정(커맨드 라인 인수, 커멘드 라인 옵션 인수, 커맨드 라인 옵션 인수와 스프링 부트)

webmaster 2023. 3. 12. 15:21
728x90

커맨드 라인 인수

커맨드 라인 인수(Command line arguments)는 애플리케이션 실행 시점에 외부 설정값을 main(args) 메서드의 args 파라미터로 전달하는 방법이다.

  • 예) java -jar app.jar dataA dataB
  • 필요한 데이터를 마지막 위치에 스페이스로 구분해서 전달하면 된다. 이 경우 dataA , dataB 2개의 문자가 args 에 전달된다.

CommandLineV1

@Slf4j
public class CommandLineV1 {

  public static void main(String[] args) {
    for (String arg : args) {
      log.info("arg = {}", arg); //Key=value 형식이 아니다.
      String[] keyValue = arg.split("=");
      log.info("key = {}, value = {}", keyValue[0], keyValue[1]); //개발자가 직접 파싱해야한다
    }
  }
}

program args 추가

  • 커맨드 라인 인수는 공백(space)으로 구분한다.
  • 커맨드 라인 인수는 key=value 형식이 아니다. 단순히 문자를 여러게 입력 받는 형식이다.
    • arg에 아래와 같은 값이 통으로 들어오기 떄문에 개발자가 = 을 기준으로 직접 데이터를 파싱해서 key=value 형식에 맞도록 분리해야 한다.
      • url=devdb
      • username=dev_user
      • password=dev_pw
    • 그리고 형식이 배열이기 때문에 루프를 돌면서 원하는 데이터를 찾아야 하는 번거로움도 발생한다.
    • 실제 애플리케이션을 개발할 때는 주로 key=value 형식을 자주 사용하기 때문에 결국 파싱해서 Map 같은 형식으로 변환하도록 직접 개발해야 하는 번거로움이 있다.

커멘드 라인 옵션 인수

일반적인 커맨드 라인 인수

커맨드 라인에 전달하는 값은 형식이 없고, 단순히 띄어쓰기로 구분한다.

  • aaa bbb -> [aaa, bbb] : 값 2개
  • hello world -> [hello, world] : 값 2개
  • "hello world" -> [hello world] (공백을 연결하려면 " 를 사용하면 된다.) : 값 1개
  • key=value -> [key=value] : 값 1개

커맨드 라인 옵션 인수(command line option arguments)

커맨드 라인 인수를 key=value 형식으로 구분하는 방법이 필요하다. 그래서 스프링에서는 커맨드 라인 인수를 key=value 형식으로 편리하게 사용할 수 있도록 스프링 만의 표준 방식을 정의했는데, 그것이 바로 커맨드 라인 옵션 인수이다.

스프링은 커맨드 라인에 - (dash) 2( -- )를 연결해서 시작하면 key=value 형식으로 정하고 이것을 커맨드 라인 옵션 인수라 한다.

  • --key=value 형식으로 사용한다.
  • --username=userA --username=userB 하나의 키에 여러 값도 지정할 수 있다.

CommandLineV2

@Slf4j
public class CommandLineV2 {

  public static void main(String[] args) {
    for (String arg : args) {
      log.info("arg {}", arg); //자바의 기본으로 문자 그대로 출력
    }
    ApplicationArguments appArgs = new DefaultApplicationArguments(args);
    log.info("SourceArgs = {}", List.of(appArgs.getSourceArgs())); //배열을 참조값을 반환해서 값을 보기 위해 list로 변경
    log.info("NoneOptionsArgs = {}", appArgs.getNonOptionArgs());
    log.info("OptionsNames = {}", appArgs.getOptionNames());

    Set<String> optionNames = appArgs.getOptionNames();
    for (String optionName : optionNames) {
      log.info("option arg {} = {}", 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); //통문자라 key-value 형식으로 못 뽑는다.
    }
  }
}
커멘드 라인 옵션 인수
  • 스프링이 제공하는 ApplicationArguments 인터페이스와 DefaultApplicationArguments 구현체를 사용하면 커맨드 라인 옵션 인수를 규격대로 파싱해서 편리하게 사용할 수 있다.
  • -- (dash)가 없는 mode=on 이라는 옵션도 마지막에 추가했다.
  • 실행 결과
    • arg : 커맨드 라인의 입력 결과를 그대로 출력한다.
    • SourceArgs : 커맨드 라인 인수 전부를 출력한다.
    • NonOptionArgs = [mode=on] : 옵션 인수가 아니다. key=value 형식으로 파싱되지 않는다. -- 를 앞에 사용하지 않았다.
    • OptionNames = [password, url, username] : key=value 형식으로 사용되는 옵션 인수다. -- 앞에 사용했다.
    • url , username , password 는 옵션 인수이므로 appArgs.getOptionValues(key) 로 조회할 수 있다.
    • mode 는 옵션 인수가 아니므로 appArgs.getOptionValues(key) 로 조회할 수 없다. 따라서 결과는 null 이다

참고

  • 참고로 옵션 인수는 --username=userA --username=userB 처럼 하나의 키에 여러 값을 포함할 수 있기 때문에 appArgs.getOptionValues(key) 의 결과는 리스트( List )를 반환한다.
  • 커맨드 라인 옵션 인수는 자바 언어의 표준 기능이 아니다. 스프링이 편리함을 위해 제공하는 기능이다.

커맨드 라인 옵션 인수와 스프링 부트

스프링 부트는 커맨드 라인을 포함해서 커맨드 라인 옵션 인수를 활용할 수 있는 ApplicationArguments를 스프링 빈으로 등록해 둔다.. 그리고 그 안에 입력한 커맨드 라인을 저장해 둔다.. 그래서 해당 빈을 주입받으면 커맨드 라인으로 입력한 값을 어디서든 사용할 수 있다.

CommandLineBean

@Slf4j
@Component
public class CommandLineBean {

  private final ApplicationArguments arguments;

  public CommandLineBean(ApplicationArguments arguments) {
    this.arguments = arguments;
  }

  @PostConstruct
  public void init(){
    log.info("source {}", List.of(arguments.getSourceArgs()));
    log.info("optionNames {}", List.of(arguments.getOptionNames()));
    Set<String> optionNames = arguments.getOptionNames();
    for (String optionName : optionNames) {
      log.info("option args {} = {}", optionName, arguments.getOptionValues(optionName));
    }

  }
}

program args

  • main 메서드의 SpringApplication.run(ExternalApplication.class, args); 실행 시, 인자로 넘어간 args를 스프링이 등록해 준다.

 

728x90