그리드 시스템
그리드 시스템을 사용하면 지리 공간적 데이터를 효율적으로 분석해 셀을 통해 지리 공간적 클러스터를 만들 수 있다.
지리 공간적 데이터를 쉽고 효율적으로 집계, 클러스터, 분할, 축소, 조인 및 인덱싱이 가능하다.
❓ 위경도: 실제 정확한 위치 측정을 해야하므로 특정 영역 처리에 부적합
❗️ 그리드 시스템으로 해결! -> 인덱싱이 아주 중요한데, 지구의 특정 지역을 일정한 크기대로 인덱싱해 공간 처리를 잘 하도록 하는 것!
- 그리드: 공간을 나누는 구조
- 셀: 그리드를 나누는 조각조각
- 그리드느 셀들의 구조
🌐 H3
Uber에서 개발한 오픈소스 지리공간 인덱싱 시스템. 전 세계를 육각형 그리드(hexagon grid)로 나누어 표현
- 전 지구를 육각형 그리드로 분할
- 그리드(grid): 지리 공간을 나누는 구조적 단위
- 계층적 구조(hierarchial): 0~15까지 해상도 조절 가능
- 그리드는 해상도(resolution)에 따라 셀 크기가 달라진다.
- 해상도 0: 아주 큰 육각형(셀)
- 해상도 15: 아주 작은 육각형

