레이블이 KMM인 게시물을 표시합니다. 모든 게시물 표시
레이블이 KMM인 게시물을 표시합니다. 모든 게시물 표시

2023년 10월 8일 일요일

KMM IOS COMPOSE ALPHA

KMM IOS COMPOSE ALPHA

iOS용 Compose Alpha가 공식적으로 출시

iOS용 Jetpack Compose Multiplatform이 드디어 공식적으로 알파 지원을 출시했습니다.

https://github.com/JetBrains/compose-multiplatform-ios-android-template/#readme

이제까지는 IOS는 주로 도메인의 미지니스 로직에서만 사용하였는데요.
이제 UI부분에서도 사용할수 있게 되어 갑니다.
compose-jb는 공식적으로 compose-multiplatform으로 이름이 바뀌었고 템플릿 프로젝트는 다양한 플랫폼에 제공되었습니다.

또한, iOS 지원에 이어 compose-multiplatform1.4.0 버전이 출시되었는데 , 즉 iOS를 경험하고 싶은 분들은 1.4 버전에서 사용해 보아야 하며 ,Android Studio Flamingo 새 버전과 마찬가지로 본격적으로 시작될 예정입니다. JDK 17을 지원합니다.

이제 공식적으로 Kotlin을 사용하여 유사한 iOS UI를 작성할 수 있으며 Swift-UI와 유사한 개발 경험을 가질 수 있습니다. (잘가. 복잡한 XML). 기존 Compose 프로젝트를 iOS 애플리케이션으로 보다 쉽게 ​​컴파일하여 UI를 구현할 수도 있습니다.

현재 iOS 지원은 아직 알파 단계로, 베타 단계에 이르지 못한 경우 API 및 호환성에 일부 변화가 있을 수 있으나, 정식 출시된 버전에서는 이미 동일한 Kotlin 코드를 사용하여 컴파일하는 경험을 하실 수 있습니다.

