5. 5
K2 컴파일러의 압도적인 프론트엔드 향상
https://blog.jetbrains.com/ko/kotlin/2023/04/kotlinconf-2023-opening-keynote/
6. 6
프론트엔드와 백엔드가 무엇인가요?
프론트
엔드
파서와 시멘틱 애널라이저로 구성.
소스코드를 읽어 구문 트리를 만들고 의미 정보를
추가함.
백엔드
중간 코드 생성 & 최적화기와 머신 코드 생성 최적
화로 나누어짐.
최적화를 하고 기계어 코드나 타겟 코드를 생성.
코틀린의 경우에는 자바 Bytecode나 LLVM의
Bitcode가 타겟.
코틀린
코틀린의 경우에 (1.3까지) 중간 코드 생성 & 최적
화기가 없었음.
효율보다는 코틀린 언어의 발전이 더 중요했음.
(기술부채)
https://twitter.com/kotlin
7. 7
백엔드에 IR의 도입
IR 백엔드에서 공유하는 중간 수준의 언어
IR
generator
& optimizer
IR을 만들고 최적화 하는 파트.
코틀린 네이티브를 만들며 새롭게 추가. 이
후 JVM(1.5)과 JS(1.6)을 IR을 쓰도록 재
작성.
공통적인 최적화를 할 수 있다. (그전까지
는 백엔드마다 별도로 작성.)
의도하지는 않았지만 새 백엔드의 성능이
향상!
https://twitter.com/kotlin
8. 남은 것은 프론트엔드
레거시 PSI (Program Structure Interface)
PSI
Program Structure Interface
코틀린 코드를 파싱한 결과 트리. IntelliJ에서 먼저 쓰던 구조를 코틀린 컴파일러도 차용.
소스 코드와 거의 대응되는 단순한 형태.
13. PSI + BindingContext가 문제가 있나요?
최적화
프론트엔드 수준에서 PSI에서 최적화를 하는 것이 쉽지 않음.
문맥이 별도의 BIndingContext에 있는 것도 최적화에 좋지 못함.
캐쉬 미스 BindingContext가 거대한 Map이어서 캐쉬 효율에 좋지 못함.
17. 프론트엔드
왜 FIR이 두개가 있나요?
파서 Raw FIR 빌더 Analyze
체커
파스트리 FIR FIR
진단
Lowering
단순화(simplify)라고 설명. 디슈거링(Desugraing)이라고도 표현.
비구조화 (Desctructure)를 연속된 대입으로 변경.
for 등을 while으로 변경. 연산자(+, +=, in, …)등을 명시적인 호출로 변형.
기타 프론트엔드 수준에서의 최적화도 수행.
18. 18
FIR 기반의 프론트엔트의 장점
컴파일러 성능 FIR 기반으로 만든 프론트엔드는 PSI + BindingContext 기반의 프론트엔드 보다 훨신 빠름.
IDE
IDE도 프론트엔드를 공유. 인텔리제이에서 의미를 파악하고 코드 하이라이팅, 분석하는 속도가 빨라짐.
Kotlin IDE 플러그인 재작성중.
19. 19
가장 많이 요청받은 기능
Static Extensions 인스턴스가 아니더라도 확장 함수를 만들 수 있음.
Collection Literals listOf, mapOf, setOf 가 아닌 리터럴로 컬렉션.
Name-based Destructuring 비구조화(구조분해)를 위치 기반이 아니라 이름 기반으로.
Explicit Fields 같은 컨셉의 private, public 프로퍼티를 만들지 않아도 됨.
Context Receivers 멤버 확장 함수 이외에 Context를 지정할 방법의 추가.
20. 20
정적 확장 (Static Extensions)
https://youtrack.jetbrains.com/issue/KT-11968
File.open("data.txt")
21. 21
정적 확장 (Static Extensions)
https://youtrack.jetbrains.com/issue/KT-11968
File.open("data.txt")
fun File.Companion.open(name: String)
22. 22
정적 확장 (Static Extensions)
https://youtrack.jetbrains.com/issue/KT-11968
File.open("data.txt")
fun File.Companion.open(name: String)
23. 23
정적 확장 (Static Extensions)
https://youtrack.jetbrains.com/issue/KT-11968
File.open("data.txt")
fun File.Static.open(name: String)
29. 29
이름 기반 비구조화 (Name-Based Restructuring)
https://youtrack.jetbrains.com/issue/KT-19627
data class Person(
val
fi
rstName: String,
val lastName: String
)
30. 30
이름 기반 비구조화 (Name-Based Restructuring)
https://youtrack.jetbrains.com/issue/KT-19627
data class Person(
val
fi
rstName: String,
val lastName: String
)
val (
fi
rstName, lastName) = person
31. 31
이름 기반 비구조화 (Name-Based Restructuring)
https://youtrack.jetbrains.com/issue/KT-19627
data class Person(
val
fi
rstName: String,
val lastName: String
)
val (lastName,
fi
rstName) = person
32. 32
컨택스트 수신자 (Context Receivers)
https://youtrack.jetbrains.com/issue/KT-10468
fun process(
context: ServiceContext,
request: ServiceRequest
) {
val data = request.loadData(context)
}
33. 33
컨택스트 수신자 (Context Receivers)
https://youtrack.jetbrains.com/issue/KT-10468
fun process(
context: ServiceContext,
request: ServiceRequest
) {
val data = request.loadData(context)
}
context(ServiceContext)
fun processRequest(request: ServiceRequest)
34. 34
컨택스트 수신자 (Context Receivers)
https://youtrack.jetbrains.com/issue/KT-10468
context(ServiceContext)
fun processRequest(request: ServiceRequest) {
val data = request.loadData()
//
}
35. 35
컨택스트 수신자 (Context Receivers)
https://youtrack.jetbrains.com/issue/KT-10468
context(ServiceContext)
fun processRequest(request: ServiceRequest) {
val data = request.loadData()
//
}
context(ServiceContext)
fun ServiceRequest.loadData(): Data
36. 36
명시적 필드 (Explicit Fields)
https://youtrack.jetbrains.com/issue/KT-14663
private val _applicationState =
MutableStateFlow(State())
val applicationState: StateFlow<State>
get() = _applicationState
37. 37
명시적 필드 (Explicit Fields)
https://youtrack.jetbrains.com/issue/KT-14663
private val _applicationState =
MutableStateFlow(State())
val applicationState: StateFlow<State>
get() = _applicationState
val applicationState: StateFlow<State>
fi
eld = MutableStateFlow(State())
61. 61
버전 처리는 어떻게 했을까요?
expect와 actual
shared/src/
commonMain
iOS와 Android에서 모두 사용할 인터페이스를 expect 키워드로 만듬.
62. 62
버전 처리는 어떻게 했을까요?
expect와 actual
shared/src/
androidMain
Android의 구현을 actual 키워드를 붙여 구현
63. 63
버전 처리는 어떻게 했을까요?
expect와 actual
shared/src/
iOSMain
iOS의 구현을 actual 키워드를 붙여 구현
64. 64
KMM for iOS에서 만나게 되는 상황들
ObjC
현재 Kotlin은 ObjC만 지원해서 제너릭 클래스만 지원하고 인터페이스를 지원하지 못함. Abstract
class를 대신 사용해야 함.
@HinddenFromObjC, @ObjcName 키워드를 적극적으로 활용하자.
@ObjcName(swiftName=“_”) _는 특수한 키워드.
plane.fuel(volume: .Gallos(gallos: 12.5)) 대신 plane.fuel(.Gallons(12.5))
장기적으로는 코트린이 Swift를 바로 타게팅할 것임. Swift를 ObjeC를 제외하고 바인드할 수 없었기에 발
생한 문제.
SourceKitten와 같은 도구들로 중간 코드를 생성하자.
라인 데메에카이 겪은 어려움
Suspend
suspend는 콜백(completion handler)이 되고 콜백은 Swift에서 async로 호출 가능하지만 취소가 불
가능함. Flow도 잘 지원되지 않음.
KMP-NativeCoroutines 라이브러리를 활용해야 함.
https://github.com/rickclephas/KMP-NativeCoroutines
코틀린 예외가 스위프트 핸들러 전달 되지 않을 수 있어 @Throws 키워드로 Error를 지정해야 함.
65. 65
KMM for iOS에서 만나게 되는 상황들
CocoaPods
아직 공식적으로 SPM(Swift Package Manager)를 지원하지 않음. Gradle API 수준에서 정리된 이후
에 지원한다고 함. (언제?)
CocoaPods는 의존성을 소스로 가져와 같이 빌드에 사용하기에 매우 비효율적.
TouchLab의 라이브러리 KMMBridge를 사용합시다.
https://github.com/touchlab/KMMBridge
SPM을 대응하기 위해서는 Git 리포지토리와 스태틱 파일 저장소가 필요하다. (AWS?)
Frozen
Global Object는 기본으로 frozen. 접근할 수 있지만 변경할 수 없음.
@ThreadLocal을 붙이면 freeze 호출 안함. Atomic한 자료구조의 사용이 필요할 수 있다.
freeze() 확장 함수를 이용해 데이터를 얼릴 수 있고 풀 수는 없음.
Global 프로퍼티는 메인스레드에서만 볼 수 있음.
66. 66
KMM for iOS에서 만나게 되는 상황들
Memory
Management
스택 트레이스 디버깅 어렵고, 메모리 매니지먼트가 아직 안정적이지는 않음.
https://youtrack.jetbrains.com/issue/KT-55512
참고
Kotlin Multiplatform Mobile을 활용한 데마에칸 드라이버앱 개발 이야기
Kotlin/Multiplatform for iOS developers : state & future by Salomon Brys
68. 68
Compose Multiplatform mobile application
템플릿을 이용해서 시작해야
템플릿 https://github.com/JetBrains/compose-multiplatform-ios-android-template
69. 69
Compose for iOS를 위해 필요한 것
Android
Studio
Android 앱과 iOS 앱를 실행할 수 있는 개발 환경.
Xcode
Xcode는 백그라운드에서 수행 됨.
Kotlin/Native가 의존하는 버전을 설치해야 함.
Kotlin
Multiplatform
Mobile
안드로이드 스튜디오에서 Kotlin Multiplatform Mobile 플러그인 설치.
CocoaPods Compose for iOS도 SPM(SwiftPackageManager)를 지원하지 않음.
78. 78
Compose for Desktop의 특징
Cross-
Platform
멀티플랫폼이 아닌 크로스플랫폼으로 분류.
JVM이 타겟이고 JVM 덕에 여러 플랫폼에서 도는 것을 크로스플랫폼으로 설명.
SKIKO
SKIA의 코틀린 바인딩 SKIKO에 의해 렌더링. https://github.com/JetBrains/skiko
SKIA의 폰트 렌더링이 운영체제 마다 달라 스크린 샷 테스트를 하지 말자.
Compose
Multiplatform
IDE support
인텔리제이 아이디어나 안드로이드 스튜디오에 설치.
https://plugins.jetbrains.com/plugin/16541-compose-multiplatform-ide-support
IntelliJ IDEA 인텔리제이 아이디어 2020.3 이상에서 사용가능.
79. 79
Compose for Desktop의 특징
참고영상 You can do desktop too! By Victor Kropp
https://www.youtube.com/watch?v=Mgf_9kxM1BA
JDK 15 JDK11으로 프로젝트 생성 가능. 네이티브 배포 패키징을 위해서는 15 이상.
84. 84
Compose for Web의 특징
WebAssembly
JavaScript를 쓰지 않고 WebAssembly로 실행.
Kotlin/WASM이 타겟.
Compose
HTML
HTML을 생성하는 Kotlin/JS의 라이브러리도 있음.
Compose for Web과 무관.
Compose
Multiplatform
IDE support
인텔리제이 아이디어나 안드로이드 스튜디오에 설치.
https://plugins.jetbrains.com/plugin/16541-compose-multiplatform-ide-support
IntelliJ IDEA 인텔리제이 아이디어 2020.3 이상에서 사용가능.