본문 바로가기
스프링 부트3

스프링 부트 3에서 ApplicationRunner와 CommandLineRunner

by 굿센스굿 2024. 12. 11.
반응형

 

스프링 부트는 애플리케이션 초기화 과정에서 특정 코드를 실행해야 할 때 **ApplicationRunner**와 CommandLineRunner 인터페이스를 제공합니다. 이 두 인터페이스는 애플리케이션이 실행된 후 초기 작업을 설정하거나, 데이터를 로드하거나, 특정 비즈니스 로직을 수행하는 데 자주 사용됩니다.

스프링 부트 3에서는 기존의 동작 방식과 동일하지만, 자바 17과 스프링 6의 새로운 기능과 함께 더 강력하고 효율적인 방법으로 활용할 수 있습니다. 이번 글에서는 두 인터페이스의 차이점과 실제 적용 사례 3가지를 통해 활용 방법을 살펴보겠습니다.


1. ApplicationRunner와 CommandLineRunner란?

1.1 ApplicationRunner

**ApplicationRunner**는 애플리케이션 실행 후 초기 작업을 수행하는 인터페이스로, 실행 시 ApplicationArguments 객체를 전달받습니다. 이 객체는 애플리케이션의 인자를 파싱하여 쉽게 접근할 수 있는 API를 제공합니다.

장점: 명령줄 인자를 처리하는 추가 기능 제공.
메서드:

void run(ApplicationArguments args) throws Exception;

1.2 CommandLineRunner

**CommandLineRunner**는 실행 시 문자열 배열 형태로 명령줄 인자를 받습니다. 이 배열은 단순히 인자의 값을 전달받는 데 사용되며, 추가적인 처리 기능은 없습니다.

장점: 단순하고 빠른 구현.
메서드:

void run(String... args) throws Exception;

주요 차이점

항목 ApplicationRunner CommandLineRunner

인자 처리 방식 ApplicationArguments 객체 String[] 배열
명령줄 인자 파싱 지원 (키-값 쌍 처리 가능) 비지원
복잡한 초기화 작업 적합 단순 작업에 적합

2. 활용 사례

2.1 데이터 초기화 작업

애플리케이션이 실행될 때 기본 데이터를 데이터베이스에 로드해야 한다면 ApplicationRunner와 CommandLineRunner가 적합합니다.

코드 예제: CommandLineRunner를 사용한 데이터 로드

@Component
public class DataLoader implements CommandLineRunner {
    private final UserRepository userRepository;

    public DataLoader(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public void run(String... args) throws Exception {
        userRepository.save(new User("admin", "admin@example.com", "ROLE_ADMIN"));
        userRepository.save(new User("user", "user@example.com", "ROLE_USER"));
        System.out.println("Initial users loaded.");
    }
}

실행 결과: 애플리케이션이 시작될 때 기본 유저 데이터를 데이터베이스에 삽입합니다.


2.2 명령줄 인자를 활용한 설정

ApplicationRunner를 사용하면 명령줄 인자를 파싱해 조건에 따라 다른 동작을 실행할 수 있습니다.

코드 예제: ApplicationRunner를 활용한 명령줄 인자 파싱

@Component
public class ArgumentProcessor implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        if (args.containsOption("mode")) {
            String mode = args.getOptionValues("mode").get(0);
            System.out.println("Running in mode: " + mode);
        } else {
            System.out.println("No mode specified. Running in default mode.");
        }
    }
}

명령어 실행 예:

java -jar app.jar --mode=production

실행 결과: mode 값이 출력되고, 인자에 따라 다른 설정이 적용됩니다.


2.3 비즈니스 로직의 비동기 실행

CommandLineRunner를 사용하여 애플리케이션 초기화와 동시에 비동기 작업을 실행할 수도 있습니다.

코드 예제: 비동기 작업 실행

@Component
public class AsyncTaskRunner implements CommandLineRunner {
    private final TaskExecutor taskExecutor;

    public AsyncTaskRunner(TaskExecutor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    @Override
    public void run(String... args) throws Exception {
        taskExecutor.execute(() -> {
            try {
                Thread.sleep(5000);
                System.out.println("Asynchronous task completed!");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.err.println("Task interrupted.");
            }
        });
    }
}

실행 결과: 애플리케이션이 시작된 후 비동기 작업이 백그라운드에서 실행됩니다.


3. 두 인터페이스의 동시 사용

ApplicationRunner와 CommandLineRunner를 함께 사용할 수도 있습니다. 각각의 인터페이스는 독립적으로 실행되므로, 다양한 초기화 작업을 분리하여 처리할 수 있습니다.

코드 예제: 두 인터페이스의 동시 사용

@Component
public class CommandLineExample implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("CommandLineRunner executed!");
    }
}

@Component
public class ApplicationExample implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("ApplicationRunner executed!");
    }
}

실행 결과:

CommandLineRunner executed!  
ApplicationRunner executed!  

4. 언제 어떤 인터페이스를 사용할까?

  • ApplicationRunner: 명령줄 인자를 세부적으로 처리하거나 복잡한 초기화 작업이 필요한 경우.
  • CommandLineRunner: 단순 작업이나 빠르게 실행할 초기 작업이 필요한 경우.

5. 결론

스프링 부트 3에서 ApplicationRunner와 CommandLineRunner는 애플리케이션 초기화를 간편하고 유연하게 수행할 수 있는 강력한 도구입니다. 필요에 따라 적절한 인터페이스를 선택해 초기화 작업을 최적화하세요. 위의 예제 코드를 참고하여 프로젝트에서 효과적으로 활용해 보세요!

반응형