뜬금없을 수 있지만 이제부터는 프로젝트 시작이나, 여타 작업들을 자세히 설명하지 않으려 한다. 처음에는 공부에 대한 복습과 기록에 대한 느낌으로 이 글들을 적어두고 있었는데, 어느샌가 부터는 불필요한 내용들이 많이 들어가기 시작했다고 생각했다. 그래서 누군가가 이 글을 읽는다면 가이드를 직접 따라오면서 읽을 것이라 가정하고, 짤막한 가이드에서의 핵심적으로 중요한 내용만을 강조해가려고 한다.
https://spring.io/guides/gs/async-method/
CompletableFuture를 이용해 Async한 함수 동작해보기
기억하면 좋을 파트들만 설명을 짧게 남겨둔다.
## User.kt
@JsonIgnoreProperties(ignoreUnknown = true)
@Entity
data class User(
var name: String?,
var Blog: String?,
@Id @GeneratedValue
val id: Int? = null
)
## GitHubLookupService.kt
@Service
class GitHubLookupService(
@Autowired private val restTemplate: RestTemplate
) {
private val logger = LoggerFactory.getLogger(GitHubLookupService::class.java)
@Async
fun findUser(user: String): CompletableFuture<User> {
logger.info("Looking up $user")
val url = "https://api.github.com/users/$user"
val result = restTemplate.getForObject(url, User::class.java)
Thread.sleep(1000L)
return CompletableFuture.completedFuture(result)
}
}
## ~Application.kt (기존 코드에 수정)
@SpringBootApplication
@EnableAsync
class CreatingAsynchronousMethodsApplication {
@Bean
fun restTemplate(): RestTemplate {
return RestTemplate()
}
@Bean
fun taskExecutor(): Executor {
val executor = ThreadPoolTaskExecutor()
executor.corePoolSize = 2
executor.maxPoolSize = 2
executor.queueCapacity = 500
executor.setThreadNamePrefix("GithubLookup-")
executor.initialize()
return executor
}
}
## AppRunner.kt
@Component
class AppRunner(
@Autowired private val gitHubLookupService: GitHubLookupService
): CommandLineRunner {
private val logger = LoggerFactory.getLogger(AppRunner::class.java)
override fun run(vararg args: String?) {
val start = System.currentTimeMillis()
val page1 = gitHubLookupService.findUser("PivotalSoftware")
val page2 = gitHubLookupService.findUser("CloudFoundry")
val page3 = gitHubLookupService.findUser("Spring-Projects")
CompletableFuture.allOf(page1, page2, page3).join()
logger.info("Elapsed time: " + (System.currentTimeMillis() - start));
logger.info("--> " + page1.get());
logger.info("--> " + page2.get());
logger.info("--> " + page3.get());
}
}
이후엔 실제로 돌려보면 가이드에서 알려주는 것과 같이 결과가 나올 것이다. 해당 가이드의 핵심은 asynchronous한 함수를 통해 여러 오래 걸릴 수 있는 작업을 동시에 진행시킬 수 있다~ 라는 것이다.
사실 실제적으로 이를 유용하게 쓰려나~ 싶기는 하다. kotlin의 coroutine을 활용하여 설계하는 방식도 있을 것이고, 이게 좀 더 익숙하기도 해서 후에 이 방식을 따로 알아봐야 할 것 같다.
코드는 여기서 확인할 수 있다.