App 프로젝트 구조 분석 및 개발 가이드

프로젝트 개요

현재 프로젝트는 Wear OS 전용 앱으로 설정되어 있습니다.

  • 패키지명: com.example.kotlinapp
  • Wear OS Compose 기반
  • Standalone 앱 (스마트폰 없이 독립 실행 가능)

현재 파일 구조

kotlin_app/
├── app/
│   ├── src/
│   │   └── main/
│   │       ├── AndroidManifest.xml
│   │       ├── java/com/example/kotlinapp/
│   │       │   └── presentation/
│   │       │       ├── MainActivity.kt
│   │       │       └── theme/
│   │       │           └── Theme.kt
│   │       └── res/
│   │           ├── drawable/
│   │           ├── mipmap-*/
│   │           ├── values/
│   │           └── values-round/
│   ├── build.gradle.kts
│   └── proguard-rules.pro
├── gradle/
│   └── libs.versions.toml
├── build.gradle.kts
└── settings.gradle.kts

기술 스택

현재 사용 중인 라이브러리

  • Compose BOM: 2024.09.00
  • Wear Compose Material: 1.2.1
  • Wear Compose Foundation: 1.2.1
  • Play Services Wearable: 18.0.0
  • Activity Compose: 1.8.0
  • Core Splashscreen: 1.0.1

SDK 버전

  • minSdk: 30 (Android 11 - Wear OS 3.0)
  • targetSdk: 36
  • compileSdk: 36

Mobile + Wear 앱 구조 제안

1. 멀티 모듈 아키텍처 (권장)

프로젝트를 Mobile과 Wear로 분리하려면 다음 구조를 추천합니다:

kotlin_app/
├── mobile/                    # 스마트폰 앱 모듈
│   ├── src/
│   │   └── main/
│   │       ├── AndroidManifest.xml
│   │       └── java/com/example/kotlinapp/mobile/
│   │           ├── MainActivity.kt
│   │           ├── ui/
│   │           ├── viewmodel/
│   │           └── data/
│   └── build.gradle.kts
│
├── wear/                      # 웨어러블 앱 모듈 (현재 app 모듈)
│   ├── src/
│   │   └── main/
│   │       ├── AndroidManifest.xml
│   │       └── java/com/example/kotlinapp/wear/
│   │           ├── MainActivity.kt
│   │           ├── presentation/
│   │           └── complication/
│   └── build.gradle.kts
│
├── shared/                    # 공통 코드 모듈
│   ├── src/
│   │   └── main/
│   │       └── java/com/example/kotlinapp/shared/
│   │           ├── data/
│   │           │   ├── model/       # 데이터 모델
│   │           │   └── repository/  # 저장소 인터페이스
│   │           └── domain/
│   │               └── usecase/     # 비즈니스 로직
│   └── build.gradle.kts
│
├── gradle/
├── build.gradle.kts
└── settings.gradle.kts

2. 모듈별 역할

Mobile 모듈 (mobile/)

  • 스마트폰 UI (일반 Compose 사용)
  • 데이터 입력 및 설정
  • Wear 앱과의 데이터 동기화
  • 백그라운드 서비스

Wear 모듈 (wear/)

  • Wear OS UI (Wear Compose 사용)
  • 워치 페이스/컴플리케이션
  • 간단한 데이터 표시 및 조작
  • 센서 데이터 수집 (심박수, 걸음 수 등)

Shared 모듈 (shared/)

  • 데이터 모델 (Kotlin Data Class)
  • 네트워크 통신 로직
  • 데이터베이스 스키마
  • Wearable Data Layer API 통신 프로토콜

코드 작성 위치 가이드

현재 구조에서 코드 추가하기

1. UI 화면 추가

위치: app/src/main/java/com/example/kotlinapp/presentation/screens/

// 예시: HomeScreen.kt
package com.example.kotlinapp.presentation.screens
 
import androidx.compose.runtime.Composable
import androidx.wear.compose.material.*
 
@Composable
fun HomeScreen() {
    // Wear OS UI 구현
}

2. ViewModel 추가

위치: app/src/main/java/com/example/kotlinapp/presentation/viewmodel/

// 예시: MainViewModel.kt
package com.example.kotlinapp.presentation.viewmodel
 
import androidx.lifecycle.ViewModel
 
class MainViewModel : ViewModel() {
    // 상태 관리 로직
}

3. 데이터 모델

위치: app/src/main/java/com/example/kotlinapp/data/model/

// 예시: UserData.kt
package com.example.kotlinapp.data.model
 
data class UserData(
    val id: String,
    val name: String
)

4. Repository (데이터 소스)

위치: app/src/main/java/com/example/kotlinapp/data/repository/

