[Android/오르다 다이어리] 레거시 리팩토링 05 - Configuration Change 대응 (ViewModel 적용)
지난 글: https://yujinius45.tistory.com/159
[Android/오르다 다이어리] 레거시 리팩토링 04 - Fragment 마이그레이션
[Android/오르다 다이어리] 레거시 리팩토링 04 - Fragment 마이그레이션지난 글: https://yujinius45.tistory.com/158 [Android/오르다 다이어리] 레거시 리팩토링 03 - Navigation Component 적용[Android/오르다 다이어리]
yujinius45.tistory.com
지난번에 Activity에서 Fragment로 전환하는 마이그레이션 작업을 진행했다. 이를 통해 화면 이동이 불편했던 문제를 해결하고, 네비게이션 바를 추가하여 더 나은 UX를 제공할 수 있었다. 하지만 이 과정에서 새로운 문제들이 발견되었다.
이번 글에서는 Fragment 마이그레이션 후 발견한 문제점(일기 작성 페이지 Configuration change 대응 문제 등)과 이를 해결하기 위해 ViewModel을 적용한 과정을 정리해보고자 한다.
✨ Fragment 마이그레이션 후 느낀 점 정리
지난 리팩토링 작업을 통해 여러 가지 이슈를 발견했다. 그중에서도 가장 크게 불편함으로 느낀점은 UI와 로직이 분리되지 않은 점과 DB 관련 버그가 존재한 점이었다. 각각의 문제를 분석하고, 개선 방안을 찾아보았다.
1. UI와 로직이 분리되지 않아 관련 수정에서 시간이 오래 걸림(유지보수성 떨어짐)
기존 Activity 기반 코드에서는 UI와 데이터 처리 로직이 뒤섞여 있었기 때문에 Fragment로 이동할 때 많은 코드 수정이 필요했다.
🔹 UI를 Fragment로 옮기면서, 데이터 로직도 함께 이동해야 해서 불필요한 코드 이동이 많았고, 시간이 오래 걸려 유지보수성이 낮다고 느낌
🔹 만약 UI와 로직을 분리했다면 UI만 이동하면 되므로 변경 작업이 훨씬 간결했을 것
🔹 오르다 다이어리 같은 경우는 해당되지 않지만, 더 큰 규모의 프로젝트에서 여러 view를 재사용한다면 View와 로직이 분리되지 않으면 재사용성이 떨어지고, 다른 곳에서 동일한 로직을 사용하고 싶을 때 중복 코드가 발생
➡️ 이를 해결하기 위해 ViewModel을 도입하여 UI와 로직을 분리하기로 결정했다. 현재는 Configuration Change 대응이 필요한 일기 작성 페이지에만 ViewModel을 적용하고, 다른 페이지들은 기존 방식으로 상태가 유지되므로 그대로 두었다.
2. DB 관련 SQL 쿼리 문제
기존 SQLite 코드에서 UPDATE가 날짜(writeDate)를 기준으로 이루어지는 문제가 있었다. 이로 인해 데이터가 꼬이는 문제가 발생했다.
🔹 해결책: ID를 기준으로 업데이트하도록 수정
🔹 하지만 SQL 직접 작성 방식이 유지보수하기 어려웠음 (최근에 진행한 프로젝트에서는 RoomDB를 사용했는데, 이를 다시 보니 가독성이 많이 떨어지는 것이 느껴짐)
➡️ SQLite 유지 vs RoomDB 마이그레이션 여부를 검토하기 위해 이후 테스트 코드 작성을 진행해볼지 고려중이다.
그래서 다시 본론으로 돌아와서, 오늘 진행할 내용을 아래에 정리하고자 한다.
지난번 Fragment 전환 과정에서 일기장 작성 페이지의 Configuration Change 대응이 필요하다는 걸 알게 되었고, 이를 해결하기 위해 이번 리팩토링을 진행했다
🛠️ Configuration Change 문제 분석
오르다 다이어리는 Activity 기반일 때부터 Configuration Change(화면 회전 등)에 어느 정도 대응이 되어 있었다. (과거의 우리 팀 기특하다! 👏)
🔹 그 이유는?
기존 Activity 구조에서는 onCreate()가 실행될 때마다 DB에서 데이터를 다시 불러오는 방식을 사용했다.
➡️ 따라서 Fragment에서도 onViewCreated()에서 DB를 다시 로드하여 데이터가 대부분 유지됨
하지만! 예외적인 경우가 있었는데, 일기 쓰기 페이지에서 이미지 상태가 유지되지 않는 문제가 발생했다.
💡 일기 쓰기 페이지에서 이미지 상태 유지 문제
▼ Configuration change 대응 안되는 모습 (사진 부분 참고)

