같은 가게에 있다는 걸 어떻게 확인할까: GPS 정확도를 예산처럼 쓰기
첫만남의 플레이그라운드 지도에는 가게마다 방이 하나씩 있어요. 이 방은 그 가게 근처에 있어야 열고 들어갈 수 있어요. “같은 자리에 있는 사람들”이라는 약속을 지키려면, 그 확인이 공정해야 했어요. 생각보다 오래 걸린 이 문제를 정리해요.
가게 하나, 방 하나
8월 23일, 플레이그라운드를 다시 만들면서 “가게가 곧 방”이라는 규칙을 정했어요. 같은 가게에 방이 여러 개 생기지 않고, 이미 있는 방이 있으면 그 방으로 안내해요. 이틀 뒤에는 가게 방을 그 가게에서만 열 수 있게 바꿨어요. 동네 반대편에서 연 방은 정작 만든 사람도 들어갈 수 없는, 보이기만 하고 들어갈 수 없는 간판이 되어 버렸거든요. 거리 확인은 앱이 아니라 서버(데이터베이스 함수)에서 해요. 앱이 “가깝다”고 우기는 걸 믿을 수 없으니까요.
정확도는 품질 점수가 아니다
휴대폰의 위치에는 정확도가 함께 와요. “여기서 반경 80m 안 어딘가”라는 뜻이에요. 처음에는 정확도가 75m보다 나쁘면 거절했어요. 그런데 이 규칙이 양쪽으로 틀렸어요.
- 지하 술집이나 쇼핑몰처럼 하늘이 안 보이는 곳에서는 75m보다 나쁜 게 보통이에요. 가게 안에 서 있는데 GPS 탓에 못 들어갔어요.
- 반대로 200m 밖에서 “정확도 40m”라고 자신 있게 말하는 위치는 통과했어요.
물어야 할 건 “이 위치가 충분히 좋은가?”가 아니라 “이 사람이 가게 안에 있을 수 있는가?”였어요. 그래서 정확도를 거절 기준이 아니라 예산으로 바꿨어요.
문 = 방의 반경 + min(정확도, 150m) -- 정확도가 300m보다 나쁘면 거절
정확도가 나쁘면 그만큼 문이 넓어지지만, 150m까지만이에요. 정확도는 휴대폰이 알려 주는 숫자라 조작된 앱은 아무 숫자나 보낼 수 있어요. 상한이 없으면 “정확도 5000m”라고 말하는 것만으로 5km짜리 문이 생기죠. 300m보다 나쁜 위치는 애매한 게 아니라 쓸모없는 위치라서 거절해요. 정확도를 안 보내면 예산도 없어요. 솔직하게 보낼수록 유리하게 만든 거예요.
이걸 고치다가 이상한 사실도 하나 찾았어요. 어떤 마이그레이션 이전에 만들어진 가게 방은 50m, 이후에 만들어진 방은 100m를 문으로 쓰고 있었어요. 같은 규칙인데, 언제 만들어졌느냐에 따라 답이 달랐던 거예요. 이것도 하나로 맞췄어요.
웹은 한 번도 새 위치를 받은 적이 없었다
9월 10일에는 웹 버전의 지도가 앱보다 “빨리 뜨는” 이유를 찾았어요. 빨랐던 게 아니라, 위치를 새로 재지 않고 있었어요. 쓰고 있던 위치 라이브러리의 웹 구현이 브라우저에 “오래된 위치라도 괜찮다(maximumAge: Infinity)”고 요청하고 있었거든요. 그래서 브라우저는 캐시에 있던, 언제 잰 건지 모를 위치를 돌려줬어요. 이론적으로는 집에서 잰 위치로 가게 방의 문을 통과할 수 있었던 거예요.
지금은 한 번 읽는 대신 위치를 계속 지켜봐요(watch). 처음에는 와이파이나 기지국으로 1초 만에 대략적인 위치를 받고, 점점 정확해져요. 1초마다 들어오는 위치 중에서 실제로 움직였거나, 더 정확해졌거나, 계속 부정확한 것만 골라 쓰고, 이 선별 규칙에는 13개의 테스트가 붙어 있어요. 그리고 방에 들어가는 버튼을 누르는 순간에는 따로 새 위치를 재요.
남아 있는 한계
위치를 조작하는 앱을 쓰면 이 문은 여전히 속일 수 있어요. 휴대폰이 알려 주는 위치를 서버가 직접 확인할 방법은 없어요. 첫만남의 문은 “속일 수 없는 문”이 아니라 “정직한 사람이 억울하지 않은 문”을 목표로 해요.
정리하면
- GPS 정확도는 품질 점수가 아니라 불확실성의 반경이에요. 거절 기준보다 예산으로 쓰는 게 맞았어요.
- 클라이언트가 보내는 숫자에는 상한을 둬야 해요.
- 같은 규칙이 데이터가 만들어진 시기에 따라 다르게 동작하지 않는지 확인해야 해요.