
- 손으로 써야 외워지는 병이 있나부다. 공부는 역시 아날로그식으로 해야돼..,,,.,
✅MVC

VIEW
: Activity, Fragment
Model
: Room이나 서버에서 데이터 처리하는 로직(Call해서 데이터 가져오기 등)
Controller
: 사용자의 이벤트를 처리하고 데이터를 xml에 바인딩해주는 역할
- 화면에 보이는 애는 VIEW가 데이터는 MODERL이 그 사이에서 controller가 컨트롤함
- setOnClickListener같은 사용자의 Action이 Controller에 들어옵니다
- Controller는 Model을 나타내줄 View를 선택합니다
- View는 Model을 이용하여 화면을 나타냅니다
- 단점
- 하나의 파일에 이벤트 처리, 서버 통신처리 등의 컨트롤하는 로직이 전부 들어가니까 복잡합니다
- 서버랑 통신할때의 call하는 로직을 activity,fragment에서 처리했었음 근데 서버 통신은 '데이터 처리' 작업의 일종인데 이걸 view에서 처리하고 있던 것입니다 즉, Model이 해야하는 일을 View에서 하면서 Model과 View사이 의존성이 생깁니다. 이는 객체지향 관점에서도 좋은 현상이 아닙니다
- Model에서 뭐 하나가 수정되면 View에서도 전부 수정해야하는 문제가 발생합니다
✅MVP

view야 인풋 들어오면 무조건 나한테 말해줘!
그리고 이거 그려줘~
- View가 Presenter에게 요청을 보내면 Presenter가 받아들여서 Model에게 이 데이터 가져다달라고 요청->받아온 데이터 처리->Presenter가 View에게 해당 데이터를 반환
- MVC는 View내부에서 데이터 요청, 이벤트 모두 처리했는데 mvp는 데이터 요청 작업을 View가 Presenter에게 요청해서 Presenter가 하는 방식입니다
- 장점
- presenter는 인풋 아웃풋 처리를 담당하는데 컨트롤러에서 화면만 띄어낸 것입니다 view와 presenter는 1:1 관계고 뭔가 view로 이벤트 들어오면 presenter가 1:1로 담당하고 presenter는 이제 ui랑 상관없는 것이 되면서 test가 가능해집니다
- 즉 view와 Model의 의존성이 없습니다(Presenter를 통해서만 데이터 전달 받으니까)
- 단점
- 근데 view하나 만들때마다 presenter도 같이 만들어야하는 문제가 발생합니다
- 비슷한 화면을 처리하는데 비슷한 로직을 구현해야함 presenter를 매번 만들어야 합니다
로직이 비슷한데 view에서 들어온 데이터를 presenter가 공통적인 로직을 수행해서 view한테 전달해야합니다
- 무조건 view는 presenter을 거쳐서 모델에 무조건 요청해야하기때문에 view와 presenter사이 의존성이 높습니다
✅MVVM

