[안드로이드 클린 아키텍처 시리즈] UI Layer 구현 3편 (with Jetpack Compose) #10

2024. 2. 14. 11:30·안드로이드/클린 아키텍처
반응형

1. 안드로이드 클린 아키텍처 UI Layer 3편

안녕하세요. 이전 포스팅에서는 Hilt를 통한 의존성 주입에 대해 살펴보았습니다. 이번 포스팅에서는 UI Layer의 마지막 부분으로, UI 컴포넌트와 ViewModel을 연결하고 사용자 인터페이스를 통해 데이터를 표시하기 위해서 Jetpack Compose를 활용한 화면 구성부터 구현하겠습니다. 본 시리즈는 클린 아키텍처에 대해 다루고 있기 때문에 Jetpack Compose를 자세히 설명하지는 않겠습니다.

영화 정보를 사용자 화면에 보여준 모습
Data Layer로부터 불러온 데이터를 화면에 보여준 모습

2. Jetpack Compose를 이용한 UI 구현

Jetpack Compose는 최신 안드로이드 UI 개발 툴킷으로, 선언적 UI 프로그래밍을 가능하게 해 줍니다. 이를 통해 더 간결하고 직관적인 코드로 UI를 구성할 수 있습니다. 우리는 Jetpack Compose를 사용하여 사용자 인터페이스를 구성하고, ViewModel에서 제공하는 데이터를 화면에 바인딩하는 과정을 구현할 예정입니다.

2-1. Compose Navigation 구현

먼저, 첫 시작 화면이나 화면 이동을 편하게 하기 위해서 jetpack compose navigation 세팅을 해주겠습니다. navigation은 크게 3가지로 구분됩니다. 아래의 코드를 보면 NavHost의 startDestination에 Page.MoveDetail.route를 전달했기 때문에 시작 화면은 MovieDetailScreen이 됩니다.

  • NavGraph : 앱 내에서 접근 가능한 모든 화면(destination)과 이 화면 사이를 이동할 수 있는 경로를 정의
  • NavHost : NavController를 통해 사용자의 명령을 실행할 수 있는 컨테이너. 즉, 화면을 보여주는 컨테이너
  • NavController : 사용자가 앱 내에서 화면을 이동할 때, NavHost에 적절한 화면을 표시하도록 관리
sealed class Page(val route: String) {
    data object MoveDetail: Page("movie_detail")
}
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val navController = rememberNavController()
            CleanarchitectureexampleTheme {
                MainGraph(mainNavController = navController)
            }
        }
    }
}
@Composable
fun MainGraph(
    mainNavController: NavHostController
) {
    NavHost(navController = mainNavController, startDestination = Page.MoveDetail.route) {
        composable(
            route = Page.MoveDetail.route
        ) {
            val viewModel = hiltViewModel<MovieDetailViewModel>()
            MovieDetailScreen(
                mainNavController = mainNavController,
                viewModel = viewModel
            )
        }
    }
}

2-2. MovieDetailViewModel 구현

MovieDetailViewModel에서는 GetMovieDetail UseCase를 호출해서 Data Layer로부터 영화 정보를 가져오겠습니다. 원래는 영화 리스트 항목에서 선택한 movieId를 받아와서 호출을 해야하지만, 영화 리스트 화면이 없기 때문에 '466420'라는 영화 고유값을 강제로 넣어줘서 해당 영화의 상세 정보를 가져오겠습니다.

@HiltViewModel
class MovieDetailViewModel @Inject constructor(
    private val getMovieDetail: GetMovieDetail,
    savedStateHandle: SavedStateHandle,
) : ViewModel() {
    val movieId = mutableStateOf(savedStateHandle.get<Int>("movieId") ?: 466420)
    val movie = mutableStateOf<MovieEntity?>(null)
    init {
        viewModelScope.launch {
            getMovieById(movieId.value).onSuccess {
                Log.d("MovieDetailViewModel", "MovieDetailViewModel: $it")
                movie.value = it
            }
        }

    }
    private suspend fun getMovieById(movieId: Int): ApiResult<MovieEntity> {
        return getMovieDetail(movieId)
    }
}

2-3. MovieDetailScreen 구현

