FEAT#1 크루위키 KMP 프로젝트 초기 세팅 및 자산 이관#1
Conversation
There was a problem hiding this comment.
Code Review
This pull request initializes a Kotlin Multiplatform project targeting Android and iOS, setting up the project structure, build configurations, and a basic shared UI using Compose Multiplatform. The code review feedback highlights several critical improvements: adding the missing Kotlin Android plugin to the Android app module, caching font and typography allocations in 'CrewWikiTheme' using 'remember' to prevent recomposition performance issues, downgrading the Android compile and target SDKs from the unstable version 36 to the stable version 35, and upgrading the JVM target and Java compatibility settings from Java 11 to Java 17 across modules.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| plugins { | ||
| alias(libs.plugins.androidApplication) | ||
| alias(libs.plugins.composeMultiplatform) | ||
| alias(libs.plugins.composeCompiler) | ||
| } |
There was a problem hiding this comment.
이유:
현재 androidApp 모듈의 plugins 블록에 Kotlin Android 플러그인(org.jetbrains.kotlin.android)이 누락되어 있습니다. 이로 인해 MainActivity.kt와 같은 Kotlin 소스 코드가 정상적으로 컴파일되지 않거나, kotlin { ... } 설정 블록을 인식하지 못해 빌드 에러가 발생할 수 있습니다.
해결 방안:
libs.versions.toml에 kotlinAndroid 플러그인을 정의하고, androidApp/build.gradle.kts 및 루트 build.gradle.kts에 추가해 주세요.
plugins {
alias(libs.plugins.androidApplication)
id("org.jetbrains.kotlin.android")
alias(libs.plugins.composeMultiplatform)
alias(libs.plugins.composeCompiler)
}| import androidx.compose.material3.MaterialTheme | ||
| import androidx.compose.material3.Typography | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.ui.text.TextStyle | ||
| import androidx.compose.ui.text.font.FontFamily | ||
| import androidx.compose.ui.text.font.FontWeight | ||
| import org.jetbrains.compose.resources.Font | ||
|
|
||
| import crewwiki.shared.generated.resources.Res | ||
| import crewwiki.shared.generated.resources.bm_hanna_pro | ||
| import crewwiki.shared.generated.resources.pretendard_bold | ||
| import crewwiki.shared.generated.resources.pretendard_medium | ||
| import crewwiki.shared.generated.resources.pretendard_regular | ||
| import crewwiki.shared.generated.resources.pretendard_semibold | ||
|
|
||
| @Composable | ||
| fun CrewWikiTheme(content: @Composable () -> Unit) { | ||
| val pretendard = FontFamily( | ||
| Font(Res.font.pretendard_regular, FontWeight.Normal), | ||
| Font(Res.font.pretendard_medium, FontWeight.Medium), | ||
| Font(Res.font.pretendard_semibold, FontWeight.SemiBold), | ||
| Font(Res.font.pretendard_bold, FontWeight.Bold), | ||
| ) | ||
| val bmHanna = FontFamily( | ||
| Font(Res.font.bm_hanna_pro, FontWeight.Normal), | ||
| ) | ||
|
|
||
| MaterialTheme( | ||
| typography = crewWikiTypography( | ||
| pretendard = pretendard, | ||
| bmHanna = bmHanna, | ||
| ), | ||
| content = content, | ||
| ) | ||
| } |
There was a problem hiding this comment.
이유:
Font 함수는 Compose Multiplatform에서 @Composable 함수입니다. 현재 구현에서는 CrewWikiTheme이 재구성(Recomposition)될 때마다 FontFamily와 Typography 인스턴스가 매번 새롭게 생성됩니다.
이로 인해 테마를 사용하는 하위 컴포넌트들이 불필요하게 재구성되거나 레이아웃 패스를 다시 거치게 되어 성능 저하를 유발할 수 있습니다.
해결 방안:
Font 호출을 통해 생성된 Font 객체들을 remember 블록의 키로 전달하여 FontFamily와 Typography를 캐싱(remember)하도록 개선합니다. 이렇게 하면 최초 구성 시에만 인스턴스가 생성되고 재구성 시에는 기존 인스턴스를 재사용하므로 성능이 최적화됩니다.
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Typography
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import org.jetbrains.compose.resources.Font
import crewwiki.shared.generated.resources.Res
import crewwiki.shared.generated.resources.bm_hanna_pro
import crewwiki.shared.generated.resources.pretendard_bold
import crewwiki.shared.generated.resources.pretendard_medium
import crewwiki.shared.generated.resources.pretendard_regular
import crewwiki.shared.generated.resources.pretendard_semibold
@Composable
fun CrewWikiTheme(content: @Composable () -> Unit) {
val pretendardRegular = Font(Res.font.pretendard_regular, FontWeight.Normal)
val pretendardMedium = Font(Res.font.pretendard_medium, FontWeight.Medium)
val pretendardSemibold = Font(Res.font.pretendard_semibold, FontWeight.SemiBold)
val pretendardBold = Font(Res.font.pretendard_bold, FontWeight.Bold)
val pretendard = remember(pretendardRegular, pretendardMedium, pretendardSemibold, pretendardBold) {
FontFamily(pretendardRegular, pretendardMedium, pretendardSemibold, pretendardBold)
}
val bmHannaPro = Font(Res.font.bm_hanna_pro, FontWeight.Normal)
val bmHanna = remember(bmHannaPro) {
FontFamily(bmHannaPro)
}
val typography = remember(pretendard, bmHanna) {
crewWikiTypography(
pretendard = pretendard,
bmHanna = bmHanna,
)
}
MaterialTheme(
typography = typography,
content = content,
)
}| android-compileSdk = "36" | ||
| android-minSdk = "24" | ||
| android-targetSdk = "36" |
There was a problem hiding this comment.
이유:
현재 android-compileSdk와 android-targetSdk가 36으로 설정되어 있습니다. Android SDK 36은 아직 정식 출시되지 않은 개발 단계의 버전이므로, 빌드 도구 호환성 문제가 발생하거나 개발자 환경 및 CI/CD 환경에서 빌드가 실패할 수 있습니다.
해결 방안:
현재 가장 안정적인 최신 버전인 35 (Android 15)로 변경하는 것을 권장합니다.
| android-compileSdk = "36" | |
| android-minSdk = "24" | |
| android-targetSdk = "36" | |
| android-compileSdk = "35" | |
| android-minSdk = "24" | |
| android-targetSdk = "35" |
| kotlin { | ||
| compilerOptions { | ||
| jvmTarget = JvmTarget.JVM_11 | ||
| } | ||
| } |
There was a problem hiding this comment.
이유:
현재 jvmTarget이 JVM_11로 설정되어 있습니다. gradle-daemon-jvm.properties에서 JDK 21을 사용하도록 설정되어 있고, 최신 Android 및 Compose Multiplatform 개발에서는 Java 17 이상을 표준으로 권장하므로, JVM_17 (또는 JVM_21)로 업그레이드하는 것이 좋습니다.
해결 방안:
jvmTarget을 JVM_17로 변경하고, 아래 compileOptions의 sourceCompatibility 및 targetCompatibility도 JavaVersion.VERSION_17로 함께 맞춰주세요.
kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_17
}
}| compileOptions { | ||
| sourceCompatibility = JavaVersion.VERSION_11 | ||
| targetCompatibility = JavaVersion.VERSION_11 | ||
| } |
There was a problem hiding this comment.
| compilerOptions { | ||
| jvmTarget = JvmTarget.JVM_11 | ||
| } |
작업 내용
크루위키 Android 앱 작업을 시작하기 위해 KMP 프로젝트 골격을 추가하고, 웹(
crew-wiki-next)에서 사용 중인 폰트/이미지 자산 일부를 Compose Multiplatform 리소스로 이관했습니다.포함 내용
androidApp,shared,iosAppBMHANNAPretendard정적 weight 세트PretendardVariable.ttfCrewWikiTheme에서 기본 타이포그래피 연결apple-icon.png를 Compose drawable 리소스로 추가icon.png,favicon.ico추가docs/asset-migration.md확인 내용
./gradlew :shared:assembleAndroidMain빌드 성공Res.font.*Res.drawable.crew_wiki_apple_icon참고
PretendardVariable.ttf는 리소스로만 추가되어 있고, 실제 테마는 정적Pretendardweight 세트를 사용합니다.