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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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
Active Record Connection Adaptersにおける長年の課題に再び取り組む
yahonda
0
200
V8のArray.prototype.flatを最大約20倍速くするまでと、巨大OSSへの大規模コミットの道のり
riyaamemiya
0
300
夫婦で子育てするための育児標準化
codmoninc
PRO
0
450
OptunaHub: ブラックボックス最適化のためのプラットフォーム
pfn
PRO
0
140
hackers_champloo_2026_tidb
makocchi
0
170
LambdaWebFunctionsを試してみた / exploring-lambda-web-functions
koukihosaka
1
360
フィンテック養成勉強会#68
finengine
0
140
Running Kotlin + Quarkus with Lambda
nealle
1
4k
触りたくないデータに、どう触るか AI時代のRBACアクセスガバナンス
ivry_presentationmaterials
0
280
AIカンパニーへの転換を支えた、エンジニアの仕事の再定義
kworkdev
PRO
2
1.3k
実践!Cloud Run ハンズオン!! / Cloud Run handson
y0hgi
2
300
古い指輪から広がった JAVA コミュニティ とのつながり
yamad
0
130
Featured
See All Featured
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
270
Git: the NoSQL Database
bkeepers
PRO
433
67k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Context Engineering - Making Every Token Count
addyosmani
9
1.2k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.4k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
4
4.4k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.3k
Tell your own story through comics
letsgokoyo
1
1.1k
SEO for Brand Visibility & Recognition
aleyda
0
4.8k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
540
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
1
570
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
590
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