Apple is Apple
article thumbnail

일일회고

 

심화 강의를 듣고, 강의에 있는 예제도 한 번 해보았다. 강의에 있던 대로 데이터 타입을 하나 잘못 써주었더니, API로 데이터를 가져올 때, 바로 에러를 뱉어내었다. 이제 난이도가 많이 올라간 만큼, 세세한 것들도 잘 신경 쓰는 자세를 가져야 할 것 같다.

 

아마 내일부터 개인 과제를 시작할 것 같은데, 강의, 강의 자료 등을 통해 열심히 도전 해 볼 생각이다. 또, 이번에는 사용 기술에 제한이 없어 이것, 저것 많이 만져봐야겠다. (일단 아키텍처?)


오늘의 키워드

  • sharedPreference
  • Room
  • 위치 정보 활용

SharedPreference

프로그램을 만들다 보면 데이터를 다룰 일이 생기고 저장할 일이 생긴다.
보통 DB를 사용을 하지만 소량의 데이터의 같은 경우엔 리소스를 많이 잡는 DB를 사용할 필요성이 낮다.
그럴 때에 안드로이드에서 제공하는 sharedPreference를 이용하여 key-value형식으로 데이터를 저장할 수 있다.

Preference란?

  • 프로그램의 설정 정보 (사용자의 옵션 선택 사항이나 프로그램의 구성 정보)를 영구적으로 저장하는 용도로 사용
  • XML 포맷의 텍스트 파일에 키-값 세트로 정보를 저장.
  • SharedPreferences 클래스
    • Preferences의 데이터(키-값 세트)를 관리하는 클래스
    • 응용 프로그램 내의 액티비티 간에 공유하며, 한쪽 액티비티에서 수정 시 다른 액티비티에서도 수정된 값을 읽을 수 있다.
    • 응용 프로그램의 고유한 정보이므로 외부에서는 읽을 수 없다.

getSharedPreferences(name, mode): 이름으로 식별되는 공유 환경설정 파일이 여러 개 필요한 경우 이 메서드를 사용한다. 앱의 모든 Context에서 이 메서드를 호출할 수 있다.

name: preference의 데이터를 저장할 XML 파일의 이름

mode : 파일의 공유 모드  -- MODE_PRIVATE: 생성된 XML 파일은 호출한 애플리케이션 내에서만 읽기 쓰기가 가능

val sharedPref = activity?.getSharedPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE)

값 쓰기: putInt(),  putString() 등 putXXX() 메서드를 사용하여 값을 쓸 수 있다.

 

-- 앱 전역에서 사용하려면, Application()을 상속받은 클래스를 만들어,  그 안에서 preference를 선언하여 접근하는 방법도 있다.

Room

Room은 안드로이드 jetpack의 구성요소 중 하나이다. ORM(Object - Relation Mapping)

ORM: 객체 관계 매핑은 데이터베이스와 객체 지향 프로그래밍 언어 간의 호환되지 않는 데이터를 변환하는 프로그래밍 기법

data class를 만든 것을 바로 데이터베이스의 엔티티로 만들어 사용할 수 있게 해 준다.

Room 라이브러리는 SQLite를 완벽히 활용하면서 원활한 데이터베이스 액세스가 가능하도록 SQLite에 추상화 계층을 제공한다.

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

 Room 주요 3요소

  • Room의 주요 3요소
    • @Database: 클래스를 데이터베이스로 지정하는 annotation, RoomDatabase를 상속받은 클래스여야 함
      • Room.databaseBuilder를 이용하여 인스턴스를 생성함
      • 보통 추상클래스를 통해 만듦
    • @Entity: 클래스를 테이블 스키마로 지정하는 annotation
      • 보통 데이터 클래스를 통해 만듦
    • @Dao: 클래스를 DAO(Data Access Object)로 지정하는 annotation
      • 보통 인테페이스를 통해 만듦
      • @Insert 자동으로 Insert Into 구문 실행
      • @Delete 자동으로 Delete from 구문 실행
      • @Update 자동으로 update set 구문 실행

Room 기본 구조

migration 대응

프로그램을 개발하다 보면 요구사항의 변경으로 인해 DB Table의 구조가 바뀌는 경우가 많다.

해당 예시는 엔티티의 추가 일 때의 경우이다.

@Database(entities=[Food::class], version=1)
abstract class AppDatabase: RoomDatabase() {
    abstract fun foodDao(): FoodDao
}

// --->

@Database(entities=[Food::class, Review::class], version=1)
abstract class AppDatabase: RoomDatabase() {
    abstract fun foodDao(): FoodDao
    abstract fun reviewDao(): ReviewDao
}

