오늘은 어제 궁금했던 DataSource 클래스에 대해서 다시 공부해보았다.
class DataSource {
companion object {
private var INSTANCE: DataSource? = null
fun getDataSource(): DataSource {
return synchronized(DataSource::class) {
val newInstance = INSTANCE ?: DataSource()
INSTANCE = newInstance
newInstance
}
}
}
fun getItemList(): MutableList<MyItem> {
return itemList()
}
}
class DataSource는 다음과 같이 작성했다.
- 객체의 인스턴스는 메모리의 힙 영역에서 할당이 되는데 만약 n개의 activity에서 호출이 된다고 하면 매번 새로 할당하여 리턴하면 비효율적이기 때문에 싱글톤 패턴으로 작성하여 한번만 할당되고 사용할 수 있도록 하려고 클래스 인스턴스를 한개만 만들어서 어떤 곳에서 호출이 되도 return 할 수 있도록 만들어 준 것이었다.
- companion object 블럭 안에 instance를 작성하면 어디에서나 접근가능하다.
- synchronized는 스레드 세이프할 수 있으므로 다중 스레스 환경에서 객체의 일관성을 보장할 수 있다.
- 이렇게 class DataSource를 작성하면 하나의 힙 영역에 인스턴스를 할당하여 효율적으로 메모리 관리를 할 수 있다고 말씀해주셨다!
여기서 힙 영역이란?
메모리 영역은 4가지 영역으로 분류가 가능한데 4가지 영역은 Code, Data, Stack, Heap이다.
Code : 실행할 프로그램의 코드가 저장되는 영역으로 CPU는 해당 영역에 저장된 명령을 하나씩 가져가 처리하게 된다.
Data : 우리가 작성한 코드에서 전역변수, 정적변수 등이 할당되는 공간으로 전역변수 같은 경우 main 함수 이전에 선언되므로 main 함수가 호출되기 이전에 Data 영역에 할당되고 해당 변수들은 프로그램이 끝날 때까지 메모리에 남아있다.
Data 영역은 두가지로 구분할 수 있는데 초기화된 변수 영역인 .data와 초기화되지 않은 변수 영역인 .bss로 나눌 수 있다.

다음과 같이 전역변수의 초기값이 있느냐 없느냐에 따라 구별되는 것으로 초기화된 x는 .data 영역으로 초기화되지 않는 전역변수 y는 .bss 영역에 할당된다.
Stack : Stack 영역은 함수 호출 시 생성되는 지역변수, 매개변수가 저장되는 영역으로 프로그램이 자동으로 사용하는 임시 메모리 영역이다. Stack 영역에서 데이터가 들어가고 나오는 방식에 대해서는 PUSH, POP 방식 그리고 LIFO(선입후출)로 설명할 수 있다.
데이터가 저장될 때 PUSH, 데이터를 빼낼 때 POP 그리고 main -> fun1 -> fun2 순서로 PUSH가 되었을때 POP될 때는 늦게 쌓인 fun2 -> fun1 -> main 순으로 되는 것이 LIFO(선입후출) 방식이다.
Heap : Heap 영역은 Stack 영역과 비슷하지만 사용자에 의해 관리되는 임시 메모리 영역이다. 즉, 사용자가 필요에 의해 동적으로 메모리를 할당할 때 사용되는 영역이다.
Stack vs Heap
Stack은 프로그램에 의해 자동으로 관리되는 정적할당영역이며 Heap 영역은 필요에 따라 사용자에 의해 관리되는 동적할당영역이다.
정적할당 되는 Stack 영역의 경우 설계자가 Code를 짜고 Compile을 할 때(Compile Time) 그 크기가 결정이 되지만 동적할당 되는 Heap 영역의 경우 Compile할 때가 아닌 이후 실제 프로그램이 동작할 때(Run Time) 크기가 결정이 된다.
MVC 패턴은 액티비티에 data list를 세팅 및 전달 해주고 UI Component에 값을 뿌려주는 방식이다. 이때까지 사용한 방식이 MVC 패턴이라고 할 수 있다.

출처 : 스탠다드반 강의자료
MVC 패턴도 구현이 잘 되지만 단점이 있는데 복잡한 앱일수록 액티비티가 수행하는 기능이 많아지면서 코드 수가 증가해 유지보수가 어려워진다. 현업 시 하나의 기능을 추가 및 수정할 때 코드가 연쇄적으로 연결되어 있어 전체를 고쳐야하는 상황이 발생할 수 있다.
액티비티에서 수행하는 기능이 많은 MVC 패턴은 액티비티가 Model, View의 역할을 다 수행하는데 SharedPreference(데이터 처리)는 Model이 View(UI 처리)는 View의 역할로 나눌 수 있다.
MVVM은 Model, View, ViewModel을 뜻하는 말이다.

출처 : 스탠다드반 강의자료
Model은 Data와 Business Logic을 담당하는데 MainActivity.kt에서 작성한 코드들을 이야기 하는 것 같다.
View는 화면에 보여지는 UI로 텍스트 입력, 버튼 터치 등과 같은 UI Event, Action을 받는다.
ViewModel은 View에 필요한 데이터를 Model로부터 가져와 가공 및 변환하고 UI와 관련된 데이터를 처리해준다. View가 Observe하고 있기 때문에 View가 변경된 데이터를 갱신할 수 있도록 LiveData로 변경사항을 전달해준다.
주말동안 구현해보고 올려봐야겠다.