두 위치 좌표 간의 거리를 구하는 방법은 다양한 프로그래밍 언어에서 구현할 수 있으며, 일반적으로 위도(latitude)와 경도(longitude)를 이용해 지구 곡률을 고려한 거리 계산(Haversine 공식)을 사용합니다. 아래에 개요, 배경, 수학식, 활용사례 및 예시 코드를 포함해 설명드리겠습니다.
📍 기본 개요: 좌표 간 거리 계산
두 지점 A(위도 φ₁, 경도 λ₁)와 B(위도 φ₂, 경도 λ₂)가 주어졌을 때, 이들 사이의 거리를 계산하려면 다음 조건을 고려해야 합니다.
- 지구는 완벽한 구형이 아니지만, 평균 반지름 6,371 km를 기준으로 계산합니다.
- 두 점 사이의 거리는 직선 거리(대권거리, great-circle distance)로 구합니다.
🧮 수학적 배경: Haversine 공식
a = sin²(Δφ / 2) + cos(φ₁) × cos(φ₂) × sin²(Δλ / 2)
c = 2 × atan2(√a, √(1−a))
d = R × c
Δφ = φ₂ − φ₁
(위도 차이, 라디안 단위)Δλ = λ₂ − λ₁
(경도 차이, 라디안 단위)R
= 지구 반지름 (6,371 km 또는 6,371,000 m)d
= 두 좌표 사이의 거리
Python 예제 코드
from math import radians, sin, cos, sqrt, atan2
def haversine(lat1, lon1, lat2, lon2):
R = 6371000 # 지구 반지름 (단위: m)
# 위도/경도 라디안 변환
phi1 = radians(lat1)
phi2 = radians(lat2)
d_phi = radians(lat2 - lat1)
d_lambda = radians(lon2 - lon1)
# Haversine 공식 적용
a = sin(d_phi / 2) ** 2 + cos(phi1) * cos(phi2) * sin(d_lambda / 2) ** 2
c = 2 * atan2(sqrt(a), sqrt(1 - a))
distance = R * c
return distance # 단위: meter
# 예: 서울(37.5665, 126.9780) ↔ 부산(35.1796, 129.0756)
print(f"거리: {haversine(37.5665, 126.9780, 35.1796, 129.0756) / 1000:.2f} km")
활용사례
- 보안 분야
- 출입 위치 간 거리를 비교하여 비정상 접근 판단 (예: GPS 위조 탐지)
- 특정 기기 또는 사용자 이동 경로 분석 (예: 정보 유출 탐지)
- 물류/배송
- 배송 경로 최적화 및 예상 도착 시간 계산
- 지정 지역 내 여부 판단 (예: 1km 이내 진입 여부)
- 생활 서비스 앱
- 사용자 위치 기반 근처 가맹점 추천
- 배달 가능 지역 판별
- 위치정보 수집 시 사전 동의 확보 필요 (개인정보 보호법)
- 정확한 좌표 보정이 필요한 경우, 실시간 보정 GPS(RTK)나 Wi-Fi 위치 보조 정보 활용
- 좌표 변환 오류 처리: 위/경도는 도(degree)에서 라디안으로 정확히 변환해야 함
- 반복 호출 시 서버 부하 주의: 캐시 혹은 사전 거리 계산 방식 적용 권장
추가 도구
- Python 외 사용 예
- JavaScript:
geolib.getDistance()
,turf.js
- SQL:
ST_Distance_Sphere()
(MySQL),ST_Distance()
+ SRID (PostGIS)
- JavaScript:
- 도식화: Folium, Leaflet, Google Maps API
Home Assistant에서는 template
센서 또는 template
함수를 이용해 Jinja2 기반 템플릿 코드로 두 지점의 위도/경도 좌표 간 거리 계산이 가능합니다. distance()
함수를 사용하면 복잡한 수식 없이도 간단하게 거리를 구할 수 있습니다.
Home Assistant 템플릿에서 거리 계산하는 방법
📐 기본 함수:
distance()
Home Assistant의 Jinja 템플릿 엔진에서는 다음 함수를 제공합니다.
distance(location1, location2)
location
은(위도, 경도)
튜플 형식- 반환값: 단위는 킬로미터(KM)
예제 1: 두 좌표 간 거리 계산 (직접 지정)
{{ distance((37.5665, 126.9780), (35.1796, 129.0756)) | round(2) }} km
📌 출력 결과: 서울 ↔ 부산 사이의 대략 거리 (약 325.38 km)
예제 2: 나의 위치 vs 특정 장소
{{ distance(state_attr('device_tracker.my_phone', 'latitude'), state_attr('device_tracker.my_phone', 'longitude'),
37.5665, 126.9780) | round(1) }}
device_tracker.my_phone의 현재 위치와 서울시청 간 거리 계산
예제 3: template 센서로 등록
template:
- sensor:
- name: "집과 회사 거리"
unit_of_measurement: "km"
state: >
{{ distance((state_attr('zone.home', 'latitude'), state_attr('zone.home', 'longitude')),
(state_attr('zone.work', 'latitude'), state_attr('zone.work', 'longitude'))) | round(2) }}
zone.home
,zone.work
은 Home Assistant에 등록된 위치 영역- 거리 값을 센서 형태로 대시보드에 표시할 수 있습니다
활용 팁
항목 | 설명 |
---|---|
위치정보 노출 | 템플릿이나 로그에 좌표 직접 노출 시 개인정보 유출 주의 |
거리에 따른 자동화 | 특정 거리 이내 진입 시 알림/자동화 가능 (예: distance < 1 km) |
Wi-Fi 기반 zone 오차 보정 | device_tracker와 zone 간 오차 발생 시 거리 기반 로직이 더 정밀 |
아이디어
- 출근 거리 기반 자동화 (거리 < 1km → 조명 켜기)
- 가족 구성원 도착 거리 알림
- 차량 GPS 연동 후 이동 경로 추적
- 특정 위치 벗어나면 알림 전송
아래는 distance()
, as_timestamp()
, now()
등의 Jinja 템플릿 함수를 활용한 위치 기반 자동화 템플릿 예시와 함께, Home Assistant의 주요 위치 센서(zone
, device_tracker
, person
) 별로 자동화를 구성하는 활용 사례입니다.
위치 기반 템플릿 함수 조합 개요
함수 | 설명 |
---|---|
distance(loc1, loc2) |
위도/경도 또는 zone, entity 속성을 기반으로 거리 계산 (단위: km) |
now() |
현재 시간 반환 (datetime 객체) |
as_timestamp() |
datetime → timestamp(초) 변환 |
states('entity_id') |
entity 상태(예: 'home' , 'not_home' ) 조회 |
state_attr('entity_id', 'latitude') |
특정 entity의 속성 추출 |
센서별 자동화 사례
1. zone 기반 자동화 예시
목적: "집(zone.home)에 1km 이내 접근 시 조명 켜기"
automation:
- alias: "가정집 근처 접근 시 조명 켜기"
trigger:
- platform: time_pattern
minutes: "/1" # 1분마다 평가
condition:
- condition: template
value_template: >
{{ distance(
(state_attr('device_tracker.my_phone', 'latitude'), state_attr('device_tracker.my_phone', 'longitude')),
(state_attr('zone.home', 'latitude'), state_attr('zone.home', 'longitude'))
) < 1 }}
action:
- service: light.turn_on
target:
entity_id: light.living_room
📌 zone.home 좌표 기준으로 device_tracker가 반경 1km 이내로 들어오면 자동 실행
2. device_tracker 기반 자동화 예시
목적: "부재 중일 때 집에 500m 이내 접근하면 알림 전송"
automation:
- alias: "집 근처 접근 시 알림"
trigger:
- platform: state
entity_id: device_tracker.my_phone
to: 'not_home'
for: "00:05:00"
condition:
- condition: template
value_template: >
{{ distance(
(state_attr('device_tracker.my_phone', 'latitude'), state_attr('device_tracker.my_phone', 'longitude')),
(state_attr('zone.home', 'latitude'), state_attr('zone.home', 'longitude'))
) < 0.5 }}
action:
- service: notify.mobile_app_myphone
data:
message: "집 근처입니다. 자동문 열까요?"
3. person 센서 기반 자동화 예시
person은 여러 device_tracker를 통합한 고수준 엔터티입니다.
목적: "사람이 회사에서 퇴근하면 자동으로 보일러 끄기 (퇴근 시간 + 위치)"
automation:
- alias: "퇴근 시 보일러 OFF"
trigger:
- platform: state
entity_id: person.john
from: 'work'
to: 'not_home'
condition:
- condition: time
after: "17:30:00"
action:
- service: climate.turn_off
target:
entity_id: climate.home_heater
4. 시간 + 위치 기반 템플릿 (거리 + 이동시간 평가)
목적: "지금 위치에서 집까지 거리 3km 이상이고, 저녁 10시 이후면 '귀가 중' 알림 전송"
trigger:
- platform: time_pattern
minutes: "/5" # 5분마다 실행
condition:
- condition: template
value_template: >
{% set dist = distance(
(state_attr('device_tracker.my_phone', 'latitude'), state_attr('device_tracker.my_phone', 'longitude')),
(state_attr('zone.home', 'latitude'), state_attr('zone.home', 'longitude'))
) %}
{% set hour = now().hour %}
{{ dist > 3 and hour >= 22 }}
action:
- service: notify.mobile_app_myphone
data:
message: "밤 늦게 집에 가는 중이군요. 조심히 들어가세요!"
사용자 관리
항목 | 점검 포인트 |
---|---|
위치 추적 범위 제한 | 너무 자주 distance() 호출 시 서버 부하 가능 → 1~5분 주기 권장 |
개인정보 보호 | GPS 좌표는 로그 및 UI에 노출되지 않도록 주의 |
다중 사용자 추적 | person.john , person.jane 식으로 구분하여 자동화 별도 설정 |
geo_location 연계 | 외부 이벤트(ex: 특정 지역 위험 알림)와 거리 기준 조건 연동 가능 |
유형 정리
구성요소 | 활용 함수 | 자동화 예시 |
---|---|---|
zone |
state_attr('zone.name', 'latitude') |
특정 장소 반경 내 접근 감지 |
device_tracker |
distance() , state_attr() |
실시간 거리 기반 판단 |
person |
state == 'home' , not_home |
통합 위치 상태 기반 조치 |
시간 조건 | now() , as_timestamp() |
특정 시간대 조건 결합 |
댓글