Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Brunch Android Architecture

kakao
PRO
December 08, 2022

Brunch Android Architecture

#Android

브런치 안드로이드 앱의 아키텍처가 어떻게 바뀌었는지 소개하고, 현재 변경 중인 내용에 대해서 공유합니다.

발표자 : ayla.k
작가들의 창작 활동을 펼칠 수 있도록 브런치와 티스토리를 개발하고 있는 아일라입니다.

kakao
PRO

December 08, 2022
Tweet

More Decks by kakao

Other Decks in Programming

Transcript

  1. Copyright 2022. Kakao Corp. All rights reserved. Redistribution or public

    display is not permitted without written permission from Kakao. Brunch architecture 김현아 ayla.k 카카오 if(kakao)2022
  2. Brunch 소개 안드로이드 앱의 변화 과정 나아가는 방향

  3. Brunch 소개 안드로이드 앱의 변화 과정 나아가는 방향

  4. Brunch

  5. 작가가 지속적인 창작 활동을 펼칠 수 있는 환경을 만들고 세상에

    감동과 영감을 줄 수 있도록 기여한다. Brunch
  6. 우리는 좋은 글이 가지는 힘을 믿습니다. Brunch

  7. Brunch 90년생이 온다 어서오세요. 휴남동 서점입니다 젊은 ADHD의 슬픔

  8. Brunch 소개 안드로이드 앱의 변화 과정 나아가는 방향

  9. ૓೯ࢎ೦ 2018 2019 2020 2021 2022 2023 MVVM Java to

    Kotlin Clean Architecture Multi Module Hilt Rx to Coroutines Test Compose UseCase MicroService
  10. MVVM적용 Observe Data Activity ViewModel Data Manager

  11. MVVM적용 Fragment Request Change Data Change Activity ViewModel Data Manager

  12. MVVM적용 Request update Result Data Change Activity ViewModel Data Manager

  13. Controller Manager . . . Repository Repository 도입

  14. 1. Independent of Frameworks. 2. Testable. 3. Independent of UI.

    4. Independent of Database. 5. Independent of any external agency. Clean Architecture
  15. Clean Architecture Ui Entities Use Cases DB Server Repository Viewmodel

    Repository Impl Ui Interface Adapters Entities Application Business Rules G atew ays Enterprise Business Rules D evices W eb Use Cases Presenters Controllers External Interfaces DB Frameworks & Drivers
  16. 분리 App Presentation Item Domain Entity Data Model

  17. 분리 App DI Application Navigator Gradle Value Presentation Item View

    ViewModel Domain Entity UseCase Repository Interface Data Model Repository DB Server
  18. 분리 후의 data 흐름 Presentation Domain Data View ViewModel Mapper

    UseCase Repository Server Repository Impl Mapper
  19. 분리 후의 data 흐름 Presentation Domain Data View ViewModel Mapper

    UseCase Repository Server Repository Impl Mapper Click
  20. 분리 후의 data 흐름 Presentation Domain Data View ViewModel Mapper

    UseCase Repository Server Repository Impl Mapper Model
  21. 분리 후의 data 흐름 Presentation Domain Data View ViewModel Mapper

    UseCase Repository Server Repository Impl Mapper Entity
  22. 분리 후의 data 흐름 Presentation Domain Data View ViewModel Mapper

    UseCase Repository Server Repository Impl Mapper Item
  23. app ݽٕܻ࠙ app( + presentation) domain data app presentation domain

    data
  24. 6TF$BTF Ui Entities Use Cases DB Server Repository Viewmodel Repository

    Impl
  25. 6TF$BTF Ui Entities Use Cases DB Server Repository Viewmodel Repository

    Impl
  26. UseCase @HiltViewModel class WebViewViewModel @Inject constructor( private val adidRepository: ADIDRepository,

    private val localInfoRepository:LocalInfoRepository, private val cookieRepository: CookieRepository )
  27. UseCase @HiltViewModel class WebViewViewModel @Inject constructor( private val adidRepository: ADIDRepository,

    private val localInfoRepository:LocalInfoRepository, private val cookieRepository: CookieRepository ){ adidRepository.brunchADIDHeader?.let { header["BRUNCH-ADID"] = it } } interface ADIDRepository { var adInfo: AdInfo? val brunchADIDHeader: String? }
  28. UseCase @HiltViewModel class WebViewViewModel @Inject constructor( private val getBrunchADIDHeaderUsecase: GetBrunchADIDHeaderUsecase,

    private val getBrunchVersionUseCase: GetBrunchVersionUseCase, private val getCookieUseCase: GetCookieUseCase, )
  29. UseCase @HiltViewModel class WebViewViewModel @Inject constructor( private val getBrunchADIDHeaderUsecase: GetBrunchADIDHeaderUsecase,

    private val getBrunchVersionUseCase: GetBrunchVersionUseCase, private val getCookieUseCase: GetCookieUseCase, ) @BeforeEach fun setUp() { whenever(getBrunchADIDHeaderUseCase()).doReturn(adidHeader) whenever(getBrunchVersionUseCase()).doReturn(version) whenever(getCookieUseCase()).doReturn(cookie) viewModel = WebViewViewModel( getBrunchADIDHeaderUseCase, getBrunchVersionUseCase, getCookieUseCase ) }
  30. Brunch 소개 안드로이드 앱의 변화 과정 나아가는 방향

  31. ੉ۧѱ ҅ࣘ ߸҃ೞח ੉ਬ?

  32. 함께 자라기

  33. MicroService Architecture

  34. 브런치의 화면

  35. 현재의 모듈 구조 Presentation Domain Data 글 activity 글 viewModel

    작가 프로필 activity 작가 프로필 viewModel 글 조회 UseCase 프로필 조회 UseCase 작품 조회 UseCase 글 Respository 프로필 Repository 작품 Respository
  36. 바뀌는 모듈 구조 Presentation:Article 글 Activity 글 ViewModel 작가 프로필

    Activity 작가 프로필 ViewModel 글 조회 UseCase 프로필 조회 UseCase 작품 조회 UseCase Presentation:WriterPro fi le Domain:Article Domain:Pro fi le Domain:Magazine 글 Respository 프로필 Repository 작품 Respository Data:Article Data:Pro fi le Data:Magazine
  37. 빌드 속도

  38. 빌드 속도 Presentation:WriterPro fi le Presentation:Article App Domain:Magazine Domain:Pro fi

    le Domain:Article Data:Magazine Data:Pro fi le Data:Article Data:Article Domain:Article Presentation:Article App
  39. 분리의 편리함 implementation("com.github.android-alatan.lifecyclecomponents:lifecycle-handler-activity:$version") implementation("com.github.android-alatan.lifecyclecomponents:lifecycle-handler-impl:$version") implementation("com.github.android-alatan.lifecyclecomponents:result-handler:$version") implementation("com.github.android-alatan.lifecyclecomponents:bundle-collector:$version") implementation("com.github.android-alatan.lifecyclecomponents:request-permission:$version") implementation("com.github.android-alatan.lifecyclecomponents:back-key-handler:$version") implementation("com.github.android-alatan.lifecyclecomponents:router:$version") implementation("com.github.android-alatan.lifecyclecomponents:view-event-legacy-impl:$version")

    implementation("com.github.android-alatan.lifecyclecomponents:lazy-provider:$version") implementation("com.github.android-alatan.lifecyclecomponents:coroutine-api:$version") implementation("com.github.android-alatan.lifecyclecomponents:lifecycle-handler-annotations:$version") implementation("com.github.android-alatan.lifecyclecomponents:lifecycle-handler-api:$version") // prerequisite implementation(“com.google.android.material:material:${material_version}") // for compose implementation("com.github.android-alatan.lifecyclecomponents:provided-compose-local-api:$version") implementation("com.github.android-alatan.lifecyclecomponents:lifecycle-handler-compose-util:$version") implementation("com.github.android-alatan.lifecyclecomponents:lifecycle-handler-compose-activity-dagger:$version") implementation("com.github.android-alatan.lifecyclecomponents:composable-holder:$version") implementation("com.github.android-alatan.lifecyclecomponents:provided-compose-local-ksp:$version") implementation("com.github.android-alatan.lifecyclecomponents:view-event-compose-extension-api:$version") implementation("com.github.android-alatan.lifecyclecomponents:view-event-compose-extension-impl:$version") implementation("com.github.android-alatan.lifecyclecomponents:view-event-compose-impl:$version") implementation("com.github.android-alatan.lifecyclecomponents:lifecycle-handler-compose-activity:$version") . . .
  40. 분리의 편리함

  41. 이해도↑ 복잡도↓ 속도↑ 복잡도 문제↓

  42. 앱접근성 컴포즈 그리고… MVI 테스트

  43. Thank you