시스템 디자인 아틀라스 CASE STUDY / LOCATION 로드맵
CASE · INTERMEDIATE읽기 24분검토일 2026-08-23

주변 장소 검색
시스템 설계

주변 검색은 지도 위의 점을 단순히 모으는 문제가 아닙니다. 셀 인덱스로 후보를 충분히 작게 만든 뒤에도, 정확한 거리·공개 정책·카테고리·순위를 순서대로 판정하고 위치 자체는 가장 적게 다뤄야 합니다.

문제·요구사항공간 인덱스장애·privacy면접 답변진도 저장
30초 핵심 요약

Geohash 또는 H3 셀은 후보를 찾는 출발점입니다. 실제 응답은 카테고리·공개 정책 → 정확 거리 → 랭킹으로 좁히며, 도심 hot cell은 resolution·shard·cache 동시성으로 따로 다룹니다. 정확 위치는 정본과 짧은 처리 경로에만 두고, 관측 데이터는 coarse bucket으로 낮춥니다.

CandidateGeohash / H3 cover
Correctnessexact distance + policy
Privacyminimum precision & retention
01 · REQUIREMENTS

반경·정책·정확성을 하나의 응답 계약으로 묶는다

# 요구사항

사용자는 “800 m 안의 카페”를 요청하지만, 시스템은 원형 경계·카테고리·영업 상태·노출 권한·순서와 위치 처리 동의를 동시에 결정합니다. 후보가 빨라도 경계 밖 또는 비공개 장소를 반환하면 안 됩니다.

R1반경 검색

좌표·반경·limit 상한을 검증하고 최종 결과의 정확한 거리로 경계를 보장합니다.

R2카테고리·상태

카테고리, 영업 상태, 테넌트·지역 노출 정책을 랭킹보다 먼저 필터합니다.

R3예측 가능한 지연

셀 후보 수와 fanout에 예산을 두고, hot cell에서도 fallback을 제한합니다.

R4위치 최소화

정확 좌표·계정·IP를 장기 로그에서 기본적으로 결합하지 않고 coarse 관측을 사용합니다.

02 · HIGH-LEVEL DESIGN

정본·파생 인덱스·정확성 판정을 분리한다

# 아키텍처

POI 정본은 versioned 변경 이벤트를 내보내고, 여러 후보 인덱스는 이를 재생성할 수 있는 파생 데이터로 유지합니다. 읽기 경로는 cell cover로 시작하지만 최종 응답 직전의 policy와 거리 검증이 진실의 경계입니다.

주변 장소 검색의 write / read path SVG DIAGRAM · candidate ≠ final answer
주변 장소 검색 아키텍처POI 정본과 변경 이벤트가 Geohash 또는 H3 셀 인덱스, Redis GEO cache, 검색 인덱스로 흘러간다. 사용자의 주변 검색 요청은 인증과 정밀도 정책을 거쳐 셀 후보를 찾고, 카테고리와 공개 정책 필터, 정확 거리 계산, 랭킹을 거쳐 결과를 반환한다.쓰기 · 정본 변경에서 파생 인덱스까지읽기 · 후보 → 정확성 → 응답POI 정본PostGIS · versionOutbox / Indexerevent · replay · lagCell candidatesGeohash / H3 / GEOCache / Search tierhot cell · category shardNearby APIauth · radius capPolicyvisible?Distanceexact radiusRanktop-k셀은 후보 단계다. 원본 좌표의 거리·가시성 정책을 통과한 장소만 사용자에게 보낸다.
정확성 경계: cell cover에서의 거짓 양성은 정상입니다. 반경 경계의 누락은 synthetic boundary test로 막고, 반경 밖 결과는 정확 거리 판정에서 제거합니다. 숨김·폐업 상태는 인덱스 lag가 있어도 read-time deny가 우선합니다.
03 · REQUEST FLOW

좌표를 오래 갖지 않고 후보를 좁힌 뒤 정확하게 답한다

# 요청 흐름
1인증·입력 검증

권한, rate limit, 좌표 범위·반경·limit 상한을 확인하고 정밀도 정책을 적용합니다.

2cell cover

Geohash prefix 또는 H3 이웃 셀을 구해 원형을 충분히 덮는 후보 영역을 만듭니다.

3후보 조회

cell + category shard와 cache를 조회해 제한된 POI ID·좌표·version만 가져옵니다.

4정책·정확 거리

공개 상태를 먼저 확인한 뒤 Haversine/PostGIS로 반경 밖 후보를 제거합니다.

5랭킹·최소 응답

거리·품질·영업 상태를 반영하고 카드에 필요한 필드와 coarse 관측만 남깁니다.

04 · INDEX CHOICES

공간 후보, 정본, 복합 검색의 책임을 섞지 않는다

# 대안 비교

하나의 엔진이 모든 요구를 만족하지 않습니다. 선택 기준은 “무엇이 빠른가”보다 정확 거리, 카테고리·텍스트 필터, index lag, 감사와 운영 복구를 어디에서 책임질지입니다.

선택장점제약적용 판단
Geohash prefix키-값 shard와 cache key에 단순경계·이웃 처리, 밀도 불균일초기 cell cover와 shard key
H3 cell계층·이웃·coarse 집계에 유리해상도·경계·라이브러리 운영 필요도시별 resolution과 분석 tier
Redis GEO원/상자 후보 탐색을 빠르게 실험정본·복합 권한·감사에 부족hot cache 또는 단순 조회 tier
PostGIS정밀 거리와 SQL 조건 결합hot read 단독 대응은 쿼리 계획 검증 필요정본, 정확 fallback, 검증 쿼리
OpenSearch geo텍스트·속성·geo filter 조합색인 지연·relevance·shard 비용발견 검색·복합 필터 tier
거리 우선설명 가능하고 privacy baseline이 단순장소 품질을 반영하지 못함기본 정렬과 relevance 비교 기준
05 · FAILURE MODES

