Skip to content
/ Wisp Public

A lightweight annotation-based deep link library for Jetpack Compose. Navigate between destinations as smoothly as a wisp of wind 🎐

License

Notifications You must be signed in to change notification settings

angryPodo/Wisp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

19 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Wisp: νƒ€μž… 세이프 μ„œλ²„ 주도 λ”₯링크 라이브러리

WispλŠ” Jetpack Compose의 νƒ€μž… 세이프 λ„€λΉ„κ²Œμ΄μ…˜ ν™˜κ²½μ—μ„œ, μ„œλ²„κ°€ λ™μ μœΌλ‘œ μ •μ˜ν•˜λŠ” λ°±μŠ€νƒμ„ ν™”λ©΄ κΉœλΉ‘μž„ 없이 μ†μ‰½κ²Œ 탐색할 수 있게 ν•΄μ£ΌλŠ” μ–΄λ…Έν…Œμ΄μ…˜ 기반 λ”₯링크 λΌμ΄λΈŒλŸ¬λ¦¬μž…λ‹ˆλ‹€.

πŸ€” μ™œ WispμΈκ°€μš”?

Jetpack Compose ν™˜κ²½μ—μ„œ navigation-compose의 κΈ°λ³Έ λ”₯λ§ν¬λŠ” 정적인 λ°±μŠ€νƒλ§Œ 생성할 수 μžˆμ–΄, μ„œλ²„κ°€ λ™μ μœΌλ‘œ μ‚¬μš©μž μ—¬μ •(User Journey)을 μ œμ–΄ν•˜λ €λŠ” μš”κ΅¬μ‚¬ν•­μ„ μΆ©μ‘±ν•˜κΈ° μ–΄λ ΅μŠ΅λ‹ˆλ‹€. WispλŠ” 이 과정을 μžλ™ν™”ν•˜μ—¬ κ°œλ°œμžκ°€ 였직 라우트 μ •μ˜μ—λ§Œ 집쀑할 수 μžˆλ„λ‘ λ•μŠ΅λ‹ˆλ‹€.

✨ 핡심 원칙

  • μ„œλ²„ 주도 (Server-Driven): λ°±μŠ€νƒ κ΅¬μ„±μ˜ λͺ¨λ“  κΆŒν•œμ€ μ„œλ²„κ°€ κ°–μŠ΅λ‹ˆλ‹€.
  • λ‹¨μˆœν•¨ (Simplicity): κ°œλ°œμžλŠ” 라우트 클래슀 μ •μ˜μ™€ μ–΄λ…Έν…Œμ΄μ…˜ μΆ”κ°€ 외에 λ³΅μž‘ν•œ λ‘œμ§μ„ μ‹ κ²½ μ“°μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
  • μœ μ—°μ„± (Flexibility): URI νŒŒμ‹± λ‘œμ§μ„ μ™ΈλΆ€μ—μ„œ μ£Όμž…ν•  수 μžˆμ–΄, μ–΄λ–€ ν˜•νƒœμ˜ λ”₯링크 URI μŠ€ν‚΄(Scheme)이라도 지원할 수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ› οΈ μ„€μΉ˜

1. build.gradle.kts (Project Level) settings.gradle.ktsκ°€ μ•„λ‹Œ ν”„λ‘œμ νŠΈ 레벨의 build.gradle.kts에 KSP ν”ŒλŸ¬κ·ΈμΈμ„ μΆ”κ°€ν•©λ‹ˆλ‹€.

plugins {
    // ...
    alias(libs.plugins.ksp) apply false
}

2. build.gradle.kts (App Module Level) app λͺ¨λ“ˆμ˜ build.gradle.kts에 ν”ŒλŸ¬κ·ΈμΈκ³Ό μ˜μ‘΄μ„±μ„ μΆ”κ°€ν•©λ‹ˆλ‹€.

plugins {
    // ...
    alias(libs.plugins.ksp)
}

