UI 및 비 UI 코드를 분리하기 위한 UI 아키텍처 디자인 패턴이다. 데이터 바인딩 인프라는 UI 및 연결된 데이터를 동기화된 상태로 유지하고, 사용자 입력을 적절한 명령으로 라우팅하는 느슨한 결합을 제공한다.
반복적인 예비 코딩 스타일 사용. 격리되는 변경 내용은 위험이 적고 실험하기가 더 쉽다.
단위 테스트 간소화. 서로 격리된 코드 단위는 프로덕션 환경 외부에서 개별적으로 테스트할 수 있다.
팀 공동 작업 지원. 잘 디자인된 인터페이스를 따르는 분리된 코드는 별도의 개인이나 팀에서 개발한 후 나중에 통합할 수 있다.
유지 관리 효율성 향상. 분리된 코드의 버그를 수정하면 다른 코드에서 재발할 가능성이 줄어든다.
MVVM 패턴으로 실습을 해보자
ToDo.kt (Model): 할 일을 나타내는 데이터 클래스를 정의한다
data class ToDo(val id: Int, val title: String, val isDone: Boolean)
ToDoRepository.kt (Model): ToDo 항목을 가져오고 저장하는 리포지토리 클래스를 작성한다.
class ToDoRepository {
private val todoList = mutableListOf<ToDo>()
init {
// 초기 데이터 로드 (예: 로컬 DB 또는 API에서 데이터 가져오기
todoList.add(ToDo(1, "할 일 1", false))
todoList.add(ToDo(2, "할 일 2", true))
}
// ToDo 목록을 반환하는 함수
fun getAllToDos(): List<ToDo> {
return todoList
}
// 새로운 ToDo를 추가하는 함수
fun addToDo(todo: ToDo) {
todoList.add(todo)
}
}
ToDoViewModel.kt (ViewModel): 비즈니스 로직을 처리하고 View에 데이터를 제공하는 ViewModel 클래스를 작성한다
class ToDoViewModel : ViewModel() {
private val repository = ToDoRepository()
// ToDo 목록을 가져오는 함수
fun getToDoList(): List<ToDo>{
return repository.getAllToDos()
}
// 새로운 ToDo를 추가하는 함수
fun addNewToDo(todo: ToDo){
repository.addToDo(todo)
}
}
MainActivity.kt (View): 사용자 인터페이스와 상호작용하는 화면을 구현한다. ViewBinding을 사용하여 XML 레이아웃과 상호작용한다.
class MainActivity : AppCompatActivity() {
private lateinit var viewModel : ToDoViewModel
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel = ViewModelProvider(this).get(ToDoViewModel::class.java)
val toDoList = viewModel.getToDoList()
// ToDo 목록을 화면에 표시하는 코드
val adapter = ToDoAdapter(toDoList)
// RecyclerView에 LinearLayoutManager 연결
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.adapter = adapter
binding.addButton.setOnClickListener {
val newToDo = ToDo(3, "할 일 3", false)
viewModel.addNewToDo(newToDo)
adapter.updateData(viewModel.getToDoList())
}
}
}
ToDoAdapter.kt (View): RecyclerView에 할 일 목록을 표시하는 어댑터 클래스를 작성한다.
class ToDoAdapter(private var items: List<ToDo>): RecyclerView.Adapter<ToDoAdapter.ToDoViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ToDoAdapter.ToDoViewHolder {
val binding = TodoItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ToDoViewHolder(binding)
}
override fun onBindViewHolder(holder: ToDoViewHolder, position: Int) {
val item = items[position]
holder.bind(item)
}
override fun getItemCount(): Int {
return items.size
}
fun updateData(newItems: List<ToDo>){
items = newItems
notifyDataSetChanged()
}
inner class ToDoViewHolder(private val binding: TodoItemBinding) : RecyclerView.ViewHolder(binding.root){
fun bind(todo: ToDo){
binding.todoTitle.text = todo.title
binding.isDoneCheckBox.isChecked = todo.isDone
}
}
}
현업에서 쓰는 아키텍쳐인 만큼 익숙해질 수 있도록 노력해야겠다.