일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 코루틴
- relay
- architecture
- boj
- 쿠링
- pandas
- TEST
- Gradle
- Codeforces
- ProGuard
- android
- Rxjava
- 암호학
- AWS
- Hilt
- 프로그래머스
- GitHub
- 백준
- Kotlin
- Python
- Coroutines
- livedata
- Compose
- MiTweet
- androidStudio
- 코드포스
- MyVoca
- textfield
- Coroutine
- activity
- Today
- Total
이동식 저장소
Android Architecture Layers - 0. Overview 본문
다음 문서를 읽고 정리한 글임을 밝힙니다. 원문을 읽을 때는 영문으로 읽기를 권합니다.
아키텍처?
아키텍처란 무엇인가? 개발자 입장에서 아키텍처는 프로그램의 서로 다른 부분을 연결하여 매끄럽게 동작하게 만들기 위한 구조를 말한다. 모바일, PC, TV 등 타겟에 따라 서로 다른 아키텍처가 적용되지만, 프로그램을 설계할 때 지켜야 할 기본적인 원칙은 동일하다.
Hello World 프로그램을 작성하는 사람이 아니라면 모든 코드를 하나의 파일에 작성하는 사람은 흔치 않을 것이다. 물론 그렇게 하는 것이 이득일 수도 있으나, 어느 정도 큰 프로젝트에서는 코드를 여러 파일로 나누어 작성한다. 보통 코드 파일을 나누는 기준은 책임(responsibility)이다. 하나의(또는 비슷한) 책임을 맡은 코드 조각을 하나의 파일로 묶어서 작성하는 것이다. 객체 지향을 지원하는 언어라면 클래스에 묶어서 작성할 수도 있다.
이건 프로그램의 최하위 구성 요소인 코드 얘기이고, 조금 위로 올라와 보자. 말했다시피 소프트웨어는 맡은 기능에 따라 나눌 수 있다. 예를 들어 UI를 보여주는 코드와 데이터를 처리하는 코드, 네트워크 통신을 담당하는 코드는 모두 별개로 작성되어야 한다.
코드를 나누기만 하면 되는가? 레고 블럭에 볼록 튀어나온 부분이 없다면 여러 블럭을 결코 결합할 수 없을 것이다. 소프트웨어를 완성하려면 여러 개로 나뉘어진 코드 조각을 유기적으로 연결해야 한다. 그냥 연결하면 안 되고, 최대한 신경써서 연결해야 한다. 마구잡이로 연결하면 어떻게 되냐고? 궁금하면 자신이 프로그래밍을 처음 배울 때 작성한 코드를 읽어보고, 그 코드에 아예 새로운 기능을 쉽게 추가할 수 있는지 되돌아 보자. 답이 쉽게 나온다면 당신은 born-to-be 아키텍처 고수이므로 이 글을 읽을 필요가 없다.
어쨌든, 이처럼 여러 코드 조각을 연결하는 방법을 아키텍처라고 한다. 그렇다면 어떤 아키텍처가 좋은 아키텍처인가? 소프트웨어의 여러 부분을 어떻게 연결해야 잘 만들었다고 소문이 날까? 구체적으로 구현하는 방법은 다르겠지만, 공통적으로 고려해야 할 사항은 다음과 같다.
의미를 정확히 전달하기 위해 원문 그대로 작성한 부분이 있음을 알린다.
Separation of Concern
C언어를 처음 배우던 시절이 생각난다. 그때 작성하던 코드는 기껏해야 20줄 정도였으니, 오히려 main에 모두 적는 것이 효율적이었다. 하지만 내 단어장 앱 ``MyVoca``은 대략 1만 5천 줄 이상의 코드로 작성되었다. 하나의 파일에 1만 5천 라인을 작성할 수 있을까?
물론 세상에 안 되는 건 없다. 하지만 나를 포함하여 많은 사람들은 코드를 여러 부분으로 나누어 테스트 가능성과 가독성 향상 등의 이점을 누린다. 코드는 맡은 일에 따라 적절히 나뉘어야 한다.
UI와 데이터를 분리하기
나는 UI와 데이터의 관계를 이렇게 생각한다.
UI는 데이터의 표현이다!
UI는 데이터를 사용자에게 표현하는 일에만 집중해야 한다. 이렇게 생각하면 데이터 로직을 UI로부터 분리할 수 있고, 따라서 로직의 재사용성과 테스트 가능성이 향상된다.
내 생각에 Separation of Concern과 UI와 데이터 분리는 어느 분야에서나 적용할 수 있는 가장 기본적인 원칙이다. 이제 안드로이드를 개발한 구글은 어떤 아키텍처를 추천하는지 알아보자.
구글이 추천하는 아키텍처
이제부터 설명할 아키텍처는 대부분의 소프트웨어에 널리 적용될 수 있는 범용 아키텍처이다. 자신의 상황에 맞게 변형하여 적용하자.
앱에는 최소한 두 개의 레이어가 존재해야 한다.
- UI 레이어는 데이터를 사용자에게 보여준다.
- Data 레이어는 비즈니스 로직을 따라 데이터를 만들고, 처리하고, 저장한다.
필요한 경우 Data 레이어를 추상화하는 Domain 레이어를 추가할 수 있다. Domain 레이어에서는 Data 레이어를 use case 단위로 추상화할 수 있다.
UI 레이어
UI 레이어는 데이터를 화면에 보여주고, 사용자와 소통하는 역할을 맡는다. 구체적으로는 실제로 화면을 그리는 UI element와 UI가 그릴 데이터를 보관하는 State holder로 나눌 수 있다. Jetpack Compose UI를 공부한 사람이라면 쉽게 이해할 수 있을 것이다.
Data 레이어
Data 레이어는 앱의 비즈니스 로직을 구현한다. 비즈니스 로직이란 앱이 데이터를 생성하고, 처리하고, 저장하는 방법을 의미한다.
Data 레이어는 0개 이상의 data source를 포함하는 repository로 구성된다. Repository는 서로 다른 data source를 약간 추상화하고 제어하는 역할을 맡는다. 예를 들어 서버로부터 지도 데이터를 받아오는 ``NetworkMapDataSource``를 ``MapDataRepository``로 추상화할 수 있다.
Repository는 다음의 역할을 맡는다.
- 앱의 나머지 부분에 데이터를 추상화하여 제공한다.
- 모든 데이터의 single source of truth가 된다.
- 여러 data source 사이의 갈등과 분란을 조정한다
- 비즈니스 로직에 따라 데이터를 처리한다.
하나의 Data source는 단 하나의 source(로컬 DB, 네트워크 서버 등)와 상호작용해야 한다. 앱의 가장 밑 부분에서 데이터 통신만을 담당하는 것이다.
Domain 레이어 (없어도 됨)
Domain 레이어는 UI와 data 레이어 사이에서 복잡한 비즈니스 로직을 추상화한다. 비즈니스 로직이 간단하다면 굳이 필요없는 부분이지만, 상황과 선호에 따라 domain 레이어를 추가할 수 있다.
예를 들어, 여러 개의 ``ViewModel``이 하나의 작업을 반복해서 호출한다면 해당 작업을 use case로 추상화하여 나타낼 수 있다. Utility 함수로 뺄 수도 있지만..
코드 간의 의존성 관리하기
소프트웨어에서 말하는 의존성은 어떤 클래스가 임무를 수행하기 위해 다른 클래스의 도움을 받는 상황을 말한다. 의존성을 관리하는 다양한 패턴이 존재하지만, Android에서는 Dependency Injection(DI) 패턴을 가장 많이 사용한다.
DI를 적용하면 클래스가 필요한 의존성 객체를 자동으로 생성하여 얻을 수 있다. 생성자를 명시적으로 호출하지 않아도 객체를 사용할 수 있는 것이다. 모호하게 들린다면 직접 DI를 공부해 보자. 그럴 만한 가치가 차고 넘치는 개념이다.
여담으로 DI를 번역하면 의존성 주입이 되는데, 영 어색해서 나는 DI라고 부르는 편이다.
고려할 사항
소프트웨어를 작성할 때 고민해야 할 점을 작성해 보았다.
Android 클래스를 최대한 배제하자
Android 클래스에 의존하는 코드는 Windows 등 다른 플랫폼에서 재사용하기 극히 어렵다. UI 레이어에서는 당연히 Android 클래스를 사용해야 하지만, 재사용될 여지가 있는 data 레이어는 최대한 언어의 기능만 사용해 보자.
앱의 본질을 고민하자
특별한 이유 없이 남들이 작성한 코드를 굳이 다시 쓸 필요는 없다. 대신 이 앱이 왜 존재해야 하는지, 어떤 역할을 맡아야 하는지 고민하자. 예를 들어 단어장 앱 ``MyVoca``의 핵심 기능은 단어를 추가하고 저장하는 것이다. 따라서 단어 저장과 관련된 data 레이어를 특히 신경써서 작성하였다.
Don't reinvent the wheel.
지름길을 택하지 말자
여기서 말하는 지름길은 당장 결과물을 만들기 위해 성능, 가독성, 독립성 등 앱의 핵심적인 가치를 해치는 일을 말한다. 당장 10분 뒤에 제출할 과제가 아니라면, 급할수록 돌아가라! 미래의 확장성과 구조를 해치는 코드는 당장 치워버려야 한다.
가장 지키기 어려운 원칙이다. 스스로에게 매일같이 하는 말이지만, 그래도 어렵다..
'Primary > Android' 카테고리의 다른 글
Android Architecture Layers - 2. Domain (0) | 2022.06.18 |
---|---|
Android Architecture Layers - 1. Data (0) | 2022.06.15 |
[Android] Application 범위에서 코루틴을 실행하고 싶다면 (0) | 2022.06.02 |
[Android] Baseline Profile wasn't successfully installed (1) | 2022.06.01 |
Android Studio에서 디바이스의 화면 캡쳐하기 (0) | 2021.09.29 |