Model아 데이터 있어? 그럼 ViewModel이 가져와서 가공하고 처리할꺼야. View는 ViewModel을 쨰려보면서 알아서 화면 그려!!
Model
: 어플리케이션에서 사용되는 데이터와 그 데이터를 처리하는 부분(서버통신, 로컬db처리)
View
: 사용자에게 보여지는 UI
ViewModel
: View를 나타내 주기 위한 Model이자 View를 나타내기 위한 데이터 처리를 하는 부분
✔MVVM을 왜 쓸까?
- 구글에서 공식적으로 MVVM을 사용하기 쉽도록 제공하는 AAC들이 있습니다. 그래서, 아키텍처를 쓸때 대표적인게 MVVM입니다
✔동작
- 모든 입력(Input)들은 View로 전달됩니다.
- View는 ViewModel한테 데이터를 요청하거나 ViewModel은 View가 입력 들어왔다고 알려주면 해당하는 Presentation Logic을 처리합니다
(Presentation Logic : 실제 눈에 보이는 GUI 화면을 구성하는 코드를 말하며 여기서는 실제로 화면에 보여지는 데이터를 처리하는 로직을 말합니다.)
- View Model은 View에게 데이터 전달하는게 아니라 View가 View Model을 관찰할 뿐 View에게 관여안합니다(MVP는 Model에게 받아온 데이터 처리하고 View에게 전달까지 했다!)
✔특징
- ViewModel은 View를 참조하지 않기 때문에 독립적입니다
(ViewModel과 View는 1:n 관계다.)
- 따라서 View가 이용할 ViewModel을 선택해 바인딩하여 업데이트를 받게 됩니다.
(Command 패턴이나 Data Binding을 이용하여 V-VM간 의존성을 없앨 수 있다.)
- Command 패턴:View에 입력이 들어오면 커맨드 패턴으로 ViewModel에 명령합니다
- Data Binding: ViewModel의 값이 변하면 자동으로 UI가 업데이트됩니다
- Model이 변경되면 해당하는 ViewModel을 이용하는 View가 자동으로 업데이트됩니다.
- ViewModel은 View를 나타내 주기 위한 Model을 처리하는 로직인 Presentation Logic을 처리합니다.
- 여러 화면이 있더라도 비슷한 데이터를 가진게 아니들이면 같은 뷰모델을 사용할 수 있습니다
- 뷰모델은 특정 뷰랑 연관이 되는게 아니라서 1:다의 관계가 가능합니다
✔장점
- View와 Model 사이의 의존성이 없습니다
- View와 ViewModel 사이의 의존성 또한 크지 않습니다
- 각 View, ViewModel, Model 부분은 독립적이어서 모듈화하여 개발 가능합니다
✔단점
✅AAC
- 깊게 파고들면 정통적인 MVVM구조는 AAC를 사용하여 구현하는 것과 거리가 멀 수도 있습니다. 하지만 AAC를 쓰게되면 MVVM 아키텍쳐를 비교적 쉽게 구현할 수 있게 되기 때문에 AAC를 바탕으로 MVVM아키텍처를 공부하는 것입니다.
✔AAC?
Android Architecture Components
의 약자로, 테스트와 유지관리가 쉬운 앱을 디자인하도록 돕는 라이브러리 모음임(JetPack중에서도 아키텍쳐 디자인을 편하게 해주기 위한 라이브러리입니다)
- AAC를 사용하는 이유는 아이텍쳐를 쉽게 구현하기 위해서 사용합니다->우리는 AAC를 이용해서 MVVM아키텍쳐(데이터,뷰,데이터 처리 로직을 분리하기 위해 패턴)를 구현할 것입니다
- 즉, AAC를 이용해 데이터,뷰,데이터 처리 로직같은 관심사들을 분리해봅시다!
✔AAC에는 뭐가 있을까?
1. ViewModel
- 독자적인 라이프사이클을 가지고 있습니다
- View와 Model사이를 중재하며 데이터 처리 로직을 중재하며 살아있는 독자적 생명주긴 가진 클래스입니다. 데이터 처리하는 일종의 공간역할을 합니다
- 라이프사이클을 고려하여 UI관련 데이터를 저장하고 관리할 수 있도록 설계합니다
2. LiveData
- 관찰이 가능한 (Observable) 데이터 홀더 클래스
- MVVM에서는 View Model이 Model에서 받아온 데이터를 가공 처리할 뿐이라고 했습니다!. View가 ViewModel의 데이터를 관찰하기 위해서 관찰가능한 데이터의 역할을 해주는 것입니다
3. DataBinding
- 레이아웃의 UI구성요소를 앱의 데이터와 결합할 수 있도록 지원하는 라이브러리입니다
4. Room
- SQLite를 쉽고 편리하게 사용할 수 있도록 지원합니다
✅ViewModel
✔ViewModel?

