본문 바로가기

Application/Android Kotlin

[Android] 데이터 저장 및 관리

데이터 저장 및 관리 구조

 

참고하여 공부하고 있는 android architecture sample 의 데이터 저장 및 관리 부분이다. 안드로이드에서 데이터 저장 및 관리는 어떻게 수행되는지 파악하기 위해 각 파일에서 어떠한 역할이 수행되는지 알아보았다. 또한 그 과정에서 처음 보는 개념 및 궁금증에 대해 따로 정리해두었다. 

 

각 파일 별 역할

  1. DefaultTaskRepository.kt:
    • 기본 작업 리포지토리 클래스를 정의한다.
    • TaskRepository 인터페이스를 구현한다.
    • 로컬 데이터 소스(localDataSource)와 네트워크 데이터 소스(networkDataSource)를 사용하여 작업(Task) 데이터를 관리한다.
  2. ModelMappingExt.kt:
    • 이모델 간 변환을 위한 확장 함수를 정의한다. 데이터 모델 간의 변환 또는 매핑을 위한 코드가 포함된다.
  3. Task.kt:
    • 작업(Task) 데이터 모델을 정의한다. 
  4. TaskRepository.kt:
    • 작업(Task) 관련 데이터를 관리하는 리포지토리 인터페이스를 정의한다. 
  5. source/local 디렉토리:
    • 이 디렉토리에는 로컬 데이터 소스 관련 파일들이 포함된다.
    • LocalTask.kt: 로컬 작업 데이터 모델을 정의한다. 
    • TaskDao.kt: 작업 데이터베이스와 상호작용하기 위한 DAO(Data Access Object)를 정의한다. 
    • ToDoDatabase.kt: 작업 데이터베이스를 생성 및 관리하는 코드가 포함된다. (RoomDatabase 클래스 상속)
  6. source/network 디렉토리:
    • 이 디렉토리에는 네트워크 데이터 소스 관련 파일들이 포함된다.
    • NetworkDataSource.kt: 네트워크 데이터를 가져오는 데 사용되는 데이터 소스 인터페이스를 정의한다.
    • NetworkTask.kt: 네트워크에서 가져온 작업 데이터 모델을 정의한다.
    • TaskNetworkDataSource.kt: 네트워크 데이터 소스와 상호작용하는 코드를 구현한다.

궁금증

1. TaskRepository interface 를 쓰는 이유

 

이는 interface 를 쓰는 이유와 같다. 간단하게 정리하면 좋을 것 같다.

  • 다형성 (Polymorphysim) 및 의존성 역전 원칙 (Dependency Inversion Principle) 적용
    하나의 인터페이스 타입(e.g TaskRepository interface)에 여러 구현체(e.g DefaultTaskRepository .. )가 있다. 따라서 고수준의 모듈(주로 어플리케이션)이 저수준의 모듈(구현체)에 직접적으로 의존하는 것이 아닌 인터페이스에 의존할 수 있다. 

  • 테스트 용이성
    인터페이스를 사용하면 테스트를 위해 mock 객체를 만드는 것이 쉽다. 

  • 제어의 역전(IoC, Inversion of Control)
    코드의 제어를 외부에서 가능하게 한다. 
    의존성 주입과 같은 패턴을 적용하여 객체 생성 및 관리를 외부에서 수행할 수 있다. 
  • 유지보수와 확장성
    인터페이스를 사용하면 새로운 구현체를 추가하거나 기존 구현체를 교체하는 작업이 간단해지므로 유지보수와 확장성을 향상시킨다.

  • 협업과 모듈화
    여러 개발자가 작업할 때 인터페이스를 사용하면 각자의 모듈 또는 컴포넌트를 독립적으로 개발하고 연결할 수 있으므로 협업과 모듈화를 용이하게 한다.

2. 처음 보는 문법들 

  • @singleton, @Inject
@Singleton
class DefaultTaskRepository @Inject constructor(
    private val networkDataSource: NetworkDataSource,
    private val localDataSource: TaskDao,
    @DefaultDispatcher private val dispatcher: CoroutineDispatcher,
    @ApplicationScope private val scope: CoroutineScope,
) : TaskRepository {

 

해당 클래스는 single ton 으로 관리되며 외부 의존성 주입 프레임워크에 의해 의존성이 주입(inject)된다는 의미이다.  

  • Coroutine 
    비동기 프로그래밍 및 병렬 처리를 위한 Kotlin 언어의 핵심 기능이다. 추후에 더 알아볼 가치가 있는 개념이다.

  • suspend
    비동기 작업을 수행하기 위해 사용된다. 

  • Flow
    Kotlin에서 비동기 및 데이터 스트림을 처리하기 위한 새로운 비동기 프로그래밍 기능이다.

  • withContext
    Kotlin의 코루틴(coroutine)을 사용할 때 사용되는 함수 중 하나로, 다른 코루틴 디스패처(스레드 또는 스레드 풀)에서 코드 블록을 실행할 수 있게 해주는 함수이다. withContext를 사용하면 비동기 작업을 수행할 때 다른 스레드에서 실행되도록 지정할 수 있다. 안드로이드 앱 개발에서 네트워크 요청 또는 파일 I/O와 같은 비동기 작업을 수행할 때 withContext를 사용하여 백그라운드 스레드에서 실행할 수 있다. 이렇게 하면 메인 스레드(UI 스레드)에서 작업을 수행하는 동안 앱이 응답하지 않는 문제를 피할 수 있다.
  • mutex
    일반적인 Mutex 와 동일하다. 여러 스레드가 데이터 경쟁 상태에 있을 때, 한 번에 하나의 스레드만 접근할 수 있는 임계 영역(critical section)을 생성한다.