오늘은 KMM Library를 Sonatype Jira Maven Central로 Android Library를 배포하는 법을 알아보겠습니다.
크게 세 가지의 단계로 알아보겠습니다. 각 단계가 이미 적용되어 있으신 분들은 다음 단계를 보시면 됩니다.
먼저, 링크를 통해 Sonatype Jira 계정을 생성해줍니다.
링크에서 이슈를 생성해줍니다.

Summary : 대충 아무 제목 적어주시면 됩니다.
Group Id : 그림1의 가이드와 같이 작성해주시면 됩니다.
Project URL : Library의 주소입니다. 임의의 레포지토리를 넣어주도록 하겠습니다.
SCM URL : Git repository의 경우 레포지토리 주소 끝에 .git 붙여주시면 됩니다.
위의 화면에서 생성된 이슈 화면입니다. 다음 화면에서 티켓 번호를 확인할 수 있습니다.
필자의 번호는 OSSRH-83686인 것을 확인할 수 있습니다.

바로 깃허브로 가서 레포를 생성해줍니다. 레포 이름에 티켓 번호만 적어주면 됩니다.

조금 기다리다보면 아래와 같이 레포지토리가 준비됐다고 코멘트가 달립니다. 이제 배포 스크립트만 작성하면 됩니다.

artifact에 signing을 하기 위해 gpg key를 생성해줍니다.
맥 기준으로 gpg 설치는 brew install gnupg를 터미널에 입력하시면 됩니다.
설치가 완료되면 gpg --gen-key를 입력해 키를 생성해줍니다.
간단하게 이름, 이메일을 입력하고 Okay를 입력하고 passphrase(비밀번호)를 입력해줍니다.
여기서 저희는 keyId, secret key ring file, password 이 세 가지 정보를 사용할 겁니다.
keyId는 public key의 마지막 8자리를 사용합니다.
password는 passpharse를 사용합니다.
secret key ring file은 다음과 같이 생성해줍니다.
$ gpg --export-secret-keys -o secret.gpg
마지막으로 공개키를 서버에 전송해줍니다.
gpg --keyserver keyserver.ubuntu.com --send-keys keyId
먼저 key id와 계정 정보등을 사용하기 위해 local.properties를 작성합니다.
signing.keyId= --> gpg key id <--
signing.password= --> gpg passphrase <--
signing.secretKeyRingFile= --> gpg secret ket ring file path <--
ossrhUsername= --> sonatype jira account user name <--
ossrhPassword= --> sonatype jira account password <--
android publish를 도와줄 gradle plugin을 만들어 줍니다.
루트 프로젝트에 convention-plugins 모듈을 만들어 줍니다.

