[Spring Boot] 스프링 부트 구동 시점에 특정 작업 실행하기 - CommandLineRunner, ApplicationRunner

김희정·2023년 11월 15일
1

Spring

목록 보기
12/18
post-custom-banner

들어가며

이번 포스팅에서는 Spring Boot Appliacation 실행시 자동으로 특정 작업을 실행하는 방법에 대해 설명하도록 하겠습니다.

스프링 부트에서는 애플리케이션 구동 시점에 특정 코드를 실행시키기 위해서 2가지 인터페이스를 제공하고 있습니다.

  • CommandLineRunner: 스트링 타입의 인자를 파라미터로 받아서 사용
  • ApplicationRunner: 다양한 종류의 파라미터를 받아서 실행하는 경우에 사용

1. CommandLineRunenr

1.1 정의

CommandLineRunner스프링 부트 1.0에 추가된 함수형 인터페이스로써 스프링 애플리케이션이 구동된 후에 실행되어야하는 빈을 정의하기 위해 사용됩니다.

아래 코드는 Spring Boot 에서 제공하는 인터페이스 명세입니다.

package org.springframework.boot;

@FunctionalInterface
public interface CommandLineRunner {
    void run(String... args) throws Exception;
}

CommandLineRunner는 파라미터로 String 타입의 가변 인자를 받고 있으며, 인터페이스 이름 그대로 커맨드 라인으로 받은 스트링 타입의 인자를 파라미터로 받아서 사용하기 위해 만들어졌습니다.


1.2 구현 클래스 작성

코드

CommandLineRunner는 이를 구현하는 클래스를 정의하고 빈으로 등록하면 애플리케이션이 구동된 후에 자동으로 run() 메소드가 실행됩니다.

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class InitRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        log.info("CommandLineRunner Args: {}", Arrays.toString(args));
    }
}

테스트

터미널(Terminal)에서 아래와 같이 명령어를 입력하면 애플리케이션을 실행할 수 있습니다.

$java -jar sample-0.0.1.jar abc 123

InitRunner 클래스의 run() 메소드의 인자로 넘어와서 출력됩니다.

TomcatWebServer  : Tomcat started on port(s): 443 (https) with context path ''
TestRunner   : CommandLineRunner Args: [abc, 123]

1.3 람다식으로 구현

간단한 코드라면 Main 클래스에서 작업 내용을 람다식으로 구현하고, @Bean 어노테이션을 활용하여 빈으로 등록하여 간소화할 수 있습니다.

@SpringBootApplication
@Slf4j
public class SampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(SampleApplication.class, args);
    }

    @Bean
    CommandLineRunner commandLineRunner(){
        return args -> {
            log.info("{}", args);
        };
    }
}

2. ApplicationRunner

2.1 정의

ApplicationRunner 역시 마찬가지로 함수형 인터페이스로써 스프링 애플리케이션이 구동된 후에 실행되어야 하는 빈을 정의하기 위한 인터페이스입니다.

목적 자체는 동일하지만 ApplicationRunenrCommandLineRunner와 달리 다양한 종류의 파라미터를 받아서실행하는 경우에 사용할 수 있습니다.

또한, CommandLineRunner스프링 부트 1.0에 추가된 반면에 ApplicationRunner스프링 부트 2.0에 추가되었습니다.

ApplicationRunner도 CommandLineRunner와 유사하게 인터페이스를 구현하는 클래스를 등록하거나, 람다식으로 직접 사용할 수 있습니다.


아래 코드는 Spring Boot에서 제공하는 ApplicationRunner 인터페이스 명세입니다.

package org.springframework.boot;

@FunctionalInterface
public interface ApplicationRunner {
    void run(ApplicationArguments args) throws Exception;
}

ApplicationRunner는 run() 메소드에서 ApplicationArguments 객체를 파라미터 인자로 받고 있습니다. ApplicationArguments 인터페이스 코드를 살펴보면 아래와 같습니다

package org.springframework.boot;

import java.util.List;
import java.util.Set;

public interface ApplicationArguments {
    String[] getSourceArgs();
    Set<String> getOptionNames();
    boolean containsOption(String name);
    List<String> getOptionValues(String name);
    List<String> getNonOptionArgs();
}

각 메소드 별 설명은 다음과 같습니다.

ApplicationArguments

  1. getSourceArgs(): 명령 인자 모두를 문자열 배열로 반환. 옵션 인수(ex: --myOption=value)와 옵션이 아닌 인수가 모두 포함됨.
  2. getOptionNames(): 명령줄 인수에 있는 고유한 옵션 이름을 반환
  3. containsOption(String name): 지정된 옵션 이름이 명령줄 인수에 있는지 확인
  4. getOptionValues(String name): 지정된 옵션 이름과 연관된 값 목록을 반환
  5. getNonOptionArgs(): 키가 없는 인수인 옵션이 아닌 인수의 목록을 반환

2.2 구현 클래스 작성

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

@Component
@Slf4j
public class TestRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("ApplicationRunner is running!");

        // Get the non-option arguments (arguments without keys)
        log.info("Non-option arguments: " + args.getNonOptionArgs());

        // Get all arguments including options
        log.info("All arguments: {}", Arrays.toString(args.getSourceArgs()));

        // Get all options
        log.info("All options: {}", args.getOptionNames());

        // Check if an option is present
        if (args.containsOption("myOption")) {
            log.info("The 'myOption' is present!");
        }

        // Access specific option values
        List<String> values = args.getOptionValues("myOption");
        if (values != null) {
            log.info("Values of 'myOption': {}", values);
        }
    }
}

2.3 테스트

IntelliJ 에서 실행 옵션을 넣어 코드를 실행합니다.

  1. 구성에서 편집을 클릭합니다.
    구성 편집 열기
  2. JVM 실행 옵션을 추가합니다.
    실행 옵션 추가

프로그램을 실행해보면 다음과 같이 로그가 생성됩니다.

TestRunner   : ApplicationRunner is running!
TestRunner   : Non-option arguments: [value2]
TestRunner   : All arguments: [--myOption=value1, value2]
TestRunner   : All options: [myOption]
TestRunner   : The 'myOption' is present!
TestRunner   : Values of 'myOption': [value1]

마치며

이번 포스팅에서는 스프링 부트 구동 시점에 특정 작업을 수행하는 두가지 방법에 대해 설명했습니다.

도움이 되셨으면 좋겠습니다.😊💖

profile
Java, Spring 기반 풀스택 개발자의 개발 블로그입니다.
post-custom-banner

1개의 댓글

comment-user-thumbnail
2023년 11월 15일

좋은 정보 감사합니다

답글 달기