안녕하세요. 이런 글을 프로그래밍 글을 쓰는 건 참 오랜만인데요
그동안 프로그램 짜느라 못올렸습니다. 이번에 총 7~8편정도로 작성할 계획이니
많은 관심 부탁드립니다.
원래는 xml방식을 이용하여 android개발을 하였으나
이번에 시간을 들여 jetpack compose와 hilt를 사용하는 방식으로
새로운 기술을 공부하게 되었습니다.
이번에 새롭게 공부한 내용에 대해 소개하겠습니다.
1. Jetpack Compose 개념
참조문서(android developer 공식문서)
https://developer.android.com/codelabs/jetpack-compose-basics?hl=ko#0
Jetpack Compose 기초 | Android Developers
이 Codelab에서는 Compose의 기본사항을 알아봅니다.
developer.android.com
JetpackCompose는 안드로이드의 최신 UI 툴킷으로, 선언형 UI 방식을 사용하여 사용자 인터페이스를 구축합니다.
이 방식은 XML 기반의 전통적인 UI 방식과 달리,
Kotlin 코드를 사용하여 UI를 정의하고 상태변화에 따라 UI가 자동으로 갱신되도록 설계되어 있습니다.
2. Hilt 개념
참조문서(android developer 공식문서)
https://developer.android.com/codelabs/android-hilt?hl=ko#0
Android 앱에서 Hilt 사용 | Android Developers
이 Codelab에서는 Hilt를 사용하여 종속 항목 삽입을 실행하는 Android 앱을 빌드해 보겠습니다.
developer.android.com
Hilt는 Dagger 기반의 Android용 의존성 주입 라이브러리로, 애플리케이션에서 의존성을 쉽게 주입하고 관리할 수 있도록 도와줍니다.
특히 Jetpack Compose와 잘 통합되어 ViewModel 또는 기타 클래스에 필요한 의존성을 쉽게 주입할 수 있습니다.
DI(의존성)은 프로그래밍에서 널리 사용되는 기법으로 Android 개발에 적합합니다.
DI를 구현하면 다음과 같은 이점이 있습니다.
- 코드 재사용 가능
- 리팩터링 편의성
- 테스트 편의성
3. Hilt 세팅방법
1) build.gradle(project 수준)
buildscript {
val kotlinVersion by extra("2.0.0")
val hiltVersion by extra("2.51.1")
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.google.dagger:hilt-android-gradle-plugin:$hiltVersion")
classpath ("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
}
}
저는 각 version을 위와 같이 맞춰 hilt를 사용하였습니다.
2) build.gradle(app 수준)
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
alias(libs.plugins.compose.compiler)
id("dagger.hilt.android.plugin")
kotlin("kapt")
}
dependencies {
// Hilt dependencies
implementation("com.google.dagger:hilt-android:2.51.1")
kapt("com.google.dagger:hilt-android-compiler:2.51.1")
// Hilt and ViewModel integration (optional)
kapt("androidx.hilt:hilt-compiler:1.0.0")
//hilt life
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
//hilt test
implementation("androidx.compose.compiler:compiler:1.5.3")
}
//hilt +
kapt {
correctErrorTypes = true
}
Android studio와 Hilt 세팅방법 단계를 다 따라하셨다면.
이제 Jetpack Compose와 Hilt를 이용할 준비는 모두 다 되었습니다.
4. Jetpack Compose와 Hilt 구현
이제부터는 jetpack compose와 hilt를 이용해 개발을 시작해보겠습니다.
1) Jetpack Compose 구현
우선 기존 xml방식과 마찬가지로 새로운 project에서 Empty Activity를 선택하면 MainActivity가 생성됩니다.
이후 Theme.kt에 있는 @Composable annotation이 붙은 000Theme의 이름을 파악한 후 (내코드 Theme.kt - SecretDiaryTheme 예시)
이 코드와(MainActivity) 같은 형식으로 만들어 줍니다.
저의 경우 Theme.kt에 SecretDiaryTheme이라는 composable함수가 생성되어 있습니다.
이후 SecretDiaryTheme을 아래와 같이 MainActivity에 적용합니다.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
SecretDiaryTheme {
}
}
}
}
이제는 본격적으로 SecretDiaryTheme을 적용할 UI를 구현할 차례입니다.
Compose 앱은 함수로 구성되어 있으며 이러한 함수들은 @Composable annotation을 붙이며
지속적으로 해당 함수를 호출하며 지속적으로 UI를 업데이트하고 유지관리합니다.
@Composable
fun SDScreen() {
}
위와 같은 형식으로 하나의 화면을 담당할 Composable 함수를 만들고
아래와 같이 아까 작성한 MainActivity의 SecretDiaryTheme에 적용합니다.
SecretDiaryTheme {
SDScreen()
}
2) Hilt 구현
이제는 compose 앱에 Hilt를 적용시켜봅시다.
저의 경우 SDApplication class를 만들고 상단에 @HiltAndroidApp이라는 annotation을 붙여주었습니다.
@HiltAndroidApp
class SDApplication : Application(){
}
그 다음에는 compose 앱을 구축할 때 본 MainActivity에 @AndroidEntryPoint라는 annotation을 붙여줍니다.
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
이번에는 아까 만든 SDScreen에 연결할 viewModel을 구현해보겠습니다.
여기서 viewModel은 UI와 데이터 로직의 분리를 위해 사용합니다.
viewModel은 UI에서 직접 데이터를 다루지 않고, UI로직과 데이터 로직을 분리하는 역할을 합니다
@HiltViewModel
class SecurityViewModel @Inject constructor() : ViewModel() {
}
viewModel을 구현 할 때는 class에 @HiltViewModel annotation을 달아줍니다.
여기서 @Inject constructor은 Hilt의 주된 목적중 하나인 DI주입을 위한 것입니다.
이 constructor안에는 추후 글을 작성할 room의 repository 사용을 위한 DI가 들어가게 됩니다
이제는 SDScreen과 SecurityViewModel을 연결하겠습니다.
SecretDiaryTheme {
SDScreen(viewModel = SecurityViewModel())
}
이런식으로 간단하게 작성하시면 SDScreen에서 SecurityViewModel을 이용해 데이터를 관리할 수 있게 됩니다.
Hilt와 Jetpack Compose를 함께 사용하면 ViewModel 또는 Repository 같은 의존성을 주입하여 상태를 관리하고,
이 상태를 기반으로 동적으로 UI를 갱신하는 앱을 쉽게 만들 수 있습니다.
결론적으로 jetpack compose는 hilt와 잘 통합되어 있으므로 두 기술은 모두 배워야 합니다.
5. Compose 상태관리
이 부분은 다음 글에 껴 넣거나 따로 쓰려다가 이 글에 같이 쓰는게 좋을 것 같아서 추가하게 되었습니다.
이 파트에서 소개할것은 mutableStateOf와 remember입니다.
이들은 Compose의 기초이자 핵심이므로 1편에 포함하였습니다.
mutableStateOf와 remember는 Jetpack Compose에서 상태 관리를 할 때 자주 사용하는 중요한 요소들입니다.
이 두 가지는 상태를 유지하고, 상태 변화에 따라 UI를 갱신하는데 사용됩니다.
1) mutableStateOf
mutableStateOf는 Jetpack Compose에서 상태를 저장하고 관리하는 가장 기본적인 도구입니다.
상태가 변경되면 해당 상태를 사용하는 Composable함수가 Recomposition을 통해 다시 그려집니다.
mutalbeStateOf의 특징
- mutableStateOf는 상태가 변경될 때 UI를 자동으로 다시 그리는 역할을 합니다.
- 자동 Recomposition을 지원하므로 개발자가 별도로 상태 변화를 반영하기 윈한 작업을 할 필요가 없습니다.
- 기본값을 설정할 수 있으며, 상태는 value 프로퍼티를 통해 접근하고 변경됩니다.
2) remember
remember는 Jetpack Compose에서 Recomposition(재구성)이 발생하더라도 특정 값을 유지하는데 사용됩니다.
Composable 함수가 다시 호출되더라도 remember는 이전에 저장된 값을 유지하여 상태가 초기화되지 않도록 합니다.
remember의 특징
- remember는 Composable 함수 내부에서 호출되며, 상태가 필요할 때 초기화를 담당합니다.
- 한 번 저장된 상태는 해당 Composable함수가 다시 호출되더라도 유지됩니다.
- remember는 기본적으로 Composable함수가 다시 그려지더라도 상태를 유지할 수 있게 해줍니다. 상태가 Recomposition 시 다시 초기화 되는 것을 방지합니다.
코드를 예시로 둘의 관계와 이해를 도와드리겠습니다.
@Composable
fun TempoScreen(
navController: NavHostController,
viewModel: SettingViewModel,
modifier: Modifier = Modifier
){
var count by remember { mutableStateOf(0) }
// UI 구성
Column {
// 카운트 숫자를 표시하는 텍스트
Text(text = "Count: $count", fontSize = 30.sp)
// 버튼을 클릭할 때마다 count를 1씩 증가시킴
Button(onClick = { count++ }) {
Text(text = "Increase Count")
}
}
}
이 코드에 대해 설명하겠습니다.
count의 값은 버튼을 누를 때 마다 값이 증가(변화)하며 mutableStateOf로 관리하고 있으므로 recomposition이 일어납니다.
만약 remember이 없다면 recomposition이 일어날 시 count값은 초기 값인 0이 될 것입니다.
허나, remember이 붙은 변수는 Composable함수가 다시 그려지더라도 상태를 유지하므로
recomposition시 count가 0이 되는 것이 아닌 증가하는 모습을 보여줍니다.
만약 mutableStateOf만 있고 remember이 붙어 있지 않았다면 count를 count.value로 관리해야되지만
remember이 함께하므로 count로만으로도 값을 변경시킬 수 있습니다.
여기까지 JetpackCompose와 Hilt에 대해 알아보았습니다.
다음 글은 Jetpack Compose에서의 디자인 구현의 특징으로 찾아뵙겠습니다.
'안드로이드 앱개발' 카테고리의 다른 글
Retrofit2를 이용한 안드로이드와 스프링 서버 통신(안드로이드편)(안드로이드 서버통신) (3) | 2024.10.03 |
---|---|
Kotlin Coruoutins과 비동기에 관하여 (1) | 2024.10.02 |
Android Room 사용하기 (4) | 2024.09.28 |
Jetpack Compose에서 UI 화면 구성과 전환(scaffold, box, navHost) (0) | 2024.09.26 |
안드로이드로 아두이와 서버통신 제어하기(WIFI D1 R1, ESP8266, 모터제어, JSON)(2) (0) | 2023.05.09 |