MovieDetailViewModel에서 영화에 대한 정보를 movie라는 상태변수에 저장했습니다. 해당 데이터가 정상적으로 불러와졌는지 확인하기 Screen에서 viewModel의 movie 정보를 Text Composeable에 전달하겠습니다. 그러면 화면에서 영화 정보를 확인할 수 있습니다.

@Composable
fun MovieDetailScreen(
    mainNavController: NavHostController,
    viewModel: MovieDetailViewModel
) {
    Column {
        Text(text = viewModel.movie.value.toString())
    }
}

3. Compose navigation 및 Screen, ViewModel 정리

이번 시간에는 각 화면의 이동, 시작화면 등의 화면 구성을 위해 compose navigation을 구현했고 영화 세부 정보를 볼 수 있는 MovieDetailScreen과 MovieDetailViewModel를 간단하게 구현했습니다.

ViewModel에서는 Domain Layer에 해당되는 getMovieDetail UseCase를 호출하고 Domain Layer에서 Repository에 영화 정보를 요청하여 다시 ViewModel로 데이터가 전달되는 과정을 통해 Screen에 영화 정보를 볼 수 있었습니다.

다음 포스팅에서는 Screen을 좀 더 이쁘게 꾸며보고 클린 아키텍처 시리즈를 마무리 하겠습니다.

저작자표시 비영리 변경금지

'안드로이드 > 클린 아키텍처' 카테고리의 다른 글

[안드로이드 클린 아키텍처 시리즈] UI Layer 구현 4편 (with Jetpack Compose) #11  (0) 2024.02.15
[안드로이드 클린 아키텍처 시리즈] UI Layer 구현 2편 (with Hilt) #9  (0) 2024.02.13
[안드로이드 클린 아키텍처 시리즈] UI Layer 구현 1편 (with Hilt) #8  (0) 2024.02.12
[안드로이드 클린 아키텍처 시리즈] Data Layer 구현 2편 #7  (0) 2024.02.11
[안드로이드 클린 아키텍처 시리즈] Data Layer 구현 1편 #6  (0) 2024.02.10
'안드로이드/클린 아키텍처' 카테고리의 다른 글
  • [안드로이드 클린 아키텍처 시리즈] UI Layer 구현 4편 (with Jetpack Compose) #11
  • [안드로이드 클린 아키텍처 시리즈] UI Layer 구현 2편 (with Hilt) #9
  • [안드로이드 클린 아키텍처 시리즈] UI Layer 구현 1편 (with Hilt) #8
  • [안드로이드 클린 아키텍처 시리즈] Data Layer 구현 2편 #7
코딩덕
코딩덕
안드로이드, 리액트 등의 개발 노하우와 최신 AI 기술을 다루는 기술 블로그입니다. 실무 중심의 경험을 바탕으로 마주한 문제와 해결 과정을 체계적으로 기록하며, 개발자에게 실질적으로 도움 되는 프로그래밍 팁과 인사이트를 쉽고 명확하게 공유하고자 합니다.
  • 코딩덕
    개발자가 들려주는 IT 이야기
    코딩덕
  • 전체
    오늘
    어제
    • 분류 전체보기 (66)
      • 안드로이드 (62)
        • 멀티 모듈 (11)
        • 클린 아키텍처 (11)
        • 트러블 슈팅 (5)
        • 코틀린 (3)
        • 코루틴 (2)
        • Compose (1)
        • Compose UI (6)
        • Compose Dialog (8)
        • Compose Paging3 (11)
        • Compose State (2)
        • Util (1)
      • Github (3)
        • PR Template (2)
        • AI Code Review (1)
      • 리액트 (1)
        • NextJs (1)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Jetpack Compose
    OnBackPressedDispatcher
    Usecase
    sealed class
    멀티 모듈
    multi module
    MutableState
    코루틴
    enum class
    Dialog
    jsonadapter
    클린 아키텍처
    LazyRow
    dynamic json
    Gradle
    Github
    ai code review
    트러블슈팅
    코틀린
    recyclerview
    안드로이드
    ViewModel
    pager
    flow
    데이터 레이어
    Clean Architecture
    paging3
    pr template
    ScrollView
    UI Layer
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
코딩덕
[안드로이드 클린 아키텍처 시리즈] UI Layer 구현 3편 (with Jetpack Compose) #10
상단으로

티스토리툴바