위치, 위치 기반 검색
- 현재 FireFlutter 에서 지원하는 위치 기반 검색은 공식 문서에서 제공하는 Firebase 의 Geo Query를 부분적으로 지원한다. 히지만 검색 결과의 정확도를 높이기 위해서 불편한 계산을 함에도 불구하고 결과가 정확하지 않다.
-
아래의 GEO Range Query 를 참고한다.
-
만약, 위치 기반 검색 결과에 오차가 있어도 괜찮다면, Geo hash 를 DB 에 저장해 놓고, 검색을 해도 된다.
- 그리고, 1km, 2km, 5km, 10km, 20km 등과 같이 원하는 데로 거리를 필터를 할 수 있는 것이 아니라, Geo hash 의 문자열 단계에 따라서 가능한데 이 또한 불편하다.
-
즉, 많은 것이 불편하고 오차가 있음에도 불구하고, 간단히 쓰고자 한다면 Geo Query 를 사용하면 된다.
-
모든 사용자 마다 위/경도를 DB 에 저장하면, 나의 위/경도와 비교해서 각 사용자가 나와 얼마나 떨어져 있는지 km 로 쉽게 표시 할 수 있다.
-
정확한 위치 기반 검색을 하고자 한다면 외부 데이터베이스 서비스(또는 검색 전용 서비스)를 이용하는 것이 좋은 방법이다. 왠만한 검색 기능이 있는 서비스들은 위치 기반 검색이 가능하다.
-
하지만, 외부 검색 서비스를 이용하기 싫다면 아래의 방법을 이용해 본다. 다만, 비용이 외부 검색보다 더 비싸게 들 수 있다.
-
참고로, 사용자의 정보를 외부 DB 에 mirror 해 놓는 경우, 그리고 그 외부 DB 의 속도가 느린 경우, 한 화면에서 여러 가지 옵션으로 사용자 검색을 할 때, 거리 검색 필터링을 하지 않는 경우 Firebase 데이터베이스를 이용해서 결과를 보여주고, 거리 검색 필터링이 추가되는 경우만 외부 DB 를 써도 되겠다.
GEO Range Query
pub.dev 에 있는 geo range 패키지를 보면, km 단위로 쿼리를 하는 방법에 대해서 설명을 하고 있다. Firebase 의 Geo query 와 마찬가지로 false positive 와 edge case 가 있을 것이라 생각하지만, geohash 문자열을 3자리 ~ 7자리로 비교하는 것 보단느 나아 보인다. 하지만, 그래도 edge case 때문에 정확한 결과를 얻을 수 없다. Geohash 기반으로 검색하는 모든 것이 다 부정확하다는 것을 알고 있어야 한다.
보다 정확한 위치 기반 거리 검색
- 나와 상대방의 lat/lon 값이 있으면 몇 km 가 떨어져 있는지 알 수 있고, 또 특정 범위 내로 필터링을 할 수 있다. pub.dev 에 많은 패키지들이 계산을 해 준다.
- Firebase 의 서비스에는 거리 기반 필터링하는 기능이 없으므로, 클라이언트 앱에서 계산을 하면 된다.
- 참고로 Firebase 비용이 들 수 있으므로 가능한 Realtime Database 에 저장을 한다.
위치 및 검색에 필요한 데이터 저장
- 각 사용자의 정보가 변경 될 때 마다, 검색을 위해서
/user-locations/<uid>/{lat: ..., lon: ..., gender: ..., displayName: ..., birthYear, .., birthMonth: .., birthDay: .., 기타 ... }
와 같이 저장한다.
거리 필터링
- 앱이 시작 할 때,
onChildAdded
이벤트로 모든 사용자의 검색 정보/user-locations/**
를 가져와 lat/lon 을 파싱하여 계산해 놓는다. (나와의 거리가 얼마나 떨어져 있는지 계산). 또한onChildAdded
는 새로운 (가입) 사용자의 정보가 추가되어도 계속 가져 올 수 있다. onChildAdded
내부 함수에서onChildChanged
이벤트를 사용하려 listen 한다. 즉, 사용자의 정보가 바뀌면 그 사용자 정보만 가져와 업데이트를 해 주면 된다.- (필요한 경우) 나의 위치가 변경이 될 수 있으니, 10분에 한번씩 나의 lat/lon 으로 다른 사용자들과의 lat/lon 거리 비교를 다시 계산한다.
- 중요한 것은, 앱의 특성(기능)에 따라 남/녀의 상대 성별만 검색하게 한다면, 남자는 여자만 검색할 수 있고, 여자는 남자만 검색 할 수 있다면, 전체 정보를 가져 올 필요 없이 상대 성별의 사용자 정보만 가져 올 수 있다. 즉, 약 50% 의 데이터 다운로드를 절감 할 수 있는 것이다.
- 검색 목록에서 거리 필터링을 하면, 해당 거리 내에 있는 사용자들만 보여주면 된다.
- 그 외 추가로 필터링을 하면 메모리에 있는 데이터만으로 검색(필터링)해서 화면에 보여주면 되는 것이다.
비용 계산
아래의 비용은 대략적인 비용이며, 실제로는 이 보다 더 많은 비용이 지출 될 수 있다. 앱이 사용자의 검색 정보를 가져 올 때, (각종 키 정보 포함) 한 명당 60 바이트 데이터 크기를 가져온다고 가정하면, 아래와 같다.
- 앱의 규모가 작은 경우, 예를 들면
- 전체 사용자 1 만명
- 매일 활동 사용자 500 명인 경우
-
10000 * 500 * 60 = 하루 300,000,000 바이트 = 하루 0.3 달러
-
앱의 규모가 큰 경우, 예를 들면,
- 전체 사용자 10 만명
- 매일 활동 사용자 2,000 명인 경우,
- 100000 * 2000 * 60 = 하루 12,000,000,000 바이트 = 하루 12 달러
물론 위 금액은 남/녀가 상대 성별만 검색한다면 비용은 절반으로 줄어들 수 있다.
전체 사용자가 1만명 이상 또는 매일 활동하는 사용자가 500 이상 (둘 중 하나) 이면, 다른 방법을 통해서 검색을 하는 것이 좋겠다.
외부 검색엔진 사용
- 전문 검색엔진인 Algoria 또는 Typesense 의 geo search 를 사용하는 것이 좋겠다.