이호준 멘토님의 우당탕탕 멘토링 5 - Local DB + Map Kit 편

지난 번 멘토링 마지막 즈음에 과제를 하나 받고 끝냈다.

과제가 뭐였냐면 내가 움직인 위치를 받아서 지도에 띄워보고, 움직인 지점들을 Local DB에 저장해서 지도 위에서 그 지점들을 이어보라는 것이었다.

그래서 이번 글에서는 내가 Local DB와 어떤 Map API를 이용하여 지도 위에 내가 움직인 위치를 나타내는 연습을 해보려 한다.


Local DB와 Map API 선정

apple 앱 개발자가 Local DB로 선택할 수 있는 선택지는 세 가지가 있다.

CoreData, Sqlite3, Realm이 바로 그것인데, 나는 이번에 Realm을 사용해서 작업을 수행하기로 결정했다.

이유는 지난 번 글에서 정리했듯이 Realm이 더 빠르고, 예전에 backend 공부할 때 한번도 사용해본 적 없었던 ORM형 CRUD를 해보고 싶었기 때문이다. 추가로 NOSQL(Not Only SQL)이 무엇인지 잘 몰라서, 감을 잡고 싶기도 했다.


지도는 NaverMaps API 를 쓸까, 애플 자체에서 제공하는 Map Kit 을 쓸까 고민하다가, 애플 자체에서 제공하는 Map Kit 을 이용하기로 했다. NaverMaps를 사용하지 않은 이유는 해당 API를 내 프로젝트에 포함시킬 경우 100MB 이상을 추가로 가져가야 한다는 점, NaverMaps API에서 제공하는 문서대로 따라해도 오류가 난다는 점, 그에 대한 비슷한 고민을 했던 참고자료도 별로 없다는 점 때문이었다. (실제로 이것 때문에 엄청나게 스트레스를 받은 경험이 있다.)


컨셉(약식 플로우 차트)

image


이번 테스트의 컨셉은 이렇다.

두 개의 화면을 만들고, 첫 화면에서 기록 시작 버튼을 누르면 두 번째 화면으로 넘어가서 기록이 시작된다.

두 번째 화면에서 시뮬레이터는 현재 미국의 어떤 지역에서 자전거를 타고 달리고 있다. 그리고 우리가 만든 앱은 위치정보가 업데이트 될 때마다 해당 좌표의 위, 경도를 임시 List에 추가한다. 또한 List에 추가될 때 이전 지점~현재 지점을 선으로 이어서 지도에 표시한다.

기록 종료 버튼을 누르면 해당 List에 담긴 기록들을 Local DB에 저장한다.

저장된 정보들은 첫 번째 화면에서 읽어들여 2021년 05월 22일 05:23:31 의 기록 과 같은 형태로 나타낸다.

이들 정보 중 하나를 클릭하면 읽어온 정보를 토대로 다시 화면에 그려준다.

또한 이들 정보를 왼쪽으로 스와이프하면 삭제할 수 있는 버튼이 뜨는데, 그 버튼을 누르면 DB에서 해당 기록을 지우고 화면에도 반영한다.


위 로직은 CRUD 중에서 Update 빼고 CRD 모두 해보는 것을 의도했다. Realm에서 Update는 단순히 위, 경도 좌표 List를 Object 안에 넣어서 DBName.update(List) 라고 써주면 끝이라 굳이 해보지 않는다고 아쉬운 건 없었다.


태스크별 화면

결론부터 말하면 이들 구현은 성공리에 끝냈고, 끝낸 화면을 먼저 보여주려 한다.

이후에는 구현을 위해 배워야 했던 기술을 다뤄보고 코드도 공개하겠다.


첫 화면에서 시작하기 버튼을 누른다.

스크린샷 2021-05-14 오후 7 03 53

화면에 내 위치가 변경됨에 따라 만들어진 발자취가 지도 위에 뜬다.

image


기록 종료 버튼을 누르면 DB에 해당 기록이 write되고, 첫 번째 화면에서는 해당 기록들을 읽어들여 리스트로 보여준다.

