로컬 DB 설계 시, 고려하면 좋은 것들

이윤설·2024년 12월 16일
0

안드로이드 연구소

목록 보기
12/33

Room과 Datastore

우선 본문에 들어가기에 앞서, 현대 안드로이드 앱 개발에서 로컬 DB 설계 시 사용되는 라이브러리 2개를 알아보자.

SharedPreferences와 DataStore, 그리고 프로토콜버퍼 라는 포스팅에서 Datastore에 대해 알아보았었다.

1. Datastore

Datastore는 "key-value" 쌍을 데이터로 저장하는 로컬 데이터베이스의 한 종류이다.
일반적인 데이터가 아니라, key-value 값을 저장하기 때문에 테마 설정(다크 모드 등)여부, 앱 설정, 환경 변수, 간단한 상태 정보 등을 저장하기에 적합하다.

2. Room

Datastore과는 반대로, Room은 일반적인 구조적 데이터를 저장할 때 사용된다.
복잡한 쿼리 수행, 엔티티 간 관계 정의 등을 수행할 수 있다.

결론

둘 중 하나만 사용하는 앱도 있겠지만, 어느정도 규모가 있는 앱이라면 두 라이브러리를 함께 사용한다.

로컬 DB 설계 시, 고려하면 좋은 것들

1. ROOM DB를 중심으로 한 ORM 사용

  • DAO 패턴을 활용하여 데이터 접근 코드를 분리한다.
  • Relation 어노테이션을 활용한 관계형 데이터를 처리한다.

2. DataStore와 Room DB의 조합

  • 앱 설정, 환경 변수, 간단한 상태 정보는 DataStore(SharedPreferences 대체)로 관리하고, 복잡한 구조적 데이터는 Room DB에 저장한다.
    • 예: 테마 설정(다크 모드 등)은 DataStore에 저장, 사용자 데이터는 Room DB에 저장.

3. 로컬 데이터와 서버 데이터의 동기화

  • 오프라인 상태에서도 앱이 문제없이 작동하도록 설계한다.
  • 서버 데이터와 로컬 데이터를 동기화하여 일관성을 유지한다.(예: Firestore와 Room DB 통합 사용).
  • WorkManager를 이용해 백그라운드에서 동기화 작업 실행.
  • 서버 동기화 여부를 로컬 데이터에 플래그로 저장.

4. 멀티모듈 설계 - 데이터 레이어 분리

  • 앱 구조를 정리하고 유지보수를 쉽게 하기 위해 데이터를 관리하는 부분과 화면을 만드는 부분을 분리한다.
  • Repository 패턴을 사용하여 데이터 저장소(Room DB, 서버, DataStore 등)가 바뀌어도 앱의 나머지 부분(ViewModel 등)은 영향을 받지 않도록 설계한다.
  • 즉, 데이터를 가져오는 역할(Room DB, 서버 등)을 "한 곳(Repository)"에 몰아서 처리하고, 화면에서는 "필요한 데이터만 요청"하도록 코드를 작성한다.
  • 예시
    • data 모듈에는 Room DB, DataStore, 네트워크 코드가 들어간다.
    • 화면(ViewModel)은 "유저 목록을 가져와줘"라고만 요청하고, Repository가 Room DB나 네트워크에서 데이터를 알아서 가져온다.

5. 스키마 변경을 고려한 유연한 설계

  • 앱이 업데이트되면 데이터베이스 구조도 변경이 필요할 수 있다(예: 새로운 컬럼 추가). 이를 대비해 Room에서 Migration 기능을 사용한다.
  • 앱을 업데이트해도 기존에 저장된 데이터가 없어지거나 충돌하지 않도록 데이터를 "안전하게 옮기는 방법"을 미리 설정한다.
  • 확장성을 고려한 설계:
    • 너무 복잡하게 설계하지 말고 필요한 데이터만 테이블에 저장한다.
    • 데이터 중복이 필요할 경우(속도 향상 등)에는 일부 중복 데이터를 저장하는 것도 허용한다.
  • 예시
    • 기존 테이블에 새로운 칼럼을 추가할 때, 기존 데이터를 보존하면서 새 칼럼도 추가되도록 Room의 Migration 코드를 작성한다.

6. 비동기 처리

  • Room과 DataStore에서 Flow를 이용해 데이터 변경 사항을 실시간으로 감지한다.

7. 보안과 암호화

  • 로컬 DB에 민감한 정보를 저장할 때 데이터 암호화를 기본적으로 고려한다.
  • Jetpack Security 라이브러리를 활용해 안전한 암호화 구현:
    • SQLCipher 같은 도구를 사용해 SQLite 데이터 암호화.
    • DataStore도 암호화 옵션 제공.

8. 캐싱전략

  • 서버에서 데이터를 매번 받아오면 느리고 데이터 요금이 발생한다. 이를 막기 위해 데이터를 로컬 DB(Room)에 저장해두고, 필요할 때만 서버와 동기화한다.
    쉽게 말해서, 서버 데이터를 "복사본"처럼 로컬에 저장하고, 바뀌었는지 확인하면서 필요할 때만 서버 데이터를 새로 가져온다.

  • 구현 방법:

    • TTL(Time-To-Live): 데이터를 일정 시간 후에 새로고침하도록 설정한다.
    • isSynced 플래그: 데이터를 로컬에서 수정했으면 이 데이터를 서버와 동기화했는지 기록하는 플래그를 사용한다.
  • 예시:
    "사용자 정보"를 Room에 저장하고, 마지막으로 서버와 동기화된 시간이 1시간 넘었으면 서버에서 새 데이터를 가져온다.

9. 테스트 가능성을 고려한 설계

  • In-Memory Room Database를 사용하여 테스트 환경에서 쉽게 테스트 가능하도록 한다.
  • Mocking 라이브러리(MockK, Mockito)로 데이터 계층 테스트.
profile
화려한 외면이 아닌 단단한 내면

0개의 댓글

관련 채용 정보