Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
생산성을 높이는 Android SDK 배포 전략
Search
Yeojun Yoon
May 30, 2025
Technology
32
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
생산성을 높이는 Android SDK 배포 전략
주최: NAVER
행사: 2025 Engineering Day
날짜: 2025-05-30
제목: 생산성을 높이는 Android SDK 배포 전략
Yeojun Yoon
May 30, 2025
More Decks by Yeojun Yoon
See All by Yeojun Yoon
AI 시대에도 통하는 개발자 취업 전략
yjyoon
0
140
KMP + Supabase: 1인 개발의 새로운 패러다임
yjyoon
0
130
사이드 프로젝트를 20번 실패한 주니어의 오답노트 훔쳐보기(feat. KMP)
yjyoon
0
840
Other Decks in Technology
See All in Technology
JAWS-UGグッズ職人仕事の流儀
kentapapa
0
120
Running Kotlin + Quarkus with Lambda
nealle
1
4k
Code for Security プロジェクト紹介 2026年10月
yu23ki14
0
110
実践!Cloud Run ハンズオン!! / Cloud Run handson
y0hgi
2
300
AIカンパニーへの転換を支えた、エンジニアの仕事の再定義
kworkdev
PRO
2
1.3k
パッチ更新でterraform initが落ちた日
grimoh
1
140
二歩目のフロントエンド・ウェブアクセシビリティ
camiha
2
660
⾮構造化データを価値に変える AI エージェント基盤とその組織
ivry_presentationmaterials
0
200
Temporal 最高!でも改めて「日付」について調べたら人類の負債すぎる件
riyaamemiya
0
180
M5Stackで作る BLEマウス GPSログの世界
tomokusaba
PRO
0
440
Persisting Massive Data with Rails ~Designing for 60 billion rows, and fighting the bottlenecks~ Railsで挑む大量データ永続化 〜600億件を永続化するための設計とボトルネックとの戦い〜
occhi
0
740
初海外で注意すべきこと12選!!!安全快適なre:invent生活にするために
yuuuuuuu168
1
180
Featured
See All Featured
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.2k
Facilitating Awesome Meetings
lara
57
7.2k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
360
Building the Perfect Custom Keyboard
takai
2
910
Google's AI Overviews - The New Search
badams
0
1.6k
Practical Orchestrator
shlominoach
192
12k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
4
1.2k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
270
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
2
6.3k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
2
2k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.2k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
Transcript
ᤓᣦᥧὺwৈᾪ 2(63-(wwᑦⰢw› Ḣℶ (ww):
328)287 x ᑦⰢᆲwἺⶒw'32:)28-32%0w'311-8wԲw-89&w '8-327 x 6%(0)w 32:)28-32w09+-2wὺwᾪởⶒwᑦⰢw8%7/wԶᇢ x ᑦⰢwᾪwԫὖwⴺ႒wῆఏ⺊
ᑦⰢᆲwἺⶒ '32:)28-32%0w'311-8wԲ -89&w '8-327 '311-8wᖶ⥦wᬒῇw₶wஊw࣎ὶwᑦⰢᆲwἺⶒwᚂഒ᷻
32:)28-32%0w 311-87 *)%8 ',36) 6)*%'836 *-< )1%28-'w )67-32-2+ ᑦⰢ
)67-32 )0)%7)w38)
)0)%7)w38) xx )%896)7 • 7944368w 2(63-(ww8%6+)8 xx 9+w-<)7 • '36)zww*36w0%6+)w-2498
xx *-<'36)zww*36w0%6+)w-2498 xx xx *)%8zw7944368w 2(63-(ww8%6+)8 )1%28-'w )67-32-2+
6)0)%7)§40)%7)§%'8-32 )2)6%8)w6)0)%7)w7w&%7)(w32w8,)w'32:)28-32%0w'311-87w74)'x '32:)28-32%0w'311-87ww→ :)67-32ww→ ',%2+)w03+ww→
жᾪഒw፮ᥒw᷻ᾪ⫮wῆఏ⺊ -89&w '8-327wᆲwᾪởⶒwᑦⰢwᾪwжᾪഒw፮ᥒw᷻ᾪ⫮wῆఏ⺊ жᾪഒ ‶Ίᧂ ᣢ࣪ở жᾪഒ ‶Ίᧂ Ắᖶở '311-8
6)0)%7) 238) 6)0)%7)§40)%7) -89& '8-327
жᾪഒw፮ᥒw᷻ᾪ⫮wῆఏ⺊ -89&w '8-327wᆲwᾪởⶒwᑦⰢwᾪwжᾪഒw፮ᥒw᷻ᾪ⫮wῆఏ⺊ 86-++)6 -89&w '8-327 6)437-836=¨(-74%8', x+-8,9&;36/*03;692¨-*¨*%-096)x=10 w w◒
):)28w8=4)wԲ ᾲ⚎ⶎw;36/*03;wᩎ
on: push: branches: - main name: Release SDK jobs: release:
runs-on: ubuntu-latest steps: - name: Release please action uses: googleapis/release-please-action@v4 id: release with: token: ${{ secrets.RELEASE_PLEASE_TOKEN }} - name: Update guide repository if: steps.release.outputs.releases_created == 'true' env: json: ${{ toJSON(steps.release.outputs) }} run: | curl -X POST \ -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer <GITHUB-TOKEN>" \ https://api.github.com/repos/android-sdk/guide/dispatches \ -d '{"event_type":"release-pr","client_payload":{"release_outputs":${{json}}}' )437-836= 6)0)%7)§40)%7)wӦԲwᤓᥧwḢᖶ 6)0)%7)§40)%7)wӦԲw›⓪wᾪ⥦ (-74%8',w w›᧗wᾪ⥦
on: repository_dispatch: types: [release-pr] name: Create new release PR jobs:
new-release-pr: runs-on: ubuntu-latest steps: - name: Update version run: | new_version=${{ github.event.client_payload.release_outputs.version }} version_path="config.toml" sed -i "s@version = \".*\"@version = \"${new_version}\"@g" "${version_path}" - name: Update release note run: | new_release_note=${{ github.event.client_payload.release_outputs.body }} release_note_path="docs/release_note.md" sed -i "1i ${new_release_note}"$'\n\n' "${release_note_path}" - name: Commit new release run: # . . . - name: Create new release PR run: # . . . 9-() )437-836= ›ଢᑑὶw6)0)%7)wᒺ› ›ଢᑑὶw',%2+)w03+wᔮ፮ :)6-732 ፮ῆḪw⚎⺎ 6)0)%7)w238)w࣪ởwὍw℺wᣳΆ - version = 8.3.0 + version = 8.4.0 '32*-+x8310 + ## 8.4.0 + + ### Features + + - support A + - support B + ## 8.3.0 6)0)%7)¨238)x1(
ᤎⵂᶧw▒ᬖ⺊wᑅw⦂⫮wῆఏ⺊ -89&w '8-327wᆲwᾪởⶒwᑦⰢwᾪwᤎⵂᶧw▒ᬖ⺊wᑅw⦂⫮wῆఏ⺊ '311-8 6)0)%7) 238) 6)0)%7)§40)%7) -89&
'8-327 ᤎⵂᶧ ‶Ίᧂ ᣢ࣪ở ᤎⵂᶧ ‶Ίᧂ Ắᖶở
on: push: branches: - main name: Release SDK jobs: release:
runs-on: ubuntu-latest steps: - name: Release please action uses: googleapis/release-please-action@v4 id: release with: token: ${{ secrets.RELEASE_PLEASE_TOKEN }} - name: Update sample app repository if: steps.release.outputs.releases_created == 'true' env: json: ${{ toJSON(steps.release.outputs) }} run: | curl -X POST \ -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer <GITHUB-TOKEN>" \ https://api.github.com/repos/android-sdk/sample/dispatches \ -d '{"event_type":"release-pr","client_payload":{"release_outputs":${{json}}}' )437-836=
on: repository_dispatch: types: [release-pr] name: Create new release PR jobs:
new-release-pr: runs-on: ubuntu-latest steps: - name: Update version catalog run: | new_version=${{ github.event.client_payload.release_outputs.version }} name="my-sdk" path="gradle/libs.versions.toml" sed -i "" "s@^${name} = \".*\"@${name} = \\"${new_version}\\"@" "${path}" - name: Build Test run: ./gradlew assembleDebug - name: Android Test run: ./gradlew connectedDebugAndroidTest - name: Commit new version catalog run: # . . . - name: Create new release PR run: # . . . %140)w 44 )437-836= )67-32w %8%03+w⭂ᾲwᩎ⁋ 9-0(wᑅw 2(63-(w)78wᩎ [versions] - my-sdk = 8.3.0 + my-sdk = 8.4.0 0-&7x:)67-327x8310
'311-8wԲw-89&w '8-327wᆲwᾪởⶒwᑦⰢwῆఏ⺊wⴺ႒ '311-8wὲ႒ᖶ⥦wᒺ›ywᇪᇢ↾wম⫮ywжᾪഒywᤎⵂᶧywخᇢԖwᚂഒw⦂⫮ڂ⇶ жᾪഒ ‶Ίᧂ ᣢ࣪ở жᾪഒ ‶Ίᧂ Ắᖶở '311-8
6)0)%7) 238) 6)0)%7)§40)%7) -89& '8-327 ᤎⵂᶧ ‶Ίᧂ ᣢ࣪ở ᤎⵂᶧ ‶Ίᧂ Ắᖶở
'311-8wᬒwℲᾎⶎԖwιw⁆ *)%8zw7944368w%8-:)w (w-28)+6%8-32 *)%8zw-140)1)28w8-80) -); *)%8zw-140)1)28w1)(-% -); 6)*%'836zw6)2%1)w731)w:%6-%&0)7 *-<zw8-80) -);
,%7w731)w&9+7 xwxwx ⶒwж⇶w*)%896)wḆwଶⶪᥒwⶎ࣎ᾎw'311-8wሂ
'311-8wᬒwℲᾎⶎԖwιw⁆ ᾪᐮwἆӟw‶ΊᧂḆwṢྲкw'311-8wᾎwᩎ⁋ὶw*-<94wὲ႒ *)%8zw7944368w2);w*)%896) ():)034 *-<zw&9+w32w2);w*)%896) *)%8zw7944368w2);w*)%896) ():)034 *-<94|w*)%8zw7944368w2);w*)%896)
'311-8wᬒwℲᾎⶎԖwιw⁆ Ủᇢжwᵺଂwὖ‶ᆲwἺⶒw'311-8w1)77%+) *-<zw6)730:)w-779)w *-<'36)zw1)136=w0)%/w32wMyClass
'311-8wᬒwℲᾎⶎԖwιw⁆ )6+)w4900w6)59)78ww*631w2%:)6)<%140) )6+)w4900w6)59)78 ↓ )&%7)w%2(w1)6+) ᖾỊⶒw1)6+)w'311-8wଶᬖw6)&%7)
6%(0)w 32:)28-32w09+-2wὺwᾪởⶒ ᑦⰢw8%7/wԶᇢ ḢဢwዞḆᥒᾎwᑦⰢw8%7/wṶwṫᦎwᥚ⁋ὺwԫ⧫ԖwᾲԶӂ
2(63-(wwᑦⰢw‶Ίᧂ %:)2w )286%0w‶ΊᧂṶw*63+ 68-*%'836= 49&0-7, Ắᖶởw ᣢ࣪ởw
ዞwᑅw*0%:36wᓺ႒wᾪⶒwᑦⰢwᥚ⁋ 63(9'8w0%:36wḆw൦ᆮwᚂഒw֢ᖺwᑅwዞḆw൦ᆮwᑦⰢwԲ⁋wᾪ -28)62%0 )<8)62%0 63(9'8w0%:367 ‶Ίᧂ ዞ 396')7%6 63+9%6( -')27)
wዞ wዞ wዞ .%:%(3'wⰢ wዞ wዞ wዞ .%:%(3'wⰢ
ᔫῗⶎԖwⅇᔫw+6%(0) 8%7/wԶᇢ 6%(0)w 32:)28-32w09+-2wὺw⺒ởⶎḢwᑦⰢw8%7/wᆲwⶒwԩḆᥒwԶᇢ wዞwᑦⰢw8%7/ wዞwᑦⰢw8%7/ wዞwᑦⰢw8%7/ wዞwᑦⰢw8%7/ wዞ wዞ
wዞ wዞ
ᔫῗⶎԖwⅇᔫw+6%(0) 8%7/wԶᇢ 6%(0)w 32:)28-32w09+-2wὺw⺒ởⶎḢwᑦⰢw8%7/wᆲwⶒwԩḆᥒwԶᇢ wዞ wዞ wዞ wዞ 32:)28-32 09+-2
ᑦⰢw6%(0)w 32:)28-32w09+-2wῇᥧⶎ٦ 6%(0)w 32:)28-32w09+-2wὺw⺒ởⶎḢwᑦⰢw8%7/wᆲwⶒwԩḆᥒwԶᇢ &9-0(§03+-''32:)28-32 plugins { `kotlin-dsl` } group
= "com.example.buildlogic" java { sourceCompatibility = VERSION_17 targetCompatibility = VERSION_17 } kotlin { compilerOptions { jvmTarget = JvmTarget.JVM_17 } } &9-0(§03+-''32:)28-32&9-0(x+6%(0)x/87 pluginManagement { repositories { mavenCenteral() google() gradlePluginPortal() } includeBuild("build-logic") } 7)88-2+7x+6%(0)x/87
ᑦⰢw6%(0)w 32:)28-32w09+-2wῇᥧⶎ٦ 6%(0)w 32:)28-32w09+-2wὺw⺒ởⶎḢwᑦⰢw8%7/wᆲwⶒwԩḆᥒwԶᇢ /* . . . */ dependencies
{ compileOnly("com.vanniktech:gradle-maven-publish-plugin") /* . . . */ } &9-0(§03+-''32:)28-32&9-0(x+6%(0)x/87 ,8847z+-8,9&x'31:%22-/8)',+6%(0)§1%:)2§49&0-7,§409+-2 class PublishConventionPlugin : Plugin<Project> { override fun apply(target: Project) { with(target) { apply<MavenPublishBasePlugin>() configure<MavenPublishBaseExtension> { group = project.groupId version = project.versionName publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL) signAllPublications() pomFromGradleProperties() } } } } &9-0(§03+-''32:)28-32 9&0-7, 32:)28-3209+-2x/8
ᑦⰢw6%(0)w 32:)28-32w09+-2wῇᥧⶎ٦ 6%(0)w 32:)28-32w09+-2wὺw⺒ởⶎḢwᑦⰢw8%7/wᆲwⶒwԩḆᥒwԶᇢ class PublishConventionPlugin : Plugin<Project> { override
fun apply(target: Project) { with(target) { apply<MavenPublishBasePlugin>() configure<MavenPublishBaseExtension> { group = project.groupId version = project.versionName publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL) publishToJFrogArtifactory() signAllPublications() pomFromGradleProperties() } } } } &9-0(§03+-''32:)28-32 9&0-7, 32:)28-3209+-2x/8 private fun Project.publishToJFrogArtifactory() { extensions.getByType<PublishingExtension>() .repositories.maven { name = "jFrogArtifactory" url = uri("https://example.com/artifactory") with(project) { if (hasProperty("jFrogUsername") && hasProperty("jFrogPassword") ) { credentials { username = property("jFrogUsername").toString() password = property("jFrogPassword").toString() } } } } } &9-0(§03+-''32:)28-32 9&0-7, 32:)28-3209+-2x/8
ᑦⰢw6%(0)w 32:)28-32w09+-2wῇᥧⶎ٦ 6%(0)w 32:)28-32w09+-2wὺw⺒ởⶎḢwᑦⰢw8%7/wᆲwⶒwԩḆᥒwԶᇢ open class PublishConventionExtension @Inject constructor( objectFactory:
ObjectFactory ) { @Input val publishType: Property<PublishType> = objectFactory .property<PublishType>() .convention(PublishType.ALL) // default value @Input val publishJavadoc: Property<Boolean> = objectFactory .property<Boolean>() .convention(false) // default value } enum class PublishType { ALL, INTERNAL_ONLY, EXTERNAL_ONLY } &9-0(§03+-''32:)28-32 9&0-7, 32:)28-32<8)27-32x/8 class PublishConventionPlugin : Plugin<Project> { override fun apply(target: Project) { with(target) { apply<MavenPublishBasePlugin>() configure<MavenPublishBaseExtension> { /* . . . */ val extension = extensions .create<PublishConventionExtension>( name = "publishOptions" ) configurePublishing(extension) } } } } &9-0(§03+-''32:)28-32 9&0-7, 32:)28-3209+-2x/8 publishOptions { publishType = INTERNAL_ONLY publishJavadoc = true }
ᑦⰢw6%(0)w 32:)28-32w09+-2wῇᥧⶎ٦ 6%(0)w 32:)28-32w09+-2wὺw⺒ởⶎḢwᑦⰢw8%7/wᆲwⶒwԩḆᥒwԶᇢ internal fun Project.configurePublishing(extension: PublishConventionExtension) { afterEvaluate
{ if (extension.publishJavadoc.get()) { apply<DokkaConventionPlugin>() } extensions.configure<PublishingExtension> { publications { val publishType = extension.publishType.get() if (publishType == PublishType.ALL || publishType == PublishType.INTERNAL_ONLY) { createMavenPublication(project = project, flavor = "internal") } if (publishType == PublishType.ALL || publishType == PublishType.EXTERNAL_ONLY) { createMavenPublication(project = project, flavor = "external") } } tasks.withType<PublishToMavenRepository>().matching { task -> val (repositoryName, publicationName) = with(task) { repository.name to publication.name } repositoryName == "jFrogArtifactory" && publicationName.startWith("external") || repositoryName == "mavenCentral" && publicationName.startWith("internal") }.configureEach { enabled = false } } } &9-0(§03+-''32:)28-32 9&0-7, 32*-+x/8 49&0-7,=4) ᓺwᑦⰢwṫᦎwᖺ٦ ዞwᓺw.%:%(3' ᑦⰢwḢᖶwᖺ٦ *0%:36wᓺwᑦⰢw‶Ίᧂwᖺ٦
ᑦⰢw6%(0)w 32:)28-32w09+-2wῇᥧⶎ٦ 6%(0)w 32:)28-32w09+-2wὺw⺒ởⶎḢwᑦⰢw8%7/wᆲwⶒwԩḆᥒwԶᇢ private fun PublisherContainer.createMavenPublication(project: Project, flavor: String)
{ create<MavenPublication>(flavor) { if (flavor == "internal") { project.extensions.findByType<LibraryExtension>()?.let { android -> artifact( project.tasks.create<Jar>("androidInternalSourcesJar") { archiveClassifier.set("sources") archiveFileName.set("internal-sources.jar") from( android.sourcesSets.getByName("main").java.srcDirs android.sourcesSets.getByName("internal").java.srcDirs ) } ) } } if (flavor == "external") { pom.license { /* . . . */ } } artifactId = project.artifactId + flavor /* . . . */ } &9-0(§03+-''32:)28-32 9&0-7, 32*-+x/8 )<8)62%0wởw431wᥚ⁋ -28)62%0wởw7396')7%6 ᑦⰢ %68-*%'8( Ḇ *0%:36wᣳΆ
ᑦⰢw6%(0)w 32:)28-32w09+-2wῇᥧⶎ٦ 6%(0)w 32:)28-32w09+-2wὺw⺒ởⶎḢwᑦⰢw8%7/wᆲwⶒwԩḆᥒwԶᇢ plugins { `kotlin-dsl` } /* .
. . */ gradlePlugin { plugins { register("examplePublish") { id = "example.convention.publish" implementationClass = "PublishConventionPlugin" } } } &9-0(§03+-''32:)28-32&9-0(x+6%(0)x/87 plugins { id("example.convention.publish") /* . . . */ } publishOptions { publishType = PublishType.ALL publishJavadoc = false } /* . . . */ *)%896),31)&9-0(x+6%(0)x/87 plugins { id("example.convention.publish") /* . . . */ } publishOptions { publishType = PublishType.INTERNAL_ONLY publishJavadoc = true } /* . . . */ *)%896)&-00-2+&9-0(x+6%(0)x/87
ᑦⰢwᾪwԫὖwⴺ႒wῆఏ⺊ ᑦⰢжw࣒wwᷪේw⁋ᔪᆲwᷪൊḆwᷪӂwԫὖⶖڂ}
ᑦⰢwᾪwԫὖwⴺ႒wῆఏ⺊ ᑦⰢwᾪwᤎⵂᶧwᚂഒwᑅwᣢ࣪wᚂഒw‶Ίᧂw᷻႒ഒ ᣢ࣪wᚂഒw‶Ίᧂw᷻႒ഒ (3//% ፮ᥒwᚂഒ ሚ⓪w0%'/w⑺ॆwᶂᇲ 690)6wᖺᥓwᇢⰢ⫮ '311-8 6)0)%7) 238)
6)0)%7)§40)%7) -89& '8-327 ᤎⵂᶧ ‶Ίᧂ ᣢ࣪ở ᤎⵂᶧ ‶Ίᧂ Ắᖶở ᣢ࣪wᚂഒ ‶Ίᧂ
ᑦⰢwᾪwԫὖwⴺ႒wῆఏ⺊ ᑦⰢwᾪw(3//%wᆲwᾪởⶒw.%:%(3' ᚂഒwᑅ +,§4%+)7wᑦⰢ ᣢ࣪wᚂഒw‶Ίᧂw᷻႒ഒ (3//% ፮ᥒwᚂഒ ሚ⓪w0%'/w⑺ॆwᶂᇲ 690)6wᖺᥓwᇢⰢ⫮
ᑦⰢwᾪwԫὖwⴺ႒wῆఏ⺊ ᑦⰢwᾪ Զၞwሚ⓪wᑅw w࿏w⑺ॆwᶂᇲ ᣢ࣪wᚂഒw‶Ίᧂw᷻႒ഒ (3//%w፮ᥒ ᚂഒ ሚ⓪w0%'/w⑺ॆwᶂᇲ 690)6wᖺᥓwᇢⰢ⫮ https://github.com/naver/nam-sdk-android/releases.tag/v8.4.1
https://naver.github.io/nam-sdk-android https://naver.github.io/nam-sdk-guide/android https://사내빌드저장소.com/app/android/gfp-sdk/real/latest https://사내빌드저장소.com/app/android/gfp-sdk/real w⑺ॆᾲwᬒwᤎⵂᶧwᇷ⢢w›ଢ
ᑦⰢwᾪwԫὖwⴺ႒wῆఏ⺊ ᑦⰢwᾪw690)6wᆲwᾪởⶒwᤎⵂᶧwởwᖺᥓwᇢⰢ⫮w◊◒ ᣢ࣪wᚂഒw‶Ίᧂw᷻႒ഒ (3//%w፮ᥒ ᚂഒ ሚ⓪w0%'/w⑺ॆwᶂᇲ 690)6wᖺᥓwᇢⰢ⫮ ,8847z+-8,9&x'317438-*=690)6
2(w3*w39'91)287