Today's

길을 나서지 않으면 그 길에서 만날 수 있는 사람을 만날 수 없다

모바일 앱(안드로이드)

습관 관리 앱 만들기 (1) - Hilt, Room으로 뼈대 세우기

Billcorea 2025. 10. 10. 15:58
반응형

 

 

 

초보 안드로이드 개발자의 습관 관리 앱 만들기 (1) - Hilt, Room으로 뼈대 세우기

앱 만들기 초안

 

안녕하세요! 오늘은 Jetpack Compose를 사용해 간단한 습관 관리 앱을 만들어보는 여정의 첫걸음을 기록해보려고 합니다. 앱의 기반을 튼튼하게 다지기 위해, 구글이 강력하게 추천하는 라이브러리인 HiltRoom을 적용하여 기본적인 데이터 추가 및 조회 기능을 구현했습니다.

왜 Hilt와 Room 인가?

앱 개발을 시작하기에 앞서, 두 가지 중요한 결정을 했습니다.

  • Hilt (의존성 주입 라이브러리): 클래스(객체)들이 필요로 하는 다른 객체들을 직접 생성하지 않고, 외부에서 "주입"해주는 방식입니다. 보일러플레이트 코드를 줄여주고, 테스트 용이성을 높이며, 앱의 전체적인 구조를 깔끔하게 만들어줍니다.
  • Room (로컬 데이터베이스 라이브러리): 사용자의 데이터를 앱 내에 안전하고 효율적으로 저장하기 위해 사용합니다. SQLite를 직접 사용하는 것보다 훨씬 간편하며, 컴파일 시간에 SQL 쿼리를 검증하여 런타임 오류를 방지해줍니다.

1단계: Gradle 설정 및 의존성 추가

가장 먼저, Hilt와 Room을 사용하기 위해 필요한 라이브러리들을 gradle/libs.versions.tomlapp/build.gradle.kts 파일에 추가했습니다. 이 과정에서 Kotlin 버전과 KSP(Kotlin Symbol Processing) 버전을 맞추는 것이 매우 중요했습니다.

// gradle/libs.versions.toml 일부
[versions]
kotlin = "2.2.20"
ksp = "2.2.20-2.0.3" // Kotlin 버전에 맞는 KSP 버전 사용!
hilt = "2.57.2"
room = "2.8.1"

[libraries]
# Hilt
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }

# Room
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }

[plugins]
hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }

또한, Hilt를 사용하기 위해 Application 클래스를 상속받는 HabitApplication을 만들고 @HiltAndroidApp 어노테이션을 붙여준 뒤, AndroidManifest.xml에 등록하는 작업을 진행했습니다.

2단계: 데이터베이스 구조 설계 (Entity, DAO, Database)

데이터베이스의 구조를 코드로 정의하는 단계를 진행했습니다.

Habit (Entity)

습관 데이터를 담을 테이블입니다. @Entity 어노테이션을 붙여 Room이 테이블로 인식하도록 했습니다.

// data/Habit.kt
@Entity(tableName = "habits")
data class Habit(
    @PrimaryKey(autoGenerate = true)
    val id: Int = 0,
    val name: String,
    val icon: String,
    val period: String,
    val time: String
)

HabitDao (Data Access Object)

데이터베이스에 실제로 접근하여 데이터를 읽고 쓰는 함수들을 정의하는 인터페이스입니다. Flow를 사용해 데이터 변경을 실시간으로 감지할 수 있도록 했습니다.

// data/HabitDao.kt
@Dao
interface HabitDao {
    @Insert
    suspend fun insertHabit(habit: Habit)

    @Query("SELECT * FROM habits ORDER BY id DESC")
    fun getAllHabits(): Flow<List<Habit>>
}

AppDatabase 및 Hilt 모듈

마지막으로, 위 요소들을 하나로 묶는 AppDatabase 클래스와, 이 데이터베이스 객체를 앱 전체에 제공(주입)하는 방법을 Hilt에게 알려주는 DatabaseModule을 만들었습니다.

// di/DatabaseModule.kt
@InstallIn(SingletonComponent::class)
@Module
object DatabaseModule {
    @Provides
    @Singleton
    fun provideAppDatabase(@ApplicationContext context: Context): AppDatabase {
        return Room.databaseBuilder(
            context,
            AppDatabase::class.java,
            "habit_database"
        ).build()
    }

    @Provides
    @Singleton
    fun provideHabitDao(appDatabase: AppDatabase): HabitDao {
        return appDatabase.habitDao()
    }
}

3단계: UI와 데이터 연결 (ViewModel)

MVVM 아키텍처에 따라, UI(View)와 데이터(Model)를 연결하는 ViewModel을 만들었습니다. @HiltViewModel 어노테이션을 사용하면 ViewModel 생성자에 필요한 의존성(HabitDao)을 Hilt가 알아서 주입해줍니다.

  • AddViewModel: 새로운 습관을 데이터베이스에 추가하는 역할.
  • HomeViewModel: 데이터베이스의 모든 습관 목록을 UI에 제공하는 역할.

4단계: 화면 구현 및 디자인 개선

마지막으로, 사용자가 실제로 보게 될 화면을 구현했습니다.

  • AddScreen: 사용자가 새로운 습관 이름을 입력하고 저장 버튼을 누르면 AddViewModel을 통해 데이터베이스에 저장합니다.
  • HomeScreen: HomeViewModel로부터 습관 목록을 실시간으로 받아와 LazyColumn으로 표시합니다. 처음에는 단순한 텍스트 목록이었지만, 가독성과 디자인을 개선하기 위해 각 항목을 Card로 감싸고 아이콘과 추가 정보를 표시하도록 개선했습니다.
Screenshot of the improved HomeScreen

디자인이 개선된 HomeScreen의 모습

오늘의 교훈: 마주친 오류들

개발 과정이 순탄하지만은 않았습니다. 몇 가지 중요한 오류를 만났고 해결 과정을 통해 많이 배울 수 있었습니다.

  • @AndroidEntryPoint 누락: Hilt를 사용하는 Activity에는 반드시 @AndroidEntryPoint 어노테이션을 붙여야 한다는 것을 배웠습니다.
  • JVM 타겟 버전 불일치: Java와 Kotlin의 컴파일 타겟 JVM 버전이 달라 발생하는 오류는 build.gradle.kts에서 compilerOptions를 통해 명시적으로 버전을 통일하여 해결했습니다.
  • Hilt와 Compose Preview: @Preview 환경에서는 Hilt 의존성 주입이 동작하지 않아 프리뷰 빌드 오류가 발생할 수 있다는 점을 알게 되었습니다.

마치며

오늘은 앱의 가장 기본적인 뼈대를 세우는 작업을 진행했습니다. Hilt와 Room을 사용해 확장 가능하고 안정적인 데이터 처리 기반을 마련했고, Jetpack Compose를 이용해 간단한 데이터 추가 및 조회 화면을 만들었습니다. 다음 포스트에서는 사용자가 직접 아이콘을 선택하는 기능과 습관을 수정/삭제하는 기능을 구현해보겠습니다. 긴 글 읽어주셔서 감사합니다!

반응형