기본 디자인 패턴 (Common Design Patterns)
출처 : https://www.raywenderlich.com/18409174-common-design-patterns-and-app-architectures-for-android
Creational Patterns
객체 생성시 반복되는 코드를 간단하고 효율적으로 작성 및 생성하는 용도.
Builder
- 샌드위치 빵을 만드는 것과 유사하게 심플하게 객체를 생성.
- 예시 : AlertDialog.Builder
Dependency Injection
- 가구가 비치된 아파트로 이사하는 것과 같다?
- 새 객체는 객체 자체를 구성하거나 사용자활 필요가 없다.
- 예시 : 네트웍 클라이언트나 이미지 로더 등에서 SharedPreference 를 접근하는 경우가 많다. 이때 이 SharedPreference 를 activity 나 fragment 에 inject 시켜주면 바로 사용이 가능하다.
- DI를 도와주는 라이브러리로 Dagger2, Dagger Hilt, Koin 등이 있다.
Singleton
- 글로벌 액세스 포인트가 존재하며(어디서든 접근 가능), 단일 인스턴스 만 존재해야함을 명시.
- 네트웍 이나 디비 커넥션이 여러개 존재하면 문제가 발생될수 있으며, 이로인해 둘 이상의 인스턴스 생성을 제한 하려는 이유.
- 이 패턴은 이해하기는 쉽지만 남용과 남용으로 인핸 위험이 발생될 우려도 쉽다.
- 디자인 패턴을 이해하는 것도 중요하지만 다른 패턴을 사용하는 것이 안전하고 유지보수가 더 쉬울 수도 있다.
Factory
- 객체의 생성로직을 관리, 팩토리 클래스는 인스턴스로 만들 객체를 제어.
- 이 패턴은 많은 공통 객체를 생성하고 다룰때 유용.
- 잘못 사용하면 과도한 객체로 인해 팩토리 클래스가 커질수 있다.
Structural Patterns
구조패턴을 사용하면 클래스와 객체의 로직과 구조에 대하여 보다 쉽게 이해 할수 있다. 안드로이드 에서는 Adapter 와 Facade 패턴이 자주 사용된다.
Adapter
- 클래스의 인터페이스를 클라이언트가 예상하는 인터페이스로 변환하여 호환되지 않는 두 클래스가 함께 작동 할 수 있다.
- 예시 : RecyclerView 사용을 위해 로직에서 RecyclerView.Adapter 를 이용.
Facade
- 다른 인터페이스 세트를 더 쉽게 사용할 수 있는 상위 레벨 인터페이스를 제공.
- 각 객체가 내부에서 일어나는 일에 대해 덜 알수록 향후 앱의 변경사항을 관리하기가 쉬워짐
- 예시 : Retrofit 의 Api 생성, 호출 방식
Decorator
- 런타임에 기능을 확장하기 위해 객체에 추가 책임을 동적으로 연결
- 예시 :
Composite
- 균일한 객체로 구성된 나무와 같은 구조를 표현하려는 경우 컴포지트 패턴을 사용.
- 이 패턴은 두개의 객체를 가질수 있음 : 컴포지트(composite), 리프(leaf).
- 컴포지트 객체는 추가 객체를 가질수 있지만, 리프 객체는 현재 객체가 마지막.
- 예시 :
Behavioral Patterns
이 패턴을 통해 다양한 앱, 모듈, 객체등의 기능에 대한 책임을 할당 할 수 있다.
Command
- 커맨드패턴을 사용하면 수신자를 몰라도 요청을 발생 할 수 있다.
- 요청을 어떻게 처리하고 완료하는지는 완전히 분리되어 있는 메카니즘.
- 예시 : 이벤트버스
- 좋은 테스트가 준비되어 있지 않다면 이벤트를 트래킹하는데 어려움이 있을수 있다.
Observer
- 객체 간의 1:N 의존성을 정의할수 있다.
- API 호출과 같은 불확실한 응답시간에 대한 작업에 사용할때, 사용자 입력을 받아서 처리할때 유용하다.
- 예시 : RxAndroid 를 이용한 구현 패턴.
- Observable 객체를 통해 값을 방출(emit)하고, Subscriber를 통해 방출될 값을 listen 하고 처리.
Strategy
- 기능이 다른 동일한 특성의 여러 객체가 있는 경우 stratege 패턴을 사용.
- 예시 :
State
- 객체의 내부 상태가 변경되면 객체의 상태가 그에 따라 동작을 변경한다.
- 예시 :
App Architectures
플랫폼과 상관없이 어떤 애플리케이션에서도 사용 가능. 앱 아키텍쳐를 사용하면 쉽게 테스트 할수 있으며, 기능 확장도 쉬워지며 분리된 코드를 작성 할 수 있다. 아키텍쳐는 다음과 같은 부분들에서 코드의 구성을 나타낸다.
- 각 클래스들의 책임과 역할.
- 패키지 구조.
- 예시 : 네트워크 호출, 응답, 에러.
Model View Controller
- 가장 인기 있는 아키텍쳐 패턴중 하나.
- 안드로이드에서는 이 방식으로 프로젝트를 구현 하는것이 쉽다.
- Model
- 데이타 클래스들, 실제 세계를 모델링한 클래스들.
- 코틀린에서는 Data class.
- 자바에서는 POJO(Plain Old Java Object). - View
- UI 화면을 구성하는 클래스들.
- xml, View 등등. - Controller
- Model 과 View 사이의 연결.
- view 를 업데이트, 사용자의 입력을 통해 model 변경. - 3가지로 클래스를 나누고 분리하면 재사용 가능하게 만드는데 도움이 된다.
Model View ViewModel
- 헷갈리는 이름으로 지정된 이 아키텍처 패턴은 MVC 패턴과 유사하다.
- Model 과 View 컴포넌트는 MVC 에서와 동일한 역할을 한다.
- ViewModel 객체는 Model 과 View 를 연결해주지만 Controller 컴포넌트와는 다르게 동작한다.
- ViewModel 객체에는 View 에 대한 명령들이 존재하고, 이 View 들을 Model에 binding 한다.
- Model 이 업데이트 되면, 해당 View 가 데이터 바인딩을 통해 업데이트 된다.
- 마찬가지로, View 에 이벤트가 발생되었을 때는 반대방향으로 바인딩이 작동하여 Model을 업데이트 한다.
- MVVM 패턴은 인기가 높아지고 있지만 여전히 디자인 패턴들 중에서는 최근에 추가된 축에 속한다.
- 구글도 이 패턴을 Android Architecture Components 를 통해 추천 하고 있다.
Clean Architecture
- 클린아키텍처는 아키텍처 그 자체 보단 컨셉이다.
- 앱의 다양한 계층이 서로 통신하는 방법들에 대한 전반적인 아키텍처를 묘사한다.
- MVC 와 MVVM 또한 클린아키텍처 에서 외부의 프리젠테이션과 UI 레이어에 존재한다.
- 자세한 정보는 https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html 에서 확인 가능.
절대적으로 하나만이 좋은 아키텍처라는 생각은 하지 않는다. 코드도 시간이 흐름에 따라 나이가 들고 로직이 복잡해 지면서 지속적으로 유지 & 보수 & 리팩토링이 필요하듯이 아키텍처 또한 각각의 시나리오와 상황에 맞춰서 1개 또는 2개 이상이 하나의 애플리케이션에 복합적으로 사용할수 있다고 생각한다.
현재 회사의 메인 프로젝트의 안드로이드 플랫폼에서는 MVP 아키텍처 패턴을 사용하고 있다. 비지니스 로직의 명확한 분리와 유닛테스트의 용이성 때문에 MVP 패턴을 채택하여 사용하고 앱 전반에 적용하고 있다. 시대가 MVVM 아키텍처 패턴을 선호하고 트렌드에 있다보니 관심이 생겨 Android Architecture Components 와 함께 MVVM 아키텍처 패턴의 도입을 검토 하고 best pratics 를 만들어 보려고 한다.
기본적인 디자인 패턴을 숙지하면서 실무에 잘 녹여서 사용해 보고 장단점을 느껴보자!