경계·신선도·고밀도 도시의 실패를 따로 복구한다

# 장애 8가지
index lag / version gap

새 POI가 늦게 보이거나 이전 위치가 후보 인덱스에 남습니다.

대응 · outbox 재처리와 version compare로 indexer를 복구하고, 정본 표본과 lag 0을 검증합니다.
hot cell stampede

도심의 한 셀에 request와 고밀도 후보가 몰려 cache miss와 fanout이 증폭됩니다.

대응 · single-flight, child cell split, category shard, stale 후보와 per-cell budget을 적용합니다.
이웃 cell 누락

커버 계산이 경계의 장소를 빼서 반경 안인데 0건 또는 누락 결과가 납니다.

대응 · boundary golden test와 canary로 검출하고 cover algorithm을 rollback합니다.
×거리/좌표 순서 오류

lat·lng 순서나 단위 오류로 반경 밖 장소가 반환되거나 전체가 사라집니다.

대응 · fail-closed, 좌표 범위 검증, Haversine·PostGIS cross-check로 막습니다.
!정책 tombstone 지연

숨김·폐업 장소가 stale cache나 색인에서 잠시 노출될 수 있습니다.

대응 · read-time deny cache, purge 재시도, revoke-to-hide SLO로 대응합니다.
cache / Redis 장애

fallback이 정본에 쏠려 검색 tier까지 timeout이 전파될 수 있습니다.

대응 · circuit breaker, candidate cap, rate limit, 제한된 fallback과 error budget을 둡니다.
shard 불균형

일부 도시·카테고리의 후보 수만 커져 tail latency가 왜곡됩니다.

대응 · per-cell QPS·candidate P99로 감지하고 re-shard·replica·resolution을 조정합니다.
$외부 provider quota

Places 보강 호출이 quota·SKU·FieldMask 변경으로 실패하거나 비용이 뛰어오릅니다.

대응 · 최소 FieldMask, quota alarm, provider breaker와 자체 정본 fallback을 사용합니다.
06 · OPERATIONS

privacy·관측·비용은 셀 인덱스 밖의 제품 계약이다

# 운영
보안·위치 개인정보

정확 위치는 목적·동의·보존 기간을 분리하고, 기본 trace와 장기 분석에는 coarse region을 씁니다. RBAC·감사 로그·radius/page 상한으로 운영자·스크래핑 위험도 함께 줄입니다.

precise location ≠ default log
관측 가능성

tier별 p99, cache hit, cover cell 수, 후보 before/after filter, index lag, revoke-to-hide, hot cell, fallback ratio를 region·radius bucket 차원에서 봅니다.

nearby_latency_ms{tier}
비용 모델

cell 해상도는 인덱스 행·재색인을, 후보 수는 CPU를, 도시 replica는 RAM·egress를 키웁니다. 외부 Places는 FieldMask·SKU·정책 준수를 별도 비용 축으로 계산합니다.

index + cache + compute + provider
면접 모드 · 추가 질문06:00
“5,000만 POI에서 사용자의 1 km 안 카페를 찾아 주세요. Geohash/H3와 PostGIS·Redis·OpenSearch를 어떻게 나누고, 도심 hot cell, 정확한 원형 경계, 폐업 장소, 위치 privacy를 어떤 순서로 설명하겠습니까?”
cell 후보 + exact distance정본과 파생 indexcategory before rankhot cell splitcoarse observability
SOURCES

공식·1차 출처와 설계 가정

NEXT CASE STUDY주변 친구 서비스 설계
EDITORIAL NOTES

작성·검토·참고 자료

콘텐츠 원칙
이 문서는 독립적으로 재작성한 한국어 학습 자료입니다. 사실과 학습용 설계 가정을 구분합니다.
최종 검토
예상 학습 시간
24분

참고 자료

  • Google Maps Platform — Nearby Search (New): type, 원형 `locationRestriction`, `rankPreference`, POST/FieldMask 계약의 공식 문서.
  • Google Maps Platform — Policies and attributions for Places API: Places 콘텐츠의 캐싱·저장 예외와 attribution·privacy policy 요구사항.
  • Redis — GEOSEARCH: 원 또는 상자 내부 member를 조회하는 명령, 단위와 복잡도 공식 문서.
  • PostGIS — ST_DWithin: geometry/geography 거리 판정과 geography 미터 단위, spatial index 후보 사용에 대한 공식 문서.
  • OpenSearch — Geographic and xy queries: `geo_point`, geo bounding box, geodistance, geoshape 등 geographic query 공식 문서.
  • H3 — Indexing functions: `latLngToCell`로 좌표를 지정 해상도 셀로 변환하는 H3 공식 문서. 이 글의 DAU·QPS·SLO, TTL, 샤드 기준, 랭킹 식, fallback 순서와 retention 기간은 공개 벤치마크가 아니라 학습용 **설계 가정/제안**이다. 실제 서비스는 POI 밀도·법률·동의 UX·공급자 계약·부하와 장애 실험으로 이를 재검증해야 한다.

사실 오류·출처 정정은 문의·정정 페이지로 알려 주세요.