해당 포스팅의 코드와 설명에 오류가 있다면 댓글로 말해주시면 감사하겠습니다.
며칠 전, 출시 된지 꽤 지난 어플이 사용하던 API 서버 호출 오류로 내부 로직이 꼬여 먹통이 되어 버렸다.
해당 프로젝트는 기능 동작만 생각하던 옛날의 내가 Ctrl + c, Ctrl + v를 수행한 중복 코드도 많고 매우 비효율 적으로 구현한 작품. 다시금 스스로 작성한 코드를 보면서 디자인 패턴의 중요성을 느끼고 가장 기초적인 MVC 패턴
부터 적용하기로 마음을 먹었다.
Model-View-Controller 패턴
프로젝트의 기능과 비례하게 코드의 양이 늘어난다. 디자인 패턴을 적용하지 않은 프로젝트는 Activity 클래스 파일에 모든 코드가 들어가 있고 해당 클래스 파일의 코드의 수는 몇 천줄이 되어 어떤 한 기능을 수정하기 위해 해당 부분을 찾으려고 스크롤만 몇분을 소요할 것이다.MVC
는 Activity에 몰려있는 기능의 로직들을 Model과 View, Controller로 나누는 패턴이다.
Model
Model은 Data에 관련된 로직을 모아놓은 클래스입니다. SharedPreferences와 Sqlite 등 DAO 클래스등으로 뷰에서 필요한 Data들을 가공하고 처리하는 코드가 있습니다. View와 Controller 독립적으로 Unit Test
를 시행할 수 있습니다. 아래는 예시 코드입니다.
class AccountModel {
MutableLiveData<List<Friend>> _friendList = MutableLiveData()
LiveData<List<Friend>> friendList = _friendList;
public void changeFriendList() {
List<Friend> newFriends = Friend.getMyFirend();
_friendList.postValue(newFriends);
}
}
View
View는 View에 접근하여 데이터를 처리하는 로직을 모아놓은 클래스입니다. 사용자의 입력 (ex) 터치 이벤트) 등이 발생하면 Controller에게 넘겨 주며 Model의 변경 사항점을 뷰에 반영 합니다.
class AccountView implements View.OnClickListener{
View view;
AccountController controller;
AccountView(AccountController controller, View view) {
this.view = view;
this.controller = controller;
initView();
}
private void initView() {
Button refreshBtn = view.findViewById(R.id.refresh_btn);
refreshBtn.setOnClickListener(this);
}
@Override
public void onClick(View view) {
controller.onClick(view);
}
public void changeFriendList(List<Friend> friendList) {
//RecyclerView 변경
}
}
Controller
Controller는 기존 Activity 클래스에서 View와 Model 로직을 제거한 나머지 부분이 되겠다. 뷰의 사용자 입력에 대한 처리와 Model과 상호작용 그 후 뷰에 모델을 반영하는 로직을 수행한다.
class AccountController extends AppcompatActivity{
AccountView accountView;
AccountModel accountModel;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//view 생성
View view = getLayoutInflater().inflate(R.layout.activity_account, null);
setContentView(view);
accountView = new AccountView(this, view);
accountModel = new AccountModel();
}
public void observeModel() {
accountModel.friendList.observe(this, new Observer<List<Friend>>() {
@Override
public void onChanged(List<Friend> newFriends) {
accountView.changeFriendList(newFriends);
}
});
}
public void onClick(View view) {
switch(view.getId()) {
case R.id.refresh_btn :
accountModel.changeFriendList();
...
}
}
}
정리하며
MVC 패턴은 디자인 패턴을 안드로이드에 막 적용하던 시기에 사용하던 패턴이라고 한다. 때문에 최근에 유행중인 MVP
, MVVM
보다 더 검색이 어려웠던 것 같다. 참고해가며 구현한 MVC 패턴도 알맞게 구현한 것인지 의문이 든다.
MVP, MVVM을 공부하기 위해서는 앞서 사람들이 많이 사용했던 MVC 패턴을 구현해보고 단점을 몸소 느끼는 것이 필요하다고 생각했다. 하지만 기능이 덜 복잡했던 탓인지 제대로 구현하지 못한 탓인지 Controller가 뷰에 의존도가 높다 등등.. 단점을 별로 못느낀것 같아요 아직 부족합니다 ㅠㅠ
class AccontUnitTest {
@Test
fun getAccountName() = runBlocking {
val name : String = Account.getMyName();
Assert.assertEquals(name, "점냥")
}
}
그래도 조금이나마 알게 된점은 Model을 View와 Controller한테 독립적이어서 UnitTest를 적용할 수 있다는 점이었어요. 디버그나 로그를 찍지 않고 UnitTest를 생성하여 Model의 정상 동작을 확인해볼 수 있었습니다.
참고
'Android > Common' 카테고리의 다른 글
[Android] MVP 적용해보기 - View와 Presenter (0) | 2020.08.11 |
---|---|
[Android] Executor - 기능 별 Thread 분리 (0) | 2020.07.17 |
[Android] 내부 DB - Room (0) | 2020.06.03 |
[Android] Google Calendar API 사용법 (4) | 2020.05.02 |
[Android] 바인딩 서비스로 음악 재생 (0) | 2020.04.29 |