SW 개발/Spring
Spring Boot, 콘솔 애플리케이션을 만드는 노하우 정리
지단로보트
2021. 12. 27. 22:36
개요
- Spring Boot 생태계에서 콘솔 애플리케이션을 만드는 방법은 다양하지만, 내가 선호하는 방법을 정리하였다. (대부분은 팀 내부에서 사용하는 유틸리티 성격의 툴링이 목적이다.)
build.gradle.kts
- 웹 애플리케이션이 아닌 한 번 실행되면 준비된 기능을 실행하고 종료되는 애플리케이션을 만들 것이기 때문에
spring-boot-starter
이면 충분하다.
dependencies {
implementation("org.springframework.boot:spring-boot-starter")
}
@SpringBootApplication 클래스 작성
- 커맨드라인 인자를 다루면 좋겠지만 팀 내에서만 사용할 것이기에 운영체제 환경 변수 주입을 더 선호한다.
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class FooApplication
fun main(args: Array<String>) {
runApplication<FooApplication>(*args)
}
@EventListener 클래스 작성
- Spring Boot의 부트 스트래핑이 완료되고, 애플리케이션이 완전히 실행 준비 상태가 되는 시점에 발동되는
ApplicationReadyEvent
이벤트에 개입하면 아래와 같이 원하는 서비스 로직을 실행시킬 수 있다.
import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.context.event.EventListener
import org.springframework.stereotype.Component
@Component
class FooRunner(
val fooService: FooService
) {
@EventListener(ApplicationReadyEvent::class)
fun run() {
fooService.runSomething()
}
}
@EnableAsync 클래스 작성
- 쉘 스크립트를 두고 굳이 JVM 언어를 사용한 커맨드라인 툴을 만드는 것의 장점은 바로 멀티 쓰레드의 사용성에 있다. 운영체제 환경 변수를 통해 사용할 쓰레드를 설정하고 아래와 같이 쓰레드 풀을 생성할 수 있다.
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.task.TaskExecutor
import org.springframework.scheduling.annotation.EnableAsync
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
@Configuration
@EnableAsync
class AsyncConfig(
@Value("\${tools.number-of-threads-to-use}") val numberOfThreadsToUse: Int,
) {
@Bean
fun taskExecutor(): TaskExecutor {
val taskExecutor = ThreadPoolTaskExecutor()
taskExecutor.corePoolSize = numberOfThreadsToUse
taskExecutor.setQueueCapacity(0)
taskExecutor.maxPoolSize = numberOfThreadsToUse
return taskExecutor
}
}
@Async 클래스 작성
- 앞서 비동기 쓰레드 풀을 활성화했기 때문에
@Async
를 이용하여 여러 개의 쓰레드로 분기하여 실행할 수 있다. 이를 통해 머신 자원의 사용을 극대화하여 원하는 작업을 실행할 수 있다.
import org.springframework.scheduling.annotation.Async
import org.springframework.stereotype.Service
@Service
class FooAsyncService {
@Async("taskExecutor")
fun doSomethingAsAsync() {
// 실행 로직 작성
}
}