KMM(Kotlin Multiplatform Mobile)은 원래 iOS 플랫폼을 지원하고, Compose Multiplatform은 KMM을 기반으로 구축되었기 때문에 블루투스, 카메라 등 iOS 네이티브 API를 지원하는 데에는 큰 문제가 없을 것이며, 동시에 이제 임베디드[MKMapView 와 같은 기본 UI 보기 도 지원됩니다 .

CocosPods 등이 사용가능한 환경(주로 맥) 에서 빌드가 가능하며 이러한 환경체크를 검사는 KDoctor를 이용하여 가능합니다.
, KMM에서 필요한 명령줄 도구이므로 KDoctor를 먼저 brew install kdoctor설치 해야 하며 동시에 KDoctor는 빌드 환경이 정상적인지 여부도 감지할 수 있습니다.

다음으로, compose-multiplatform-ios-android-template 을 사용하면 Compose Multiplatform 프로젝트에 androidApp, iosApp, shared라는 세 가지 모듈이 포함됩니다. 여기서 shared는 이름에서 알 수 있듯이 공유 Kotlin 모듈입니다.

현재 Android 스튜디오의 iOS 시뮬레이터에서 Compose Multiplatform을 실행하려면 iosApp 실행 구성을 선택 해야 하며 주로 해당 실행 대상을 선택해야 합니다.

실제 컴퓨터에서 실행해야 하는 경우 먼저 iOS 개발자 계정이 있어야 하며 Xcode에 로그인해야 합니다.

  • 귀하의 계정에서 정보를 얻으십시오TEAM_ID
  • Xcode에 등록된 iOS 장치인 실제 컴퓨터에 연결합니다.

또한 터미널에서 실행하여 kdoctor --team-ids자연스러운 팀 ID 목록을 얻을 수 있습니다.

당연한 얘기지만 Apple 개발자 등록이 되어 있어야 됩니다.

iOS를 실행하기 전, 위에서 언급한 설정이 필요하며TEAM_IDiosApp/Configuration/Config.xcconfig , 파일 아래의 설정을 열고 TEAM_ID안드로이드 스튜디오에서 프로젝트를 다시 열면 iosApp실행 중인 구성에서 등록된 iOS 디바이스를 확인할 수 있습니다.

iOS용 Compose Multiplatform이 공식적으로 출시되는 날을 기대해 보겠습니다.

2021년 2월 3일 수요일

[Android] Kotlin Multiplatform Mobile, 즉 Kotlin KMM사용해보기

Android, IOS,웹 애시당초 같은 로직을 언어마다 따로 만든다는게 잘못된거 아닌가? 그냥 C++ 하나 정도면 사람이 프로그램하는게 전혀 문제가 없는데, 뭘또 계속 만드는지...여튼 이런 환경에서 Kotlin 이 어느정도 답을 제시하고 있다.

Kotlin MPP 프로젝트는 IntelliJ에서 해도 되고, 익숙한 Android Studio Plugin (Kotlin Multiplatform Mobile) 을 설치해서 해도 된다. 

AndroidStudio 를 이용하면  바로 IOS 도 실행 해볼수 있다.(안되더라)

1. 안드로이드스튜이도에서 신규작성을 할때, 맨마지막에 있는 KMM Application을 선택하자.

2.앱이름과 등등 이름을 입력하고 생성하자. 관련 라이브러리 받으라 더럽게 오래 걸린다.

https://github.com/sugoigroup/kotlin_mpp_example/commit/9ce2f2fd791270c86eeae6265837a9b49eb473f5

3.shared 의 build.gradle.kts를 보면 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
kotlin {
    android()
    ios { //ios가 sourceSet에서는 iosMain으로 지정
        binaries {
            framework {
                baseName = "shared" // ios프로젝트를 xcode에서 열어보면 shared란 framework 이름으로 추가되어있다. 
            }
        }
    }
    sourceSets {

        val iosMain by getting
    }

}


3. Hello 공용모듈을 분석해보자

commonMain 아래에 있는것들이 말그대로 공용함수가 있는곳이다. 프로젝트 작성과 함께Greeting.kt, Platform.kt 가 있다.

kotlin 에서는

expect :  이 키워드를 붙인 클래스나 함수는 각 플랫폼에서 동일하게 사용될것 같은 (마치 인터페이스같은) 것이라는 의미이다.

actual : 앞서 expect로 외부에서 불러내면 , 각 플랫폼에따라서 상황에 맞는 동작을 해야되는데 actual 키워드를 클래스나 함수 앞에 붙여준다. 따라서 expect 가 붙어있는 것들은 각 플랫폼(iosMain, AndroidMain, jsMain등)에 aspect로 쌍을 이뤄서 써줘야한다.

그래서 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
--shared/commonMain/.../Greeting.kr 
//Greeting 클래스는 외부의 각플랫폼에서 불러낼수 있다. 단, 어떤 플랫폼에서 불러내든 동일한 처리와 결과같을 가지게 된다.
class Greeting {
    fun greeting(): String {
        return "Hello, ${Platform().platform}!" // Platform().platform 이라는 expect(실제의 구현체가 있을지 없을지 모르는 예상의) 키워드가 붙은 클래스를 불러냈다.
    }
}

--shared/commonMain/.../Platform.kr
// expect가 붙은 Platform 클래스는 platform(문자형변수)를 가지고있고, 외부에서 Greeing.greeting()을 불러실행할떄, Platform().platform 형식으로 값을 가져다가 출력한다. 이곳에는 단지 expect만 지정했기때문에 실제 구현체는 공용모듈안의 각 플랫폼에서 진행하자.
expect class Platform() {
    val platform: String
}

--shared/androidMain/Platform.kr
// exctual라인옆에 <E> 가 보인다. expect에 대응하는 안드로이드플랫폼용 actual을 구현하자. 
// actual이 조금 지저분하다. 여튼 안드로이드는 SDK_INT로 버젼을 확인하니 해당 코드를 넣어주었다
actual class Platform actual constructor() {
    actual val platform: String = "Android ${android.os.Build.VERSION.SDK_INT}"
}

--shared/iosMain/Platform.kr
// ios코드가 재밌다. UIDevice클래스(랩퍼겠지?)를 이용하여 버젼을 출력하는 코드를 넣었다..
actual class Platform actual constructor() {
    actual val platform: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion
}

이로써 공통 모듈은 준비가 되었다.

이제 각 플랫폼에서 공통모듈을 불러내서 Greeting함수만 실행하면 각 플랫폼의OS버젼이 출력된다.

--androidApp/.../MainActivity.kt
안드로이드의 gradle.build 에 공용모듈의 의존성을 추가(implementation(project(":shared"))한다음소스에서 클래스와 함수 불러내면 된다.
호출:Greeting().greeting();
결과:"Hello, Android 28!"

결국 shared모듈을 의존성에 추가하면, 공통 Greeting클래스라 expect된 Platform().platform을 호출하고 androidMain플랫폼에 actual하여 적어준대로 "Android ${android.os.Build.VERSION.SDK_INT}"를 출력하게 된다.



--iosApp/.../ContentView.swift
안드로이드와 비슷하게, ios프로젝트 내부에 공용모듈인  shared.framework을 추가되었고, swift언어로  클래스와 함수를 불러냈다.
호출:Greeting().greeting();
결과:"Hello, ios ....!"

마찬가지로, expect된 Platform().platform을 iosMain 에서 "UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion" 식으로 출력했다.

4. 그럼 나도 추가해보자. 일단 멀티플랫폼에서 사용할만한게...환전?! 환전예상가격을 조회하는 어플을 만든다 할때, 미국달러를 나라별 환전금액으로 변환해주는 로직을 안드로이드와 아이폰 양쪽에서 만들필요없이 공통로직에서 처리하면 좋을것 같다. 

https://github.com/sugoigroup/kotlin_mpp_example/commit/5c7956fa68dd2fb6dc93ad278d99804bb5eae352

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
--commonMain/.../ExchangeMoney.kt
외부에서 사용할 클래스와 함수를 expect 정의
expect class ExchangeMoney(baseDollor: Double) {
    fun toYen(): Double
    fun toWon(): Double
}

--commonMain/.../ExchangeMoneyCalcurator.kt
각 플랫폼에서 expect함수를 통해 actual 선언된 함수를 이용할때, 플랫폼에 상관없이 똑같이 처리할 로직을 넣음
class ExchangeMoneyCalcurator(val baseDollor: Double, val country: String) {
    fun calc(): Double {
        val rate: Double = when (country) {
            "YEN" -> 0.91
            "WON" -> 0.95
            else -> 1.0
        }
        return baseDollor * rate
    }

}

--androidMain/.../ExchangeMoney.kt
expect 함수들을 actual로 구현. 단 공통로직은 ExchangeMonetCalcurator를 호출하여 구현
actual class ExchangeMoney actual actual class ExchangeMoney actual constructor(val baseDollor: Double) {
    actual fun toYen(): Double {
        return ExchangeMoneyCalcurator(baseDollor, "YEN").calc()
    }
    actual fun toWon(): Double {
        return ExchangeMoneyCalcurator(baseDollor, "WON").calc()
    }
}


--iosMain/.../ExchangeMoney.kt
actual class ExchangeMoney actual constructor(val baseDollor: Double) {
    actual fun toYen(): Double {
       return ExchangeMoneyCalcurator(baseDollor, "YEN").calc()
    }
    actual fun toWon(): Double {
        return ExchangeMoneyCalcurator(baseDollor, "WON").calc()
    }
}

--androidApp/.../MainActivity.kt
사용하자

        tv.text = ("3 달라는 한국돈으로 " + ExchangeMoney(3.0).toWon())

--iodApp/.../ContentView.swift
사용하자

       
        Text("3 달라는 엔화로" + String(ExchangeMoney(baseDollor: 3.0).toYen()))


이밖에 멀티플랫폼에서 사용할만한 라이브러리가 있다.


https://github.com/AAkira/Kotlin-Multiplatform-Libraries

GraghQL, SQLDelight, Realm, Koin, LiveData, coroutine, uuid, firebase, moko-widget 등 디비와 통신, 로직에 사용할 만한 라이브러리 들이 있다