안드로이드 MVVM 패턴과 AAC

강현성·2022년 8월 9일
0

android

목록 보기
2/18

1. MVVM 패턴


처음 안드로이드 앱을 개발했을 때를 생각해 보면 MainActivity.java에 모든 코드를 작성하며 앱을 개발했었다. 이런 방식은 개발할 때는 편할지 몰라도 앱의 규모가 커지면 하나의 클래스에 모든 코드를 작성하다 보니 내가 작성한 코드도 읽기 힘들어지는 문제가 있고 이로 인해 유지 보수 측면에서 보면 매우 안 좋은 결과를 보인다. 이러한 문제를 해결하기 위해 나온 디자인 패턴이 MVVM 패턴이다.

MVVM 패턴은 Model, View, ViewModel로 각각의 역할을 나누어 가독성과 재사용성을 높인 디자인 패턴이다.

  • View: 사용자의 event(텍스트 입력, 버튼 클릭 등)를 받으며 Observe를 통해 ViewModel의 데이터를 관찰하여 자동으로 UI를 갱신한다.

  • ViewModel: View가 요청한 데이터를 Model로 요청하고 받아온다.

  • Model: ViewModel이 요청한 데이터를 가져와 반환한다.(백엔드 처리)

이렇게 각각의 역할을 나눠 서로에 대한 의존성을 낮추어 코드의 가독성을 높이고 유지보수에 큰 도움을 준다.

2. AAC(Android Architecture Component)

MVVM 패턴을 쉽게 구현하도록 구글에서는 AAC(Android Architecture Component)를 제공한다.

ACC는 Android jetpack의 구성요소로 테스트와 유지관리가 쉬운 앱을 디자인하도록 돕는 라이브러리 모음

  • Livedata를 사용하여 기본 데이터베이스가 변경되면 뷰에 알리는 데이터 객체를 빌드합니다.
  • ViewModel은 앱 회전 시 제거되지 않는 UI 관련 데이터를 저장합니다.
  • Room은 SQLite 개체 매핑 라이브러리입니다. 이것을 사용하여 상용구 코드를 피하고 SQLite 테이블 데이터를 자바 객체로 쉽게 변환하세요. Room은 SQLite 문의 컴파일 시간 확인을 제공하며 RxJava, Flowable, LiveData observable을 반환할 수 있습니다.

📌 ViewModel

ViewModel 클래스는 수명 주기를 고려하여 UI관련 데이터를 저장하고 관리하도록 설계된 클래스이다. ViewModel 클래스를 사용하면 화면 회전과 같이 구성을 변경 할 때도 데이터를 유지할 수 있다.

Android는 앱 사용중 메모리가 부족해지거나 화면을 회전하면 사용자 의도와 상관없이 Activity를 Destroy -> Create 시킨다. 이과정에서 데이터가 초기화 되는데 이를 해결하기 위해 onSaveInstanceState() 메서드를 사용하여 onCreate()의 번들에서 데이터를 복원할 수 있지만 사용자 목록이나 비트맵과 같은 대용량의 데이터는 복원시키지 못한다.

이러한 문제들을 해결하기 위해 수명 주기를 고려하여 UI 관련 데이터를 저장하는 ViewModel 클래스를 사용한다.

📝ViewModel 구현(JAVA)

MyViewModel.java

public class MyViewModel extends ViewModel {
    private MutableLiveData<List<User>> users;
    public LiveData<List<User>> getUsers() {
        if (users == null) {
            users = new MutableLiveData<List<User>>();
            loadUsers();
        }
        return users;
    }

    private void loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}

MainActivity.java

public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        // Create a ViewModel the first time the system calls an activity's onCreate() method.
        // Re-created activities receive the same MyViewModel instance created by the first activity.

        MyViewModel model = new ViewModelProvider(this).get(MyViewModel.class);
        model.getUsers().observe(this, users -> {
            // update UI
        });
    }
}

📝ViewModel의 수명 주기

ViewModel 객체의 범위는 ViewModel을 가져올 때 ViewModelProvider에 전달되는 Lifecycle로 지정된다. ViewModel은 범위가 지정된 Lifecycle이 영구적으로 경과될 때 까지, 즉 Activity에서는 Activity가 끝날 때까지 Fragment에서는 Fragment가 분리될 때까지 메모리에 남아 있는다.

📌 LiveData

LiveData는 관찰 가능한 데이터 홀더 클래스이다. 관찰 가능한 일반 클래스와 달리 LiveData는 Lifecycle를 인식합니다. 이를 통해 활성 상태에 있는 앱 클래스의 옵저버에게만 업데이트 정보를 알릴 수 있다.