어떤 기록을 클릭하면 해당 기록을 Local DB로부터 read하여 화면에 다시 그려준다.


testbicycling


어떤 기록을 delete하고 싶다면 해당 기록을 왼쪽으로 스와이프 하면 나타나는 삭제 버튼을 클릭한다.

testDeleteRealm


후기

지난 번 푸시알림 편 에서 위치기반 푸시 알림을 공부한 것에 이어 지도에 실시간으로 내 위치를 그려보고 LocalDB에 저장하여 저장해둔 값을 읽어내는 것을 해보고 나니 이제는 뭔가 어떤 기능이든 혼자서도 충분히 구현해낼 자신감이 마구 솟아오른다.

동시에 이런 경험을 누군가와 같이 했다면 자료조사 하는 데에 걸리는 시간이 훨씬 덜 걸렸을 것이라는 아쉬움도 남았다.

예전에 지도 위에 음식점 정보를 띄우고 가게 평점을 남기는 프로젝트를 한 것에 이어 지도를 다시 한 번 만지게 되니 뭔가 지도 관련해서 코드를 만지는 것에 흥미가 생긴다. 도메인에 대해 고민해봐야 하는데... 이 흥미만으로 도메인을 결정하는 게 맞는걸까 갈등이 생긴다.

(으악!! 도메인 어떻게 정해야 할지 정말 모르겠다 ㅠㅠ 일단 블랙홀 조금 밀면서 천천히 고민해보아야겠다.)


구현을 위해 배워야 했던 기술

구현을 위해 다음과 같은 기술을 배워야 했고, 해당 기술 중

Local DB(Realm)에 관한 부분은 여기에 따로 정리해뒀고,

나머지 Map Kit 사용법에 대한 부분은 여기에 정리해뒀다.

혹시나 코드가 필요한 분들을 위해 github 링크를 여기에 남겨둔다.

(github 폴더가 많을텐데, HoTechCourse/TrackMyTrace에 파일들이 위치해 있다.)


Map Kit

xcode 자체에서 제공하는 맵 API인 Map Kit 의 사용방법을 익혀야 했다. 사용자의 위치를 계속 따라다니면서 해당 위치를 중심으로 지도를 옮겨야 했고, Zoom을 할 수 있도록 설정을 해야 했다.

또한 지점과 지점을 지도상에서 잇기 위해서는 어떤 함수를 이용해야 하는지 공부해야 했고, 어떤 지점을 지도 위에서 특정 마크로 표시하려면 어떤 것들이 필요한지 공부해야 했다.

그리고 점과 점을 이을 때 어떤 색깔로, 얼마나 굵은지 설정하는 메서드에 대한 공부도 필요했다.


Realm

Realm의 경우 CRUD에 대한 코드 자체는 매우 간단했다.

예를 들어 create하는 코드는 다음과 같이 매우 짧았다.

var realm = try! Realm()

    func create<T: Object>(_ object: T) {
        do {
            try realm.write {
                realm.add(object)
            }
        } catch {
            print("realm create error: \(error)")
        }
    }

반면에 Realm 자체를 쓰기 위해서는 특별한 조건이 있었는데, 다음과 같았다:

  • 모든 Realm 변수는 Runtime 내내 유지될 것
    • 이를 위해 @objc dynamic 이라는 키워드를 변수 앞에 써주어야 했다.
  • 모든 Realm Class는 Realm 자체에서 제공하는 Object(여기서 말하는 Object는 일반 Object랑 다름!!)를 conform 할 것.
  • Optional 변수의 경우 Realm에서 제공하는 Optional 변수를 사용할 것.

(오종인 멘토님께서 굳이 빨라야 하냐, 더 무거운 거(약 2.5~4mb 더 들어가게 됨 쓰면) 써야 하냐고 물으셔서 용량이 커지지 않는 이상 굳이 쓸 필요는 없다고 결론... 다 하고 나서 알게된 거라 일단 이번 프로젝트는 realm을 사용.)

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기
// custom