convention-plugins 모듈의 그래이들을 작업해줍니다.
// convention/build.gradle.kts
plugins {
`kotlin-dsl`
}
repositories {
gradlePluginPortal()
}
다시 루트 프로젝트로가서 settings.gradle.kts에서
includeBuild("convention-plugins)
를 추가해줍니다.
android.publication.gradle.kts를 source 폴더 안에 넣어주고 publication 스크립트를 작성해줍니다.
plugins {
`maven-publish`
signing
}
ext["signing.keyId"] = null
ext["signing.password"] = null
ext["signing.secretKeyRingFile"] = null
ext["ossrhUsername"] = null
ext["ossrhPassword"] = null
val publishGroupId: String by project
val publishArtifactId: String by project
val pomName: String by project
val pomDescription: String by project
val siteUrl: String by project
val gitUrl: String by project
val licenseName: String by project
val licenseUrl: String by project
val developerId: String by project
val developerName: String by project
val developerEmail: String by project
val properties = rootProject.file("local.properties").reader().use {
Properties().apply {
load(it)
}
}.onEach { (name, value) ->
ext[name.toString()] = value
}
afterEvaluate {
publishing {
repositories {
maven {
name = "sonatype"
setUrl("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials {
username = properties["ossrhUsername"].toString()
password = properties["ossrhPassword"].toString()
}
}
}
publications {
register<MavenPublication>("release") {
groupId = publishGroupId
artifactId = publishArtifactId
version = "1.0.0"
from(components.getByName("release"))
pom {
name.set(pomName)
description.set(pomDescription)
url.set(siteUrl)
licenses {
license {
name.set(licenseName)
url.set(licenseUrl)
}
}
developers {
developer {
id.set(developerId)
name.set(developerName)
email.set(developerEmail)
}
}
scm {
url.set(gitUrl)
}
}
}
}
}
}
signing {
sign(publishing.publications)
}
저는 gradle.properties에 다음과 publishGroupId, publishArtifactId, ..를 정의해줬습니다.
publishGroupId=io.github.taehoonleee
publishArtifactId=naver-login-kotlin-sdk
pomName=Sample Naver Login Library
pomDescription=Sample Naver Login Library target (iOS + Android)
siteUrl=https://github.com/TaehoonLeee/naver-login-kotliin-sdk
gitUrl=https://github.com/TaehoonLeee/naver-login-kotliin-sdk.git
licenseName=Apache License 2.0
licenseUrl=http://www.apache.org/licenses/LICENSE-2.0
developerId=leetaehoon
developerName=Taehoon Lee
developerEmail=lyc9290@gmail.com
그런 다음 kmm library의 gradle에서 작업하겠습니다.
plugins {
id("android.publication")
}
먼저, 우리가 작성한 플러그인을 넣어줍니다.
android {
compileSdk = 32
sourceSets["main'].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 21
targetSDk = 32
}
publishing {
signleVariant("release") {
withSourceJar()
withJavadocJar()
}
}
}
그런 다음 안드로이드 타겟 라이브러리만 만들 것이기 때문에 android configuration에서 진행하겠습니다.
publishing {
singleVariant("release") {
withSourceJar()
withJavadocJar()
}
}
이 부분만 추가해주시면 됩니다.
경우에 따라 withJavadocJar()이나 withSourceJar()를 생략해주셔도 됩니다.
여러 varinats archive를 배포하시고 싶으신 분은
multipleVariants {
allVariants() 또는 includeBuildTypeValues("debug", "release")
}
이렇게 사용하시면 됩니다.
이렇게 스크립트를 작성하신 다음
./gradlew publishReleasePublicationToSonatypeRepository
를 실행해주시면 배포과정이 진행됩니다.
gradle build가 성공적으로 끝나면 링크에 들어가셔서 status가 open인 repository를 발견하실 수 있습니다.

해당 레포지토리를 클릭해서 하단 Content Tab에서 누락된 파일이 있는지 체크합니다. 그런 다음 Close 버튼을 누릅니다.
Close 버튼을 누르면 Repository를 검사하는데, Activity 탭을 통해 진행 상황을 볼 수 있습니다.


위의 그림처럼 Repository closed 스텝까지 도달하면 Release 버튼을 눌러 최종적으로 배포를 시작합니다. 이 release 과정은 시간이 걸릴 수 있습니다(몇십분 ~ 2시간).
만약, 첫 배포시면 release가 완료되면 아래와 같이 이슈에 코멘트가 달립니다.

레포지토리가 릴리즈되면 기존에 gradle에서 dependency 넣는 것 처럼 넣으시면 됩니다.
저의 경우에 kmm 프로젝트가 아닌 안드로이드 네이티브 플랫폼에서 사용할 일이 있어서 안드로이드 종속적인 라이브러리로 만들어봤습니다.
다음에는 안드로이드와 iOS에서 사용할 수 있는 라이브러리로 만들어보는 포스팅을 해보겠습니다.
https://developer.android.com/studio/publish-library/upload-library#create-pub
https://stackoverflow.com/a/63502756
https://dev.to/kotlin/how-to-build-and-publish-a-kotlin-multiplatform-library-going-public-4a8k
https://velog.io/@james-chun-dev/maven-배포-jcenter-에서-maven-으로-마이그레이션#gpg-키-인증
https://getstream.io/blog/publishing-libraries-to-mavencentral-2021/