“잠깐, 주변을 한번 둘러봐주세요”.
한국인 대부분이라면 한 번쯤은 경보 문자를 받아보셨을 겁니다. 문자가 너무 많이 와서 불편함을 느낄 때도 있지만, 종종 어린 나이에 실종되는 경우를 볼 때면, 찾고 있을 가족들 생각에 안타깝기도 합니다.
과거 실종자 링크를 클릭해보았더니, 네이버 블로그
가 나왔습니다. 전국민들에게 실종 문자를 보내는 것 치고는 개선의 여지가 있다는 생각이 들었습니다. “나라면 뭘 개선할 수 있을까?” 시민들이 이동 중일 때, 근처에 실종 신고된 사람이 있다면 앱 푸시 알림으로 알려주고, 신상정보를 토대로 주변을 살펴볼 수 있도록 만들면 매우 효율적일 것이라는 생각이 들었습니다. 한편으로는 “만들면 누가 쓸려나..? 서버비는 어떻게 하지..? 앱은 어떻게 만들지..?”라는 고민에 다시 일상으로 돌아갔습니다.
그러던 어느 날, 링크드인에서 비슷한 방향성의 고민을 하는 종원님의 글을 접하면서, “누군가도 나와 같이 어떻게 개선할 수 있을지 고민하고 있구나”라는 생각에 동기부여를 받았습니다. 마침 설날이 다가오기도 하여, 앱 개발자이신 강민님과 함께 빠르게 MVP를 제작하게 되었고, 이제 피드백을 받아보려고 합니다.
Look Around
앱은 사용자가 이동하는 동안, 백그라운드로 실행되어 주변에 신고된 실종자가 존재하면 이를 알려줍니다. 이 알림을 받은 사용자는 제공된 실종자 신상정보를 토대로 잠시 주변을 둘러보며 상황을 확인할 수 있도록 설계되었습니다.
만약 LookAround
의 이 아이디어에 공감을 하신다면, 사용해보시고 피드백 주신다면 감사하겠습니다.
https://github.com/missingfinder/missingfinder
이 프로젝트는 실종자 데이터를 수집, 저장 및 조회하는 Cloudflare Workers 기반의 서비스입니다.
https://missingproxy.missingfinder-kr.workers.dev
data_hash
값을 사용합니다.초기 실행 시 300~500명의 실종자 데이터가 존재할 수 있으며, Cloudflare Free Tier의 subrequest 제한 (최대 50 요청/Request)으로 인해 Cloudflare 내부에서 모든 데이터를 처리할 수 없습니다.
따라서 local에서 init.js
를 사용하여 SQL 쿼리를 생성한 후, 배치 단위로 업로드해야 합니다.
for file in insert_missing_persons_*.sql; do
yes | wrangler d1 execute missing_db --remote --file="$file"
done
https://geo-missing-lookup.missingfinder-kr.workers.dev
const x = parseFloat(url.searchParams.get("x"));
const y = parseFloat(url.searchParams.get("y"));
const max_people = parseInt(url.searchParams.get("max_people")) || 10;
const threshold_km = parseFloat(url.searchParams.get("threshold_km")) || 5;
두 좌표 $({\phi_1}, {\lambda_1})$와 $({\phi_2}, {\lambda_2})$ 사이의 거리를 계산하는 공식은 다음과 같습니다.
\[d = R \cdot \cos^{-1} \left( \sin \phi_1 \sin \phi_2 + \cos \phi_1 \cos \phi_2 \cos (\lambda_2 - \lambda_1) \right)\]변수 설명:
SELECT id, name, current_age, age_when_missing, incident_date, clothing_description,
person_type, gender, incident_location, incident_x, incident_y, additional_features,
photo_base64,
(6371 * ACOS(
COS(RADIANS(?)) * COS(RADIANS(incident_y)) * COS(RADIANS(incident_x) - RADIANS(?)) +
SIN(RADIANS(?)) * SIN(RADIANS(incident_y))
)) AS distance
FROM missing_persons
WHERE (
6371 * ACOS(
COS(RADIANS(?)) * COS(RADIANS(incident_y)) * COS(RADIANS(incident_x) - RADIANS(?)) +
SIN(RADIANS(?)) * SIN(RADIANS(incident_y))
)
) <= ?
ORDER BY distance ASC
LIMIT ?;
위 SQL 쿼리는 주어진 $(x, y)$ 좌표를 기준으로 특정 반경 내(threshold_km)에 위치한 실종자들을 검색하며, 가장 가까운 순으로 정렬하여 최대 max_people명의 데이터를 반환합니다.