위 코드처럼 데이터베이스의 테이블이 추가되고 그대로 실행하게 되면, 이전에 사용되던 데이터베이스와 지금 사용하려는 데이터베이스 내부가 변경되어 migration error가 발생하게 된다.
이때, migration을 통해 데이터베이스 버전을 올려주어 에러를 해결해 줄 수 있다.

    val migration_1_2 = object : Migration(1,2) {
        override fun migrate(database: SupportSQLiteDatabase) {
            database.execSQL("CREATE TABLE `REVIEW` (`id` INTEGER, `review` TEXT," + "PRIMARY KEY(`id`))")
        }

    }
    return Room.databaseBuilder(context, AppDatabase::class.java, "BookSearchDB")
//        .fallbackToDestructiveMigration().build()
        .addMigrations(migration_1_2).build()

먼저, Migration객체를 선언한다. Migration객체의 파라미터로 이전버전, 다음버전을 넣는다.
그리고 Migration객체의 migrate메서드를 오버라이드하여 데이터베이스 테이블을 재정의한다
마지막으로 Room.databaseBuilder를 build 하는데 addMigrations() 메서드를 이용하여

(migration은 여러 개를 추가할 수도 있다.)
방금 생성한 migration을 파라미터로 전달하여 migrate 해준다.

주석처리한 fallbackToDestructiveMigration() 메서드는 migrate객체를 만들지 않고 바로
다음버전으로 migrate해주는 메서드이다.
코드 작성상, 편리함은 있지만, 이 메서드는 이전 데이터베이스를 아예 삭제 후 재생성하기 때문에 데이터 손실이 있다. 데이터 손실을 방지하고자 하면 해당 메소드는 사용을 절대 하면 안 된다. 데이터 손실이 있어도 상관없을 경우, 편하게 사용하여도 된다.

위치정보 활용

사용자의 위치를 추적하기 위한 3가지 권한이 필요하다.

  • android.permission.ACCESS_COARSE_LOCATION: 와이파이나 모바일 데이터(또는 둘 다)를 사용해 기기의 위치에 접근하는 권한이다. 
  • android.permission.ACCESS_FINE_LOCATION: 위성, 와이파이, 모바일 데이터 등 이용할 수 있는 위치 제공자를 사용해 최대한 정확한 위치에 접근하는 권한이다.
  • android.permission.ACCESS_BACKGROUND_LOCATION: 안드로이드 10(API 레벨 29) 이상에서 백그라운드 상태에서 위치에 접근하는 권한이다.

권한을 등록하고 LocationManager를 통해 위치정보를 가져올 수 있다.

 

 

위치정보 얻기

 

한 번만 얻기

LocationManager의 getLastKnownLocation() 함수를 이용

Location은 위치의 정확도, 위도, 경도, 획득 시간 등의 데이터를 포함

  • getAccuracy():  정확도
  • getLatitude():  위도
  • getLongitude():  경도
  • getTime():  획득 시간

여러 번 얻기

계속 위치를 가져와야 한다면 LocationListener를 이용

  • onLocationChanged(): 새로운 위치를 가져오면 호출
  • onProviderEnabled(): 위치 제공자가 이용할 수 있는 상황이면 호출
  • onProviderDisabled(): 위치 제공자가 이용할 수 없는 상황이면 호출

Retrofit

오픈소스 라이브러리로, REST API 통신을 위한 기능들을 담은 통신 라이브러리이다.

okHttp라이브러리의 상위 구현체로, Retrofit은 OkHttp를 네트워크 계층으로 활용하고 그 위에 구축되어 있다.

 

다음과 같은 장점이 있다.

  • 빠르다 - AsyncTask보다 3~10배의 성능을 보여준다.  (AsyncTask는 deprecated 되었다.)
  • 가독성 - Annotation(애노테이션) 사용으로 코드의 가독성이 뛰어나다. 그래서 직관적인 코딩이 가능하다.
  • 간단한 유지 보수 - Retrofit은 서버 연동 시 주로 주고받는 데이터인 JSON, XML을 자동을 파싱 해주는 Converter 연동을 지원해 준다.

기본 사용법

 

외부 라이브러리이므로 의존성 추가가 필요하다.


implementation 'com.squareup.retrofit2:retrofit:$retrofit_version
implementation 'com.squareup.retrofit2:converter-gson:$retrofit_version // 받아온 데이터를 변환해 주는 라이브러리


(converter는 JSON 타입의 결과를 객체로 자동 파싱해준다.)

 

Model 은 서버 연동을 위해 사용하는 데이터 추상화 클래스이다. 위에서 이야기했던 convertor가 JSON 데이터를 자동으로 파싱 하고, 객체를 생성한 후 모델에서 정의한 변수에 데이터를 담아준다. 보통 DTO 클래스라고 부른다.

profile

Apple is Apple

@mjjjjjj