dependencies {
    // Wisp
    implementation(project(":wisp-runtime"))
    ksp(project(":wisp-processor"))

    // ... 기타 μ˜μ‘΄μ„±
}

πŸš€ μ‚¬μš©λ²•

1. 라우트 μ •μ˜

@Serializable μ–΄λ…Έν…Œμ΄μ…˜μ΄ 뢙은 data class λ˜λŠ” object에 @Wisp μ–΄λ…Έν…Œμ΄μ…˜μ„ μΆ”κ°€ν•˜μ—¬ λ”₯링크 λŒ€μƒμœΌλ‘œ μ§€μ •ν•©λ‹ˆλ‹€.

// app/src/main/java/com/example/app/Routes.kt

import com.angrypodo.wisp.annotations.Wisp
import kotlinx.serialization.Serializable

@Serializable
@Wisp("home")
data object Home

@Serializable
@Wisp("product/{productId}")
data class ProductDetail(val productId: String)

@Serializable
@Wisp("settings")
data object Settings

2. 라이브러리 μ΄ˆκΈ°ν™”

Application 클래슀의 onCreate()μ—μ„œ, KSPκ°€ μƒμ„±ν•œ WispRegistryλ₯Ό μ‚¬μš©ν•˜μ—¬ Wisp 라이브러리λ₯Ό μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.

// app/src/main/java/com/example/app/MyApplication.kt

import android.app.Application
import com.angrypodo.wisp.generated.WispRegistry
import com.angrypodo.wisp.runtime.Wisp

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Wisp.initialize(WispRegistry)
    }
}

주의: AndroidManifest.xml의 <application> νƒœκ·Έμ— android:name=".MyApplication" 속성을 μΆ”κ°€ν•˜λŠ” 것을 μžŠμ§€ λ§ˆμ„Έμš”.

3. NavHost μ„€μ •

Compose Activityμ—μ„œ NavHostλ₯Ό μ„€μ •ν•˜κ³ , μ •μ˜ν•œ λΌμš°νŠΈμ™€ Composable 화면을 μ—°κ²°ν•©λ‹ˆλ‹€.

// app/src/main/java/com/example/app/MainActivity.kt

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val navController = rememberNavController()
            NavHost(navController = navController, startDestination = Home) {
                composable<Home> { HomeScreen(navController) }
                composable<ProductDetail> { backStackEntry ->
                    val product = backStackEntry.toRoute<ProductDetail>()
                    ProductDetailScreen(product.productId)
                }
                composable<Settings> { SettingsScreen() }
            }
        }
    }
}

4. λ”₯링크 탐색 μ‹€ν–‰

이제 μ•±μ˜ μ–΄λŠ κ³³μ—μ„œλ“  NavController만 μžˆλ‹€λ©΄ navigateTo(uri) ν™•μž₯ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 동적 λ°±μŠ€νƒμ„ 탐색할 수 μžˆμŠ΅λ‹ˆλ‹€.

  • URI ν˜•μ‹: scheme://host?stack={encoded_stack}
  • stack νŒŒλΌλ―Έν„°:
    • κ°œλ³„ λ°±μŠ€νƒ κ²½λ‘œλŠ” | 문자둜 κ΅¬λΆ„ν•©λ‹ˆλ‹€.
    • URL 인코딩이 ν•„μš”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
// HomeScreen.kt μ—μ„œ λ²„νŠΌ 클릭 μ‹œ λ”₯링크 μ‹€ν–‰

Button(onClick = {
    // λ°±μŠ€νƒ: ProductDetail(productId="123") -> Settings
    val uri = "app://wisp?stack=product/123|settings".toUri()
    navController.navigateTo(uri)
}) {
    Text("Deep Link Navigation")
}
_11.24._23.34.mp4

About

A lightweight annotation-based deep link library for Jetpack Compose. Navigate between destinations as smoothly as a wisp of wind 🎐

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages