SlideShare a Scribd company logo
Kotlin Coroutines
& Spring Framework
Coupang Tech CoP
Catalog Platform & Quality tribe
debop@coupang.com
목차
• Why Kotlin?
• Coroutines
• Spring Asynchronous
• Spring with Coroutines
Why Kotlin?
Concise, Safe, Versatile, Interoperable, Tooling
Combines OO and functional features
Focused on
• Interoperability
• Safety
• Clarity
• Tooling support
a pragmatic programming language
for JVM, Android, JavaScript, LLVM
bytecode
Interoperability
Java
*.kt
*.java
compiler
Javacompiler
Concise
Drastically reduce
The amount of boilerplate code you need to write
data class Customer(val name: String,
var email: String,
val company: String = “coupang”)
Use lambda expression
val positiveNumbers = list.filter { it > 0 }
data class : POJO with getter,setter, equals, hashCode, toString, copy
Concise
Use lambda expression
val positiveNumbers = list.firstOrNull { it > 0 }
Lazy initialization
lateinit var positiveNumbers:List<Int>
val positiveNumbers by lazy { listOf(1,2,3) }
SAFE
All type is Nonnull is default
var output:String
output = null // compilation error
println(output.length())
user?.name?.isEmpty() ?: true
Rid NullPointerExceptions !!!
Auto-cast
fun calcuateTotal(obj:Any) {
if(obj is Invoice) {
obj.calculateTotal() // auto-cast
}
}
Versatile
• Android : No performance impact. Very small runtime.
• JavaScript: Write code in Kotlin and target JavaScript to run on Node.js or in
browser
• Web: Whether you want strongly typed HTML, CSS builder or just plain web
development
• Application Server
• The technology doesn’t matter. 100% compatible with all JVM frameworks.
• Enterpise
• Use Kotlin for any type of Enterprise Java EE development.
• Native
• Kotlin/Native is a LLVM backend for the Kotlin compiler, runtime implementation
and native code generation facility using LLVM toolchain.
Kotlin Basics
Let’s look at real code
Functions
fun sum(a: Int, b: Int): Int {
return a + b
}
fun sum(a: Int, b: Int) = a + b
fun printSum(a: Int, b: Int): Unit {
print(a + b)
}
Variables
val a: Int = 1
val b = 1 // `Int` type is inferred
var c: Int // Type required when no initializer
// is provided
c = 1 // definite assignment
var x = 5 // `Int` type is inferred
x += 1
x ++
String Interpolation
val i = 10
val s = “i=$i” // evaluates to “i=10"
val s = “abc”
val str = “$s.length is ${s.length}”
// evaluates to “abc.length is 3"
val price = ""”
|${‘$’}9.99
""”.trimMargin()
When Expression
when (x) {
1 -> print(“x == 1”)
2 -> print(“x == 2”)
0, 1 -> print(“x == 0 or x == 1”)
parseInt(s) -> print(“s encodes x”)
in 1..10 -> print(”x is in the range”)
in validNumbers ->
!in 10..20 -> print(”x is not in the range”)
is String -> x.startsWith(“prefix”)
x.isOdd() -> print(“x is odd”)
x.isEven() -> print(“x is even”)
else -> println(“otherwise”)
}
Loop
for(item in collection)
print(item)
for(i in array.indices)
print(array[i])
for((index,value) in array.withIndex()) {
print(“element at $index is $value”)
}
Collections
val immutableList = listOf(1, 2, 3)
val mutable = mutableListOf(1, 2, 3)
val arrayList = arrayListOf(1, 2, 3)
val immutableMap = mapOf("foo" to 1, "bar" to 2)
val readWriteMap = hashMapOf("foo" to 1, "bar" to 2)
println(map["foo"])
Kotlin Avanced
Let’s look at real code
null safety
clean = cleaner?.javaClass?.getMethod("clean")
fun load(resourceBasename: String, rootPath: String? = null): Config {
val config = ConfigFactory.load(resourceBasename)
return rootPath?.let { path -> config.getConfig(path) } ?: config
}
Operators
operator fun Duration.unaryMinus(): Duration = this.negated()
operator fun Duration.div(divisor: Int): Duration = this.dividedBy(divisor.toLong())
operator fun Duration.div(divisor: Long): Duration = this.dividedBy(divisor)
operator fun Duration.times(multiplicand: Int): Duration = this.multipliedBy(multiplicand.toLong())
operator fun Duration.times(multiplicand: Long): Duration = this.multipliedBy(multiplicand)
operator fun ReadableInstant.rangeTo(other: ReadableInstant): Interval = Interval(this, other)
operator fun Instant.minus(builder: DurationBuilder): Instant = this.minus(builder.period.toStandardDuration())
operator fun Instant.plus(builder: DurationBuilder): Instant = this.plus(builder.period.toStandardDuration())
operator fun get(index: Int): ITimeLineMoment
operator fun set(index: Int, value:ITimeLineMoment): Unit
Extension Functions
fun String?.toUtf8Bytes(): ByteArray = this?.toByteArray(Charsets.UTF_8) ?: emptyByteArray
fun String?.toUtf8ByteBuffer(): ByteBuffer =
this?.let { Charsets.UTF_8.encode(this) } ?: ByteBuffer.allocate(0)
fun ByteArray?.toUtf8String(): String = this?.toString(Charsets.UTF_8) ?: EMPTY_STRING
fun ByteBuffer?.toUtf8String(): String =
this?.let { Charsets.UTF_8.decode(this).toString() } ?: EMPTY_STRING
fun <T> Array<T>.stream(): Stream<T> = Arrays.stream(this)
Coroutines in Kotlin
Experimental features in Kotlin 1.1
kotlinx.coroutines
A Fiber is a lightweight thread that uses cooperative multitasking instead of preemptive
multitasking. A running fiber must explicitly "yield" to allow another fiber to run, which makes their
implementation much easier than kernel or user threads.
A Coroutine is a component that generalizes a subroutine to allow multiple entry points for
suspending and resuming execution at certain locations. Unlike subroutines, coroutines can
exit by calling other coroutines, which may later return to the point where they were invoked in the
original coroutine.
A Green Thread is a thread that is scheduled by a virtual machine (VM) instead of natively by the
underlying operating system. Green threads emulate multithreaded environments without relying on
any native OS capabilities, and they are managed in user space instead of kernel space, enabling
them to work in environments that do not have native thread support.
• Process: OS-managed (possibly) truly concurrent, at least in the presence of suitable hardware
support. Exist within their own address space.
• Thread: OS-managed, within the same address space as the parent and all its other threads.
Possibly truly concurrent, and multi-tasking is pre-emptive.
• Green Thread: These are user-space projections of the same concept as threads, but are not OS-
managed. Probably not truly concurrent, except in the sense that there may be multiple worker
threads or processes giving them CPU time concurrently, so probably best to consider this as
interleaved or multiplexed.
• Fibers: OS-managed. Exactly threads, except co-operatively multitasking, and hence not truly
concurrent.
• Coroutines: Exactly fibers, except not OS-managed.
• Goroutines: They claim to be unlike anything else, but they seem to be exactly green threads, as
in, process-managed in a single address space and multiplexed onto system threads. Perhaps
somebody with more knowledge of Go can cut through the marketing material.
이런 개념들을 알아야 …
async/await / yield
fibers
[stackless] continuations
Suspendable
Computations
public CompletionStage<Boolean> addAdultItemAsync(final long productId, final long itemId) {
log.trace("Add adult product cache. productId={}, itemId={}", productId, itemId);
final RLock lock = getProductLock(productId);
return lock.lockAsync(3000, TimeUnit.MILLISECONDS)
.thenComposeAsync(rl -> updateProductItemMapping(productId, itemId), global)
.thenComposeAsync(updated -> adultInverseIndex.fastPutAsync(itemId, productId), global)
.thenComposeAsync(added -> adultProductItemMap.putAsync(productId, itemId), global)
.whenCompleteAsync((result, error) -> lock.forceUnlock(), global);
}
Future combination is weired 😫
Suspendable Computation
asyncUI {
val image = await(loadImage(url))
myUI.setImage(image)
}
Suspending call Time consuming operation
UI Thread
await(…)
loadImage(url)
Worker Thread
setImage(…)
Continuation
Coroutines Goals
• Asynchronous programming (and more)
• without explicit callbacks
• without explicit Future combinators (see Deathwing code)
• Maximum flexibility for library designer
• with minimal runtime support
• and no macros (like Scala)
Coroutines 종류
Stackless Stackful
Language
restrictions
Use in special context 😫 Use anywhere 😀
Implemented in C#, Scala, Kotlin, … Quasar, Javaflow …
Code transformation Local (compiler magic) 😀 All over the place 😫
Runtime support Little 😀 Substantial 😫
The C# Way
async Task<String> work() {
Thread.sleep(200);
return “done”;
}
async Task moreWork() {
Console.WriteLine(“Work started”);
var str = await work();
Console.WriteLine($“Work completed: {str}”);
}
The Kotlin Way
fun work(): Deferred<String> = async(CommonPool) {
delay(200). // non-blocking Thread.sleep()
“done”
}
fun moreWork():Deferred<Unit> = async(CommonPool) {
println(“Work started”)
val str = await(work())
println(“Work completed: $str”)
}
How suspension works
fun moreWork():Deferred<Unit> =
async(CommonPool) {
println(“Work started”)
val str = await(work())
println(“Work completed: $str”)
}
controller.await(
work(),
current_continuation
)
return
Coroutines : Job
@Test fun `coroutine is light-weight`() = runBlocking {
val jobs = List(100_000) {
launch(CommonPool) {
delay(1000L)
print(".")
}
}
jobs.forEach { it.join() }
}
Yield example : Lazy Fibonacci
val seq = buildSequence<Int> {
var a = 0
var b = 1
yield(1)
while (true) {
yield(a + b)
val tmp = a + b
a = b
b = tmp
}
}
val list = seq.take(10).toList()
assertThat(list).isEqualTo(listOf(1, 1, 2, 3, 5, 8, 13, 21, 34, 55))
Channel
@Test fun `channel basic`() = runBlocking {
val channel = Channel<Int>()
launch(CommonPool) {
(1 .. 5).forEach { channel.send(it * it) }
}
repeat(5) {
println(channel.receive())
}
println("Done!")
}
Async@Spring
SpringCamp 2017 참고
Spring Framework 비동기 방식
• @Async
• Async Request Processing
• Callable
• DeferedResult
• ResponseBodyEmitter
• AsyncRestTemplate
@Async
• SimpleAsyncTaskExecutor 를 이용하여, 지정한 작업을 수행
• Not ThreadPool !!!
• @Async 는 실전에서는 사용하지 말 것 !!!
Asychronous MVC 의 리턴 타입
• Callable<T>
• WebAsyncTask<T>
• DeferredResult<T>
• ListenableFuture<T>
• CompletionStage<T>
• ResponseBodyEmitter
@GetMapping("/composeasync2")
DeferredResult<String> asyncCompose2() {
DeferredResult dr = new DeferredResult();
ListenableFuture<String> f1 = myService.async();
f1.addCallback(res1 -> {
ListenableFuture<String> f2 = myService.async2(res1);
f2.addCallback(res2 -> {
ListenableFuture<String> f3 = myService.async3(res2);
f3.addCallback(res3 -> {
dr.setResult(res3);
}, e -> {
dr.setErrorResult(e);
});
}, e -> {
dr.setErrorResult(e);
});
}, e->{
dr.setErrorResult(e);
});
return dr;
}
알흠다운 콜백
헬
AsyncRestTemplate
• Spring 4.0 부터 RestTemplate 의 비동기-논블록킹 버전인
AsyncRestTemplate 제공
• 겉은 비동기-논블록킹이지만 논블록킹 IO 를 사용하지 않음 ㅠ.
ㅠ
• Netty 를 이용하여 논블록킹 IO (NioEventLoopEventGroup) 을
사용할 수 있음
• 리턴 타입이 ListenableFuture 라 콜백 헬 발생 !!!
 ListenableFuture 를 Kotlin Coroutines 의 Deferred 로 변환