- 빠른 공간 인덱싱 및 근접성 계산
- 단위: 셀(cell) - point가 아님!
- 동일한 그리드 안의 위경도는 다를지라도 h3셀로 변환하면 동일한 h3셀값이 나온다.
- 정확한 위치 특정이 어렵지만 공간을 찾거나 처리하는 데 있어서 비용이 적고 효율적이다.
- resolution이 높으면 비교적 정확하게 위치 특정 가능하지만 처리량이 증가
✔️ 육각형인 이유: 정사각형보다 거리 왜곡이 적고, 구 위에서 자연스럽게 맞물림
- 사각형보다 거리 왜곡이 적어 동일한 거리를 유지하기 쉽다.
- H3은 이십면체 기반으로 지구를 모델링하고 육각형 타일로 나눈다.
📌 차별점
우버는?
- 사용자 요청 시 무조건 배차가 가능하도록 만드는 것이 목표
- 드라이버의 공급을 늘려야 하므로 가격인상(surge price)가 사용되어 특정 지역의 수요가 많아지면 추가 요금을 받고 배차를 생성해 주는 방식
- 드라이버가 surge price 지역만 찾아다니거나(surge trip) surge price 범위 내에서도 고객의 요청이 드라이버에게까지 가지 못하는 경우 발생(원래는 도시 단위로 surge price를 형성 -> 지역이 넓어 발생함)
- grid sysem으로 여러 크기의 셀에서 사용자 action을 인지하고 대처할 수 있도록 h3 만들게 됨
- 동적으로 특정 셀의 변화도 측정 가능
💡 GeoJSON
지리 공간(위치) 데이터를 표현하기 위한 JSON 데이터 형식의 표준
다각형 - 사각형 지역을 나타내는 geojson polygon -> polyfill()에 바로 사용가능
{
"type": "Polygon",
"coordinates": [[
[126.97, 37.56],
[126.99, 37.56],
[126.99, 37.57],
[126.97, 37.57],
[126.97, 37.56] // 도형 닫기 (첫 점 반복)
]]
}
🛠️ 함수
1️⃣ geo_to_h3(lat, lng, resolution)
위경도 좌표를 H3 인덱스로 변환
h3_index = h3.geo_to_h3(37.5665, 126.9780, 9)
- 입력: 위도, 경도, 해상도
- 출력: 해당 위치가 포함된 H3 셀의 인덱스 ('8928308280fffff')
2️⃣ h3_to_geo(h3_index)
H3 인덱스를 셀의 중심 좌표로 변환
lat_lng = h3.h3_to_geo(h3_index)
- 입력: h3 인덱스
- 출력: 해당 셀의 중심 좌표 (위도, 경도) 형태로
- H3 셀의 시각화나 지도 위 마커 표시할 때 유용하다
3️⃣ h3_to_geo_boundary(h3_index)
주어진 인덱스에 해당하는 육각형 셀의 꼭짓점 좌표들 반환
boundary = h3.h3_to_geo_boundary(h3_index)
- 입력: h3 인덱스
- 출력: 꼭짓점 좌표 리스트 (6~7개 좌표쌍)
- 육각형 꼭짓점 좌표는 셀의 중심을 기준으로 반시계 방향으로 정렬된 위경도 좌표
- 해당 H3 셀의 중심을 중심점으로 하는 육각형 꼭짓점들의 지리적 위치(위/경도)계산해 리턴
- 셀을 지도 위에 폴리곤으로 그릴 때 사용
- folium, geopandas, matplotlib 등과 연동해 시각화
📍폴리곤: 경계로 둘러싸인 2차원 공간 영역
4️⃣ k_ring(h3_index, k)
중심 셀로부터 반경 k만큼 떨어진 이웃 셀들을 반환
neighbors = h3.k_ring(h3_index, 1) # 반경 1칸 이웃들
- 입력: h3 인덱스, 반경
- 출력: 중심 셀 포함 주변 k거리 내의 셀 인덱스들
- set으로 반환
- 특정 지점을 중심으로 범위를 설정하거나 밀접한 지역 분석 시 사용
- 이 음식점 주변 300m 반경의 다른 상점들
5️⃣ polyfill(geojson, resolution)
다각형(행정구역, 공원 등) 영역을 h3 셀로 채움
polygon = {
'type': 'Polygon',
'coordinates': [[[126.97, 37.56], [126.99, 37.56], [126.99, 37.57],
[126.97, 37.57], [126.97, 37.56]]]
}
filled = h3.polyfill(polygon, 9)
- 입력: 다각형 영역을 나타내는 Geojson형식의 폴리곤, 해상도
- GeoJson에서 Polygon표준이 요구하는 형식이므로 다각형 좌표의 사작과 끝점은 반드시 같아야 함!
- 첫 번째 점을 다시 반복해 도형을 닫아야 함
- 닫아야 도형이구나 인식
- 육각형이 아닌 일반 다각형이므로 어떤 모양이든 상관 없음. 그냥 영역 안을 h3 육각형 셀들로 채우라는 뜻
- 서울시 마포구의 지도 경계
- 사각형 범위(위경도 네 점)
- 둥근 원 형태를 근사한 좌표
- GeoJson에서 Polygon표준이 요구하는 형식이므로 다각형 좌표의 사작과 끝점은 반드시 같아야 함!
- 출력: 폴리곤 안을 채우는 h3 인덱스 셀들(set)
- 어떤 구역 안의 데이터를 전부 포함하는 셀 집합 만들 때 유용
- e.g. 마포구 전체를 커버하는 셀들을 추출해서 인구 데이터 매핑
- 행정구역을 h3 셀로 나눠서 그 셀에 인구 데이터를 연결시키는 작업
- 인구를 균등 분배하거나, 각 셀의 면적 비율, 건물 밀도, POI 개수 등으로 가중치 분배
- e.g. 마포구 전체를 커버하는 셀들을 추출해서 인구 데이터 매핑
6️⃣ compact() / uncompact()
여러 셀을 상위 레벨로 압축 / 세밀한 레벨로 다시 펼침
compact_set = h3.compact(set_of_indexes)
expanded_set = h3.uncompact(compact_set, res=9)
- 입력:
- compact: 중복되거나 겹치는 셀들을 상위 레벨 셀로 합침
- uncompact: 해상도 지정해 다시 세부 셀로 분할
- 출력: 압축된/풀린 h3 인덱스 셀 집합
- 공간 데이터 압축해 저장/전송하거나 시각화할 때 셀 수 줄이기
함수 | 설명 | 주요 활용 |
---|---|---|
geo_to_h3 |
위도/경도 → H3 인덱스 | 위치 기반 데이터 정규화 |
h3_to_geo |
H3 인덱스 → 중심 좌표 | 지도 표시, 시각화 |
h3_to_geo_boundary |
H3 셀 → 꼭짓점 좌표 | 육각형 지도 그리기 |
k_ring |
셀 주변 k 단계 이웃 |
반경 분석 |
polyfill |
다각형 → 셀들로 채우기 | 영역 집계, 공간 통계 |
compact /uncompact |
셀 압축/확장 | 데이터 최적화 |
📦 설치
pip install h3
https://mark-kim.blog/h3_basic/
H3 기본 이해하기
Uber에서 개발한 H3가 무엇이며, 왜 우버가 H3를 만들었는지 살펴본다.
mark-kim.blog