-
ViewModel은 라이프사이클을 고려하여 UI관련 데이터를 저장하고 관리할 수 있도록 설계합니다
-
UI를 관리하는 UI Controller에 과도한 역할을 부여하면 과부하가 올 수 있고 테스트 또한 어려워지기 때문에, UI관리 시 View Data 소유권을 분리하는 방법이 더 쉽고 효율적이라는 점을 이용한 것이 ViewModel입니다
-
주의해야할 점은 activity나 fragment보다 생명주기가 길다 activity가 만들어지고 onDestroy가 호출되어도 살아있습니다
-
view에서 이루어졌던 서버통신이나 데이터처리 로직들을 굳이 view에서 하지말고 viewmodel에서 하고 , viewmodel안에 데이터 처리 로직들이 있으니까 activity에서는 데이터 처리 로직들을 생명주기 변해도 상관할필요가 없습니다. 라이브데이터로 viewmodel안의 데이터를 관찰하니까 activity가 죽어도 viewmodel은 살아있으니까 activity에서는 상관 꺼도되는게 viewmodel을 사용하는 이유입니다
즉 데이터 처리 로직 분리할꺼야!=viewmodel씀
-
viewmodelprovider은 viewmodel을 생성하는 일종의 클래스다. viewmodelprovider는 viewmodel에 lifecycle을 전달하며 viewmodel은 lifecycle이 끝날때까지 메모리에 남아있습니다
-
viewmodelprovider안에는 첫번째로는 현재 뷰모델을 만드는 view가 어떤 것이니? viewmodel을 만들수 있는 view로는 activity아니면 fragment가 있습니다
-
viewmodel을 만드는거 누구라는거 넣어주고, fragment가 주인이면 방법이 2가지임 이거 내가 알아볼 것입니다
-
만약 액티비티가 주인이면 이거에 맞게 viewmodel의 라이프사이클을 지정해주면 생성되어서 동작합니다
✔ViewModel 주의점
-
ViewModel안에서는 절대 view에 대한 작업 금지입니다!(ex.binding가져오기, 클릭리스너 달기)
- 아키텍쳐 관점에서도 안맞고, AAC의 구조상 VIEW객체 가져오게 될경우 ViewModel은 Activity,Fragment보다 생명주기가 더 긴데 뷰 객체 가져와서 쓰면 뷰는 죽었는데 ViewModel이 뷰 가지고있으면 안쓰는 뷰인데 메모리 차지하니까!
-
절대로 context의 레퍼런스를 가지는 객체(ex.activity, fragment, view)를 viewModel에 집어넣으면 안됩니다. 집어넣게 될 경우 memory leak 현상이 발생합니다
-
ViewModel은 activity, fragment보다 더 긴 생명주기를 가지고 있기 때문에 configuration이 바뀌었을 경우 activity,fragment는 destroy되고 recreate됩니다
-
이때 생성된 새로운 instance는 ViewModel의 동일한 instance를 가지게됩니다. 따라서 ViewModel에 Activity,Fragment에 대한 참조를 유지하는 것은 memory leak 현상이 일어나고 최악의 경우 crash가 날 수 있습니다
✅LiveData
컴포넌트 생명주기가 변화하면 라이브데이터가 옵져버를 통해 관찰하고 옵져버 안에잇는 작업들을 실행해줍니다.
무조건 최신 데이터만 반환한다는 특징이 있습니다.
- LiveData는 관찰이 가능한(Observable) 데이터 홀더 클래스입니다.
- Activity, Fragment, Service와 같은 컴포넌트의 생명주기를 인식하며 생명주기 인식을 통해 활성 상태에 있는 컴포넌트의 Observer만 업데이트합니다.
- Ovserver는 LiveData의 관찰자입니다
Ovserver의 생명주기가 STARTED, RESUMED상태이면 LiveData는 Observer를 활성 상태로 간주하여 업데이트 정보를 알립니다
✔ MVC

✔ ViewModel로 데이터 관리


- counter을 ViewModel에 넣어서 사용하면 ViewModel은 컴포넌트보다 생명주기가 길기 때문에 화면이 회전하는 등의 onDestroy가 호출되어도 데이터가 초기화되지 않습니다
✔ ViewModel로 데이터 관리+LiveData


- LiveData에 Observe를 달아서 관찰 가능한 데이터로 만들면 setOnClickListener에서 이벤트 클릭 로직을안써도 라이브데이터가 업데이트 될때마다 observe에 의해 자동으로 감지되어 데이터 로직이 실행됩니다
✔ LiveData+DataBinding사용



- view가 ViewModel을 구독하도록 databinding시켜서 알아서 데이터 변화를 감지해 view에 업데이트 되도록 한다 이때 view는 activity의 생명주기를 알고있어야 하기 때문에 setLifecyclerOwner로 생명주기를 전달합니다
- ViewModel을 반드시 상속받아야 LiveData를 사용할 수 있는거 아님! LiveData를 사용하는 이유는 결국 데이터가 생명주기를 따라서 자동으로 업데이트 되도록 하는거니까!
- ViewModel은 데이터가 onDestroy되어도 초기화되지 않도록 하는 컨테이너 역할이라고 보면됩니다
- ViewModel과 LiveData의 목적은 다르지만 같이 사용해서 업데이트, 생명주기 편의성을 도모합니다