가능
Async@Spring
• TaskExecutor 의 전략적 활용이 중요
• 스프링의 모든 비동기 기술에는 ExecutorService 의 세밀한 설정이 가
능
• CompletableFuture 도 ExecutorService의 설계가 중요
• 비동기 스프링 기술을 사용하는 이유?
• IO 가 많은 서버에서 서버 자원의 효율적 활용
Low Latency, High Throughput
• 서버 외부 작업
• 그럼 Spring 에서 다른 방법은 없나
• Callback Hell 은 못 피하는 것인가?
• Java 8 ForkJoin Pool 이나 Scala 의 Global Executor 을 쓰면 안되나?
•
Coroutines@Spring
Coroutines with Spring
• Kotlin suspend 함수를 Spring 에서 직접 이용
• Spring TaskExecutor 를 사용하지 않고, ForkJoin Pool 사용
• Callback Hell 없이 async/await 사용
• Spring 에서 Kotlin Coroutines 의 다양한 기능 활용
• Async IO
• Channel
Coroutines 을 사용하기 위한 Spring Configuration
@SpringBootApplication
@EnableAutoConfiguration
@EnableCoroutine
@EnableWebCoroutine
open class DemoAppConfiguration {
@Bean
fun demoService(): DemoService {
return DemoService()
}
}
open class DemoService {
@Scheduled(fixedRate = 60_000)
suspend open fun everyMinute() {
log.info { "I'm still alive ... every minutes I will back..." }
}
suspend open fun delayedReturn(str: String, delayMillis: Long): String {
delay(delayMillis)
return str
}
@Coroutine(COMMON_POOL)
suspend open fun commonPoolReturn(str: String, delayMillis: Long): String {
delay(delayMillis)
return str
}
}
Coroutines 가 적용된 RestController
@RestController
open class DemoController @Inject constructor(private val demoService: DemoService) {
private val restOperations = CoroutineRestOperations.invoke()
@GetMapping("/delayed")
suspend open fun delayedReturn(): String {
log.info { "Before call to [demoService.delayed]" }
val result = demoService.delayedReturn("delayed", 1000)
log.info { "After call to [demoService.delayed]" }
return result
}
@GetMapping("/commonPool")
suspend open fun commonPoolReturn(): String {
log.info { "Before call to [demoService.commonPoolReturn]" }
val result = demoService.commonPoolReturn("commonPool", 1000)
log.info { "After call to [demoService.commonPoolReturn]" }
return result
}
@GetMapping("/rest")
@Coroutine(COMMON_POOL)
suspend open fun rest(request: HttpServletRequest): String {
val result = restOperations.getForEntity(request.requestURL.toString()
.replace("rest", "delayed"),
String::class.java)
return "Rest result: ${result.body}"
}
RestTemplate 에서 Coroutine 이 적용된 CoroutineRestOperations 인터페이스를 사용하여,
외부 서버 정보를 요청할 수도 있다.  RestTemplate 처럼 Blocking 되지 않는다.
interface CoroutineRestOperations {
companion object : KLogging() {
operator fun invoke(restOperations: RestOperations = RestTemplate(),
context: CoroutineContext = NewThreadCoroutineDispatcher): CoroutineRestOperations {
log.info { "Create CoroutineRestOperations Proxy ..." }
return createCoroutineProxy(CoroutineRestOperations::class.java,
restOperations,
DefaultCoroutineProxyConfig(context))
}
}
}
suspend fun <T : Any?> getForEntity(url: String, responseType: Class<T>?, vararg uriVariables: Any?):
ResponseEntity<T>
Concolusion
• 범용의 Spring Framework 에 Kotlin Coroutines 을 사용
• Low latency, High throughput 실현
• 비동기, 논 블럭킹을 Readable Code 로 구현
• Java CompletableFuture 의 thenXXXX 메소드에서 해방
• Spring context 를 이용하여 향후 retry, scheduled 등 다양한
방식의 구현체에 Coroutines 적용 예정
• Effective Java 를 배워서 구현하려면, 차라리 Kotlin 으로 구현
해라
• 향후 Kotlin Native 로 진정한 비동기 IO 를 사용할 수 있다.
Thank you!

More Related Content

PDF
COPY FROMで異常データをスキップできるようになった話(第45回 PostgreSQLアンカンファレンス@オンライン 発表資料)
PPTX
Getting started with postgresql
PDF
Cassandra techniques de modelisation avancee
PPTX
ELK Stack
PPTX
Google cloud Dataflow & Apache Flink
PPTX
Angular Data Binding
PDF
Image Processing on Delta Lake
PPT
Solr Presentation
COPY FROMで異常データをスキップできるようになった話(第45回 PostgreSQLアンカンファレンス@オンライン 発表資料)
Getting started with postgresql
Cassandra techniques de modelisation avancee
ELK Stack
Google cloud Dataflow & Apache Flink
Angular Data Binding
Image Processing on Delta Lake
Solr Presentation

What's hot (20)

PDF
The Point of Vue - Intro to Vue.js
PDF
Using PostgreSQL for Data Privacy
PDF
Python as part of a production machine learning stack by Michael Manapat PyDa...
PDF
Laporan Praktikum Aplikasi Komputer Sistem Operasi
PDF
Deep dive into Coroutines on JVM @ KotlinConf 2017
PPTX
Splunk
PDF
Get to know PostgreSQL!
PDF
Morel, a Functional Query Language
PDF
Vuex to Pinia, how to migrate an existing app
PDF
Tips on how to improve the performance of your custom modules for high volume...
PDF
ElasticSearch in action
PDF
Spring Framework - AOP
PDF
Apache Spark 2.0: A Deep Dive Into Structured Streaming - by Tathagata Das
PPTX
Konsep dasar oop
PDF
Introduction to Apache Solr
PDF
Microservices Tracing With Spring Cloud and Zipkin @Szczecin JUG
PDF
Introduction to elasticsearch
PDF
ES6 presentation
PPTX
RocksDB detail
PPTX
Snowflake Data Loading.pptx
The Point of Vue - Intro to Vue.js
Using PostgreSQL for Data Privacy
Python as part of a production machine learning stack by Michael Manapat PyDa...
Laporan Praktikum Aplikasi Komputer Sistem Operasi
Deep dive into Coroutines on JVM @ KotlinConf 2017
Splunk
Get to know PostgreSQL!
Morel, a Functional Query Language
Vuex to Pinia, how to migrate an existing app
Tips on how to improve the performance of your custom modules for high volume...
ElasticSearch in action
Spring Framework - AOP
Apache Spark 2.0: A Deep Dive Into Structured Streaming - by Tathagata Das
Konsep dasar oop
Introduction to Apache Solr
Microservices Tracing With Spring Cloud and Zipkin @Szczecin JUG
Introduction to elasticsearch
ES6 presentation
RocksDB detail
Snowflake Data Loading.pptx
Ad

Similar to Kotlin coroutines and spring framework (20)

PDF
The Swift Compiler and Standard Library
PPT
An Overview Of Python With Functional Programming
PPTX
KotlinForJavaDevelopers-UJUG.pptx
PDF
Denis Lebedev, Swift
PDF
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
PPT
Os Reindersfinal
PPT
Os Reindersfinal
PDF
Kotlin: A pragmatic language by JetBrains
PDF
TypeScript Best Practices
PDF
Effective Object Oriented Design in Cpp
PDF
What can be done with Java, but should better be done with Erlang (@pavlobaron)
PDF
C# - What's next
PDF
Cocoa heads 09112017
PPSX
Java Tutorial
PPT
Scala - brief intro
PDF
Android 101 - Building a simple app with Kotlin in 90 minutes
PDF
Kotlin boost yourproductivity
PDF
Introduction to Scalding and Monoids
PDF
From Java to Scala - advantages and possible risks
PDF
Kotlin, smarter development for the jvm
The Swift Compiler and Standard Library
An Overview Of Python With Functional Programming
KotlinForJavaDevelopers-UJUG.pptx
Denis Lebedev, Swift
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
Os Reindersfinal
Os Reindersfinal
Kotlin: A pragmatic language by JetBrains
TypeScript Best Practices
Effective Object Oriented Design in Cpp
What can be done with Java, but should better be done with Erlang (@pavlobaron)
C# - What's next
Cocoa heads 09112017
Java Tutorial
Scala - brief intro
Android 101 - Building a simple app with Kotlin in 90 minutes
Kotlin boost yourproductivity
Introduction to Scalding and Monoids
From Java to Scala - advantages and possible risks
Kotlin, smarter development for the jvm
Ad

More from Sunghyouk Bae (16)

PDF
JUnit5 and TestContainers
PDF
Introduction of failsafe
PDF
Kotlin @ Coupang Backed - JetBrains Day seoul 2018
PDF
Spring data requery
PDF
Requery overview
PDF
Kotlin @ Coupang Backend 2017
PDF
measure metrics
PDF
Alternatives of JPA/Hibernate
PPTX
Java naming strategy (자바 명명 전략)
PPTX
테스트자동화와 TDD
PPTX
SpringBoot with MyBatis, Flyway, QueryDSL
PPTX
JUnit & AssertJ
PPTX
좋은 개발자 되기
PDF
Using AdoRepository
PDF
Multithread pattern 소개
PDF
Strategy Maps
JUnit5 and TestContainers
Introduction of failsafe
Kotlin @ Coupang Backed - JetBrains Day seoul 2018
Spring data requery
Requery overview
Kotlin @ Coupang Backend 2017
measure metrics
Alternatives of JPA/Hibernate
Java naming strategy (자바 명명 전략)
테스트자동화와 TDD
SpringBoot with MyBatis, Flyway, QueryDSL
JUnit & AssertJ
좋은 개발자 되기
Using AdoRepository
Multithread pattern 소개
Strategy Maps

Recently uploaded (20)

PDF
Cost to Outsource Software Development in 2025
PDF
Salesforce Agentforce AI Implementation.pdf
PPTX
Monitoring Stack: Grafana, Loki & Promtail
PPTX
Weekly report ppt - harsh dattuprasad patel.pptx
PDF
iTop VPN Free 5.6.0.5262 Crack latest version 2025
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
AutoCAD Professional Crack 2025 With License Key
PPTX
Patient Appointment Booking in Odoo with online payment
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
Autodesk AutoCAD Crack Free Download 2025
PPTX
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
PDF
Nekopoi APK 2025 free lastest update
PDF
Download FL Studio Crack Latest version 2025 ?
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Designing Intelligence for the Shop Floor.pdf
PDF
Tally Prime Crack Download New Version 5.1 [2025] (License Key Free
PDF
How to Make Money in the Metaverse_ Top Strategies for Beginners.pdf
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PPTX
assetexplorer- product-overview - presentation
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Cost to Outsource Software Development in 2025
Salesforce Agentforce AI Implementation.pdf
Monitoring Stack: Grafana, Loki & Promtail
Weekly report ppt - harsh dattuprasad patel.pptx
iTop VPN Free 5.6.0.5262 Crack latest version 2025
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
AutoCAD Professional Crack 2025 With License Key
Patient Appointment Booking in Odoo with online payment
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
Autodesk AutoCAD Crack Free Download 2025
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
Nekopoi APK 2025 free lastest update
Download FL Studio Crack Latest version 2025 ?
CHAPTER 2 - PM Management and IT Context
Designing Intelligence for the Shop Floor.pdf
Tally Prime Crack Download New Version 5.1 [2025] (License Key Free
How to Make Money in the Metaverse_ Top Strategies for Beginners.pdf
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
assetexplorer- product-overview - presentation
Adobe Illustrator 28.6 Crack My Vision of Vector Design

Kotlin coroutines and spring framework

  • 1. Kotlin Coroutines & Spring Framework Coupang Tech CoP Catalog Platform & Quality tribe [email protected]
  • 2. 목차 • Why Kotlin? • Coroutines • Spring Asynchronous • Spring with Coroutines
  • 3. Why Kotlin? Concise, Safe, Versatile, Interoperable, Tooling
  • 4. Combines OO and functional features Focused on • Interoperability • Safety • Clarity • Tooling support a pragmatic programming language for JVM, Android, JavaScript, LLVM
  • 7. Concise Drastically reduce The amount of boilerplate code you need to write data class Customer(val name: String, var email: String, val company: String = “coupang”) Use lambda expression val positiveNumbers = list.filter { it > 0 } data class : POJO with getter,setter, equals, hashCode, toString, copy
  • 8. Concise Use lambda expression val positiveNumbers = list.firstOrNull { it > 0 } Lazy initialization lateinit var positiveNumbers:List<Int> val positiveNumbers by lazy { listOf(1,2,3) }
  • 9. SAFE All type is Nonnull is default var output:String output = null // compilation error println(output.length()) user?.name?.isEmpty() ?: true Rid NullPointerExceptions !!! Auto-cast fun calcuateTotal(obj:Any) { if(obj is Invoice) { obj.calculateTotal() // auto-cast } }
  • 10. Versatile • Android : No performance impact. Very small runtime. • JavaScript: Write code in Kotlin and target JavaScript to run on Node.js or in browser • Web: Whether you want strongly typed HTML, CSS builder or just plain web development • Application Server • The technology doesn’t matter. 100% compatible with all JVM frameworks. • Enterpise • Use Kotlin for any type of Enterprise Java EE development. • Native • Kotlin/Native is a LLVM backend for the Kotlin compiler, runtime implementation and native code generation facility using LLVM toolchain.
  • 12. Functions fun sum(a: Int, b: Int): Int { return a + b } fun sum(a: Int, b: Int) = a + b fun printSum(a: Int, b: Int): Unit { print(a + b) } Variables val a: Int = 1 val b = 1 // `Int` type is inferred var c: Int // Type required when no initializer // is provided c = 1 // definite assignment var x = 5 // `Int` type is inferred x += 1 x ++
  • 13. String Interpolation val i = 10 val s = “i=$i” // evaluates to “i=10" val s = “abc” val str = “$s.length is ${s.length}” // evaluates to “abc.length is 3" val price = ""” |${‘$’}9.99 ""”.trimMargin() When Expression when (x) { 1 -> print(“x == 1”) 2 -> print(“x == 2”) 0, 1 -> print(“x == 0 or x == 1”) parseInt(s) -> print(“s encodes x”) in 1..10 -> print(”x is in the range”) in validNumbers -> !in 10..20 -> print(”x is not in the range”) is String -> x.startsWith(“prefix”) x.isOdd() -> print(“x is odd”) x.isEven() -> print(“x is even”) else -> println(“otherwise”) }
  • 14. Loop for(item in collection) print(item) for(i in array.indices) print(array[i]) for((index,value) in array.withIndex()) { print(“element at $index is $value”) } Collections val immutableList = listOf(1, 2, 3) val mutable = mutableListOf(1, 2, 3) val arrayList = arrayListOf(1, 2, 3) val immutableMap = mapOf("foo" to 1, "bar" to 2) val readWriteMap = hashMapOf("foo" to 1, "bar" to 2) println(map["foo"])
  • 16. null safety clean = cleaner?.javaClass?.getMethod("clean") fun load(resourceBasename: String, rootPath: String? = null): Config { val config = ConfigFactory.load(resourceBasename) return rootPath?.let { path -> config.getConfig(path) } ?: config }
  • 17. Operators operator fun Duration.unaryMinus(): Duration = this.negated() operator fun Duration.div(divisor: Int): Duration = this.dividedBy(divisor.toLong()) operator fun Duration.div(divisor: Long): Duration = this.dividedBy(divisor) operator fun Duration.times(multiplicand: Int): Duration = this.multipliedBy(multiplicand.toLong()) operator fun Duration.times(multiplicand: Long): Duration = this.multipliedBy(multiplicand) operator fun ReadableInstant.rangeTo(other: ReadableInstant): Interval = Interval(this, other) operator fun Instant.minus(builder: DurationBuilder): Instant = this.minus(builder.period.toStandardDuration()) operator fun Instant.plus(builder: DurationBuilder): Instant = this.plus(builder.period.toStandardDuration()) operator fun get(index: Int): ITimeLineMoment operator fun set(index: Int, value:ITimeLineMoment): Unit
  • 18. Extension Functions fun String?.toUtf8Bytes(): ByteArray = this?.toByteArray(Charsets.UTF_8) ?: emptyByteArray fun String?.toUtf8ByteBuffer(): ByteBuffer = this?.let { Charsets.UTF_8.encode(this) } ?: ByteBuffer.allocate(0) fun ByteArray?.toUtf8String(): String = this?.toString(Charsets.UTF_8) ?: EMPTY_STRING fun ByteBuffer?.toUtf8String(): String = this?.let { Charsets.UTF_8.decode(this).toString() } ?: EMPTY_STRING fun <T> Array<T>.stream(): Stream<T> = Arrays.stream(this)
  • 19. Coroutines in Kotlin Experimental features in Kotlin 1.1 kotlinx.coroutines
  • 20. A Fiber is a lightweight thread that uses cooperative multitasking instead of preemptive multitasking. A running fiber must explicitly "yield" to allow another fiber to run, which makes their implementation much easier than kernel or user threads. A Coroutine is a component that generalizes a subroutine to allow multiple entry points for suspending and resuming execution at certain locations. Unlike subroutines, coroutines can exit by calling other coroutines, which may later return to the point where they were invoked in the original coroutine. A Green Thread is a thread that is scheduled by a virtual machine (VM) instead of natively by the underlying operating system. Green threads emulate multithreaded environments without relying on any native OS capabilities, and they are managed in user space instead of kernel space, enabling them to work in environments that do not have native thread support.
  • 21. • Process: OS-managed (possibly) truly concurrent, at least in the presence of suitable hardware support. Exist within their own address space. • Thread: OS-managed, within the same address space as the parent and all its other threads. Possibly truly concurrent, and multi-tasking is pre-emptive. • Green Thread: These are user-space projections of the same concept as threads, but are not OS- managed. Probably not truly concurrent, except in the sense that there may be multiple worker threads or processes giving them CPU time concurrently, so probably best to consider this as interleaved or multiplexed. • Fibers: OS-managed. Exactly threads, except co-operatively multitasking, and hence not truly concurrent. • Coroutines: Exactly fibers, except not OS-managed. • Goroutines: They claim to be unlike anything else, but they seem to be exactly green threads, as in, process-managed in a single address space and multiplexed onto system threads. Perhaps somebody with more knowledge of Go can cut through the marketing material.
  • 22. 이런 개념들을 알아야 … async/await / yield fibers [stackless] continuations Suspendable Computations
  • 23. public CompletionStage<Boolean> addAdultItemAsync(final long productId, final long itemId) { log.trace("Add adult product cache. productId={}, itemId={}", productId, itemId); final RLock lock = getProductLock(productId); return lock.lockAsync(3000, TimeUnit.MILLISECONDS) .thenComposeAsync(rl -> updateProductItemMapping(productId, itemId), global) .thenComposeAsync(updated -> adultInverseIndex.fastPutAsync(itemId, productId), global) .thenComposeAsync(added -> adultProductItemMap.putAsync(productId, itemId), global) .whenCompleteAsync((result, error) -> lock.forceUnlock(), global); } Future combination is weired 😫
  • 24. Suspendable Computation asyncUI { val image = await(loadImage(url)) myUI.setImage(image) } Suspending call Time consuming operation UI Thread await(…) loadImage(url) Worker Thread setImage(…) Continuation
  • 25. Coroutines Goals • Asynchronous programming (and more) • without explicit callbacks • without explicit Future combinators (see Deathwing code) • Maximum flexibility for library designer • with minimal runtime support • and no macros (like Scala)
  • 26. Coroutines 종류 Stackless Stackful Language restrictions Use in special context 😫 Use anywhere 😀 Implemented in C#, Scala, Kotlin, … Quasar, Javaflow … Code transformation Local (compiler magic) 😀 All over the place 😫 Runtime support Little 😀 Substantial 😫
  • 27. The C# Way async Task<String> work() { Thread.sleep(200); return “done”; } async Task moreWork() { Console.WriteLine(“Work started”); var str = await work(); Console.WriteLine($“Work completed: {str}”); }
  • 28. The Kotlin Way fun work(): Deferred<String> = async(CommonPool) { delay(200). // non-blocking Thread.sleep() “done” } fun moreWork():Deferred<Unit> = async(CommonPool) { println(“Work started”) val str = await(work()) println(“Work completed: $str”) }
  • 29. How suspension works fun moreWork():Deferred<Unit> = async(CommonPool) { println(“Work started”) val str = await(work()) println(“Work completed: $str”) } controller.await( work(), current_continuation ) return
  • 30. Coroutines : Job @Test fun `coroutine is light-weight`() = runBlocking { val jobs = List(100_000) { launch(CommonPool) { delay(1000L) print(".") } } jobs.forEach { it.join() } }
  • 31. Yield example : Lazy Fibonacci val seq = buildSequence<Int> { var a = 0 var b = 1 yield(1) while (true) { yield(a + b) val tmp = a + b a = b b = tmp } } val list = seq.take(10).toList() assertThat(list).isEqualTo(listOf(1, 1, 2, 3, 5, 8, 13, 21, 34, 55))
  • 32. Channel @Test fun `channel basic`() = runBlocking { val channel = Channel<Int>() launch(CommonPool) { (1 .. 5).forEach { channel.send(it * it) } } repeat(5) { println(channel.receive()) } println("Done!") }
  • 34. Spring Framework 비동기 방식 • @Async • Async Request Processing • Callable • DeferedResult • ResponseBodyEmitter • AsyncRestTemplate
  • 35. @Async • SimpleAsyncTaskExecutor 를 이용하여, 지정한 작업을 수행 • Not ThreadPool !!! • @Async 는 실전에서는 사용하지 말 것 !!!
  • 36. Asychronous MVC 의 리턴 타입 • Callable<T> • WebAsyncTask<T> • DeferredResult<T> • ListenableFuture<T> • CompletionStage<T> • ResponseBodyEmitter
  • 37. @GetMapping("/composeasync2") DeferredResult<String> asyncCompose2() { DeferredResult dr = new DeferredResult(); ListenableFuture<String> f1 = myService.async(); f1.addCallback(res1 -> { ListenableFuture<String> f2 = myService.async2(res1); f2.addCallback(res2 -> { ListenableFuture<String> f3 = myService.async3(res2); f3.addCallback(res3 -> { dr.setResult(res3); }, e -> { dr.setErrorResult(e); }); }, e -> { dr.setErrorResult(e); }); }, e->{ dr.setErrorResult(e); }); return dr; } 알흠다운 콜백 헬
  • 38. AsyncRestTemplate • Spring 4.0 부터 RestTemplate 의 비동기-논블록킹 버전인 AsyncRestTemplate 제공 • 겉은 비동기-논블록킹이지만 논블록킹 IO 를 사용하지 않음 ㅠ. ㅠ • Netty 를 이용하여 논블록킹 IO (NioEventLoopEventGroup) 을 사용할 수 있음 • 리턴 타입이 ListenableFuture 라 콜백 헬 발생 !!!  ListenableFuture 를 Kotlin Coroutines 의 Deferred 로 변환 가능
  • 39. Async@Spring • TaskExecutor 의 전략적 활용이 중요 • 스프링의 모든 비동기 기술에는 ExecutorService 의 세밀한 설정이 가 능 • CompletableFuture 도 ExecutorService의 설계가 중요 • 비동기 스프링 기술을 사용하는 이유? • IO 가 많은 서버에서 서버 자원의 효율적 활용 Low Latency, High Throughput • 서버 외부 작업 • 그럼 Spring 에서 다른 방법은 없나 • Callback Hell 은 못 피하는 것인가? • Java 8 ForkJoin Pool 이나 Scala 의 Global Executor 을 쓰면 안되나? •
  • 41. Coroutines with Spring • Kotlin suspend 함수를 Spring 에서 직접 이용 • Spring TaskExecutor 를 사용하지 않고, ForkJoin Pool 사용 • Callback Hell 없이 async/await 사용 • Spring 에서 Kotlin Coroutines 의 다양한 기능 활용 • Async IO • Channel
  • 42. Coroutines 을 사용하기 위한 Spring Configuration @SpringBootApplication @EnableAutoConfiguration @EnableCoroutine @EnableWebCoroutine open class DemoAppConfiguration { @Bean fun demoService(): DemoService { return DemoService() } }
  • 43. open class DemoService { @Scheduled(fixedRate = 60_000) suspend open fun everyMinute() { log.info { "I'm still alive ... every minutes I will back..." } } suspend open fun delayedReturn(str: String, delayMillis: Long): String { delay(delayMillis) return str } @Coroutine(COMMON_POOL) suspend open fun commonPoolReturn(str: String, delayMillis: Long): String { delay(delayMillis) return str } }
  • 44. Coroutines 가 적용된 RestController @RestController open class DemoController @Inject constructor(private val demoService: DemoService) { private val restOperations = CoroutineRestOperations.invoke() @GetMapping("/delayed") suspend open fun delayedReturn(): String { log.info { "Before call to [demoService.delayed]" } val result = demoService.delayedReturn("delayed", 1000) log.info { "After call to [demoService.delayed]" } return result } @GetMapping("/commonPool") suspend open fun commonPoolReturn(): String { log.info { "Before call to [demoService.commonPoolReturn]" } val result = demoService.commonPoolReturn("commonPool", 1000) log.info { "After call to [demoService.commonPoolReturn]" } return result }
  • 45. @GetMapping("/rest") @Coroutine(COMMON_POOL) suspend open fun rest(request: HttpServletRequest): String { val result = restOperations.getForEntity(request.requestURL.toString() .replace("rest", "delayed"), String::class.java) return "Rest result: ${result.body}" } RestTemplate 에서 Coroutine 이 적용된 CoroutineRestOperations 인터페이스를 사용하여, 외부 서버 정보를 요청할 수도 있다.  RestTemplate 처럼 Blocking 되지 않는다. interface CoroutineRestOperations { companion object : KLogging() { operator fun invoke(restOperations: RestOperations = RestTemplate(), context: CoroutineContext = NewThreadCoroutineDispatcher): CoroutineRestOperations { log.info { "Create CoroutineRestOperations Proxy ..." } return createCoroutineProxy(CoroutineRestOperations::class.java, restOperations, DefaultCoroutineProxyConfig(context)) } } } suspend fun <T : Any?> getForEntity(url: String, responseType: Class<T>?, vararg uriVariables: Any?): ResponseEntity<T>
  • 46. Concolusion • 범용의 Spring Framework 에 Kotlin Coroutines 을 사용 • Low latency, High throughput 실현 • 비동기, 논 블럭킹을 Readable Code 로 구현 • Java CompletableFuture 의 thenXXXX 메소드에서 해방 • Spring context 를 이용하여 향후 retry, scheduled 등 다양한 방식의 구현체에 Coroutines 적용 예정 • Effective Java 를 배워서 구현하려면, 차라리 Kotlin 으로 구현 해라 • 향후 Kotlin Native 로 진정한 비동기 IO 를 사용할 수 있다.