$30 off During Our Annual Pro Sale. View Details »

Brunch Android Architecture

kakao
December 08, 2022

Brunch Android Architecture

#Android

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

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

kakao

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

    View Slide

  2. Brunch 소개


    안드로이드 앱의 변화 과정


    나아가는 방향

    View Slide

  3. Brunch 소개


    안드로이드 앱의 변화 과정


    나아가는 방향

    View Slide

  4. Brunch

    View Slide

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


    세상에 감동과 영감을 줄 수 있도록 기여한다.
    Brunch

    View Slide

  6. 우리는 좋은 글이 가지는 힘을 믿습니다.
    Brunch

    View Slide

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

    View Slide

  8. Brunch 소개


    안드로이드 앱의 변화 과정


    나아가는 방향

    View Slide

  9. ૓೯ࢎ೦
    2018 2019 2020 2021 2022 2023
    MVVM
    Java to Kotlin
    Clean Architecture
    Multi Module
    Hilt
    Rx to Coroutines
    Test
    Compose
    UseCase
    MicroService

    View Slide

  10. MVVM적용
    Observe Data
    Activity ViewModel
    Data


    Manager

    View Slide

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


    Manager

    View Slide

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


    Manager

    View Slide

  13. Controller


    Manager


    .


    .


    .
    Repository
    Repository 도입

    View Slide

  14. 1. Independent of Frameworks.


    2. Testable.


    3. Independent of UI.


    4. Independent of Database.


    5. Independent of any external agency.
    Clean Architecture

    View Slide

  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

    View Slide

  16. 분리
    App Presentation
    Item
    Domain
    Entity
    Data
    Model

    View Slide

  17. 분리
    App
    DI


    Application


    Navigator


    Gradle Value
    Presentation
    Item


    View


    ViewModel
    Domain
    Entity


    UseCase


    Repository Interface
    Data
    Model


    Repository


    DB


    Server

    View Slide

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


    Impl
    Mapper

    View Slide

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


    Impl
    Mapper
    Click

    View Slide

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


    Impl
    Mapper
    Model

    View Slide

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


    Impl
    Mapper Entity

    View Slide

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


    Impl
    Mapper
    Item

    View Slide

  23. app
    ݽٕܻ࠙
    app( + presentation)


    domain


    data
    app


    presentation


    domain


    data

    View Slide

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

    View Slide

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

    View Slide

  26. UseCase
    @HiltViewModel


    class WebViewViewModel @Inject constructor(


    private val adidRepository: ADIDRepository,


    private val localInfoRepository:LocalInfoRepository,


    private val cookieRepository: CookieRepository


    )

    View Slide

  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?


    }

    View Slide

  28. UseCase
    @HiltViewModel


    class WebViewViewModel @Inject constructor(


    private val getBrunchADIDHeaderUsecase: GetBrunchADIDHeaderUsecase,


    private val getBrunchVersionUseCase: GetBrunchVersionUseCase,


    private val getCookieUseCase: GetCookieUseCase,


    )

    View Slide

  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


    )


    }


    View Slide

  30. Brunch 소개


    안드로이드 앱의 변화 과정


    나아가는 방향

    View Slide

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

    View Slide

  32. 함께 자라기

    View Slide

  33. MicroService Architecture

    View Slide

  34. 브런치의 화면

    View Slide

  35. 현재의 모듈 구조
    Presentation Domain Data
    글 activity
    글 viewModel
    작가 프로필 activity
    작가 프로필 viewModel
    글 조회 UseCase
    프로필 조회 UseCase
    작품 조회 UseCase
    글 Respository
    프로필 Repository
    작품 Respository

    View Slide

  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

    View Slide

  37. 빌드 속도

    View Slide

  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

    View Slide

  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")


    .


    .


    .


    View Slide

  40. 분리의 편리함

    View Slide

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

    View Slide

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

    View Slide

  43. Thank you

    View Slide