// 예시: UserRepository.kt
package com.example.kotlinapp.data.repository
 
interface UserRepository {
    suspend fun getUser(): UserData
}

5. Navigation

위치: app/src/main/java/com/example/kotlinapp/presentation/navigation/

// 예시: NavGraph.kt
package com.example.kotlinapp.presentation.navigation
 
import androidx.navigation.NavHostController
import androidx.wear.compose.navigation.SwipeDismissableNavHost

6. Utils/Extensions

위치: app/src/main/java/com/example/kotlinapp/utils/

Mobile + Wear 앱 구현 방법

방법 1: 별도 프로젝트로 분리

  • Mobile 앱과 Wear 앱을 완전히 독립된 프로젝트로 개발
  • 장점: 각각 독립적으로 배포 및 관리 가능
  • 단점: 코드 중복 가능성, 동기화 어려움

방법 2: 멀티 모듈 프로젝트 (권장)

  • 하나의 프로젝트 안에 mobile, wear, shared 모듈 구성
  • 장점: 코드 공유 용이, 일관된 버전 관리
  • 단점: 초기 설정 복잡도 증가

방법 3: Flavor 활용

  • buildType flavor로 mobile/wear 구분
  • 장점: 프로젝트 구조 간단
  • 단점: UI 라이브러리가 달라서 관리 어려움

멀티 모듈 구성 방법

1. settings.gradle.kts 수정

rootProject.name = "Kotlin App"
include(":mobile")
include(":wear")
include(":shared")

2. 현재 app 모듈을 wear로 변경

# 디렉토리 이름 변경
mv app wear

3. mobile 모듈 생성

Android Studio에서:

  1. File > New > New Module
  2. “Phone & Tablet Module” 선택
  3. Module name: “mobile”
  4. Package name: com.example.kotlinapp.mobile

4. shared 모듈 생성

Android Studio에서:

  1. File > New > New Module
  2. “Android Library” 선택
  3. Module name: “shared”
  4. Package name: com.example.kotlinapp.shared

5. shared 모듈의 build.gradle.kts

plugins {
    alias(libs.plugins.android.library)
    alias(libs.plugins.kotlin.android)
}
 
android {
    namespace = "com.example.kotlinapp.shared"
    compileSdk = 36
 
    defaultConfig {
        minSdk = 30
    }
}
 
dependencies {
    // 공통 라이브러리
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
}

6. mobile/wear 모듈에서 shared 참조

dependencies {
    implementation(project(":shared"))
    // 기타 의존성...
}

Mobile-Wear 데이터 통신

Wearable Data Layer API 사용

shared 모듈에 공통 상수 정의

// shared/src/main/java/com/example/kotlinapp/shared/WearableConstants.kt
object WearableConstants {
    const val DATA_PATH = "/kotlin_data"
    const val MESSAGE_PATH = "/kotlin_message"
}

Mobile에서 데이터 전송

// mobile 모듈
import com.google.android.gms.wearable.*
 
class DataSender(private val context: Context) {
    private val dataClient: DataClient by lazy {
        Wearable.getDataClient(context)
    }
 
    suspend fun sendData(data: ByteArray) {
        val putDataReq = PutDataMapRequest.create(WearableConstants.DATA_PATH).run {
            dataMap.putByteArray("data", data)
            asPutDataRequest()
        }
        dataClient.putDataItem(putDataReq).await()
    }
}

Wear에서 데이터 수신

// wear 모듈
class DataReceiver(context: Context) : WearableListenerService() {
    override fun onDataChanged(dataEvents: DataEventBuffer) {
        dataEvents.forEach { event ->
            if (event.dataItem.uri.path == WearableConstants.DATA_PATH) {
                val data = DataMapItem.fromDataItem(event.dataItem)
                    .dataMap.getByteArray("data")
                // 데이터 처리
            }
        }
    }
}

권장 아키텍처 패턴

MVVM (Model-View-ViewModel)

presentation/
├── screens/          # Composable UI
│   ├── HomeScreen.kt
│   └── DetailScreen.kt
├── viewmodel/        # ViewModel
│   ├── HomeViewModel.kt
│   └── DetailViewModel.kt
└── navigation/       # Navigation Graph

data/
├── model/           # 데이터 모델
├── repository/      # Repository 구현
└── source/          # 데이터 소스 (local/remote)

domain/
├── usecase/         # 비즈니스 로직
└── repository/      # Repository 인터페이스

다음 단계

  1. 현재 단일 모듈(Wear only) 유지 vs 멀티 모듈 전환 결정
  2. Mobile 앱 필요 여부 확인
  3. 데이터 공유 방식 결정 (Wearable Data Layer, Firebase, REST API 등)
  4. UI/UX 설계
  5. 기능 구현 시작

참고 자료