📝LiveData 사용 이점

  • UI와 데이터 상태의 일치 보장
    LiveData는 Observe Pattern을 따르며 기본 데이터가 변경될 때 Observer 객체에 알려 UI를 업데이트 할 수 있도록 한다.

  • 메모리 누수 없음
    관찰자는 Lifecycle 객체에 결합되어 있으며 연결된 lifecycle이 끝나면 자동으로 삭제됩니다.

  • 중지된 활동으로 인한 비정상 종료 없음
    Acitivty가 백 스택에 있을 때를 비록하여 관찰자의 lifecycle이 비활성 상태에 있으면 관찰자는 어떤 LiveData 이벤트도 받지 않는다.

  • lifecycle을 수동으로 처리하지 않음
    UI 구성요소는 관련 데이터를 관찰하기만 할 뿐 관찰을 중지하거나 다시 시작하지 않습니다. LiveData는 관찰하는 동안 관련 수명 주기 상태의 변경을 인식하므로 이 모든 것을 자동으로 관리합니다.

  • 최신 데이터 유지
    수명 주기가 비활성화되면 다시 활성화될 때 최신 데이터를 수신합니다. 예를 들어 백그라운드에 있었던 활동은 포그라운드로 돌아온 직후 최신 데이터를 받습니다.

  • 적절한 구성 변경
    기기 회전과 같은 구성 변경으로 인해 활동 또는 프래그먼트가 다시 생성되면 사용 가능한 최신 데이터를 즉시 받게 됩니다.

  • 리소스 공유
    앱에서 시스템 서비스를 공유할 수 있도록 싱글톤 패턴을 사용하는 LiveData 객체를 확장하여 시스템 서비스를 래핑할 수 있습니다. LiveData 객체가 시스템 서비스에 한 번 연결되면 리소스가 필요한 모든 관찰자가 LiveData 객체를 볼 수 있습니다.

📝 LiveData 객체 사용

  1. LiveData의 인스턴스를 생성한다. 이 작업은 일반적으로 ViewModel 클래스 내부에서 이루어진다.
public class NameViewModel extends ViewModel {

// Create a LiveData with a String
private MutableLiveData<String> currentName;

    public MutableLiveData<String> getCurrentName() {
        if (currentName == null) {
            currentName = new MutableLiveData<String>();
        }
        return currentName;
    }

// Rest of the ViewModel...
}

2. onChanged() 메서드를 정의하는 Observer 객체를 만든다. 이 메서드는 LiveData 객체가 보유한 데이터 변경 시 발생하는 작업을 제어한다. 일반적으로 Activity or Fragment와 같은 UI 컨트롤러에 Observer 객체를 만든다.
public class NameActivity extends AppCompatActivity {

    private NameViewModel model;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Other code to setup the activity...

        // Get the ViewModel.
        model = new ViewModelProvider(this).get(NameViewModel.class);

        // Create the observer which updates the UI.
        final Observer<String> nameObserver = new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String newName) {
                // Update the UI, in this case, a TextView.
                nameTextView.setText(newName);
            }
        };

        // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
        model.getCurrentName().observe(this, nameObserver);
    }
}

3. observe() 메서드를 사용하여 LiveData 객체에 Observer 객체를 연결합니다.
4. LiveData 객체를 업데이트하는 경우 MutableLiveData 클래스는 setValue(T) 또는 postValue(T) 메서드로 LiveData 객체에 저장된 값을 수정합니다.
button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        String anotherName = "John Doe";
        model.getCurrentName().setValue(anotherName);
    }
});

📌 Room

Room은 스마트폰 내장 DB에 데이터를 저장하기 위해 사용하는 라이브러리이다.

다음은 구글에서 말하는 SQLite API를 직접 사용하는 대신 Room을 사용하면 좋은 이유들이다.

  • SQL 쿼리의 컴파일 시간 확인
  • 반복적이고 오류가 발생하기 쉬운 상용구 코드를 최소화하는 편의 주석
  • 간소화된 데이터베이스 이전 경로

📝 Room 기본 구성요소

  • 데이터베이스 클래스: 데이터베이스를 보유하고 앱의 영구 데이터와의 기본 연결을 위한 기본 액세스 포인트 역할을 합니다.
  • 데이터 항목: 앱 데이터베이스의 테이블을 나타냅니다.
  • 데이터 액세스 객체(DAO): 앱이 데이터베이스의 데이터를 쿼리, 업데이트, 삽입, 삭제하는 데 사용할 수 있는 메서드를 제공합니다.

profile
Hello!

0개의 댓글