- 사용자가 일기 작성 도중 이미지를 추가하고 화면을 회전, 다크 모드 변경 등을 하면 이미지가 사라짐
- 기존 방식에서는 DB에서 다시 불러오기 때문에 유지됨, 하지만 일기 작성 도중의 데이터(입력 내용, 이미지)는 DB에 저장되지 않음
- 즉, Configuration Change가 발생하면 Fragment가 재생성되면서
imageUri가 초기화되는 문제가 발생
➡️ 이를 해결하기 위해 ViewModel을 도입하여 데이터 상태를 유지하는 방식으로 개선하기로 결정했다.
🔧 Configuration Change 해결 방법
Configuration Change(예: 화면 회전, 다크 모드 변경 등) 발생 시 데이터를 유지하는 방법에는 두 가지 방법이 있다.
📌 onSaveInstanceState() 활용
✔️ 원리
onSaveInstanceState()는 Activity/Fragment가 소멸될 때 데이터를 Bundle에 저장하고, 이후 Bundle을 통해 데이터를 복원하는 방식- 간단한 UI 상태(텍스트, 숫자, Boolean 등)를 저장하는 용도로 사용됨
❌ 단점
https://developer.android.com/topic/libraries/architecture/saving-states#viewmodel
Don't use saved instance state to store large amounts of data, such as bitmaps, nor complex data structures that require lengthy serialization or deserialization. Instead, store only primitive types and simple, small objects such as String.
Data limitations : only for primitive types and simple, small objects such as String
- 크기 제한이 있어서 Bitmap, Uri 같은 대용량 데이터 저장 불가능
Read/write time: slow (requires serialization/deserialization)
- 데이터가 많아질수록 Bundle을 파싱하는 과정이 성능 저하를 일으킬 수 있음.
➡️ 텍스트, 체크박스 상태 등 간단한 UI 상태 저장에는 적합하지만, 이미지 상태 유지에는 적절하지 않음. 물론 uri만 저장시키면 되지만 일기 저장 로직도 분리할 예정이기에 viewmodel 선택.
📌 ViewModel 활용 (선택한 방법)
https://developer.android.com/topic/libraries/architecture/saving-states#viewmodel
Use ViewModel to handle configuration changes
ViewModel is ideal for storing and managing UI-related data while the user is actively using the application.
✔️ 원리
- ViewModel은 Configuration Change 시에도 유지되는 객체
- Fragment가 소멸되더라도, Activity가 살아 있는 동안 ViewModel은 유지됨
- LiveData를 함께 사용하면 자동으로 UI 업데이트 가능
✅ 장점
- Configuration Change 후에도 자동으로 데이터 유지됨
- Fragment가 여러 번 생성되더라도 같은 ViewModel을 공유 가능
- LiveData와 함께 사용하면 UI 자동 갱신 가능
➡️ 이미지 상태 유지, UI와 로직 분리를 위해 ViewModel을 활용하기로 결정
☺️ 적용 결과 및 후기
1. Configuration Change 대응 강화
- 화면 회전, 다크 모드 변경 후에도 입력 데이터와 이미지 상태가 유지됨
2. UI와 비즈니스 로직 분리
- UI는 Fragment에서 관리하고, 데이터 처리는 ViewModel에서 수행하여 코드 구조가 더 명확해짐
- 아래 이미지와 같이 UI의 데이터를 가져와 유효값인지 체크하고 일기장 저장을 하던 로직을 ViewModel로 이전하여 UI는 저장 됐는지만 체크하고 토스트 메세지 출력.

3. DataBinding 및 LiveData 활용
DataBinding을 적용하여 UI와 ViewModel 데이터를 직접 연결- 데이터 변경 시 UI에서
setText()등을 명시적으로 호출할 필요 없어서 편리했음.
4. MVVM 패턴 적용 후 개선된 점
- setText() 등의 과정이 없어서 코드가 깔끔해짐.
- LiveData를 활용하여 UI가 자동으로 업데이트되도록 구성
- 하지만 현재 작업에서는 ViewModel이 단순 데이터 저장소 역할만 하고 있음
➡️ 현재는 일기 작성 페이지에서만 ViewModel을 적용했고, 다른 페이지들은 기존 방식으로도 상태가 유지되므로 그대로 두었다. 추후 더 복잡한 기능이 추가될 경우 ViewModel 활용도를 높일 계획이다.
이제 다크 모드로 변경해도 작성하던 것 사라지지 않는다!!
▼ Configuration change 대응 되는 모습

'Android > 오르다 다이어리' 카테고리의 다른 글
| [Android/오르다 다이어리] 레거시 리팩토링 07 - SQLite, MapMemo 기능 완성 (1) | 2025.03.02 |
|---|---|
| [Android/오르다 다이어리] 레거시 리팩토링 06 - DBHelper 싱글톤 패턴 적용 (0) | 2025.03.01 |
| [Android/오르다 다이어리] 레거시 리팩토링 04 - Fragment 마이그레이션 (0) | 2025.02.24 |
| [Android/오르다 다이어리] 레거시 리팩토링 03 - Navigation Component 적용 (0) | 2025.02.20 |
| [Android/오르다 다이어리] 레거시 리팩토링 02 - targetSdk 34 적용 이슈와 해결 (0) | 2025.02.11 |