Geuneul — Summer Survival Map — Hong Seong Ju
← Projects

Complete · Personal project

Geuneul — Summer Survival Map

A map service that combines more than 150,000 public POIs, PostGIS spatial search, and real-time reports to help people find nearby shelter during heat waves and rain.

Current status Development ended after the web app, API, PWA, and AWS infrastructure were implemented and verified. The public URL and repository remain available as completed evidence.

Desktop view of Geuneul showing the place list and map side by side
Desktop view of Geuneul showing the place list and map side by side
ROLEEnd-to-end ownership of product, data, backend, and infrastructure
ACTIVITYPersonal project
Public POIs150k+
Radius p95~1.4s

Verified scope

Contribution boundaries and evidence

Direct role
End-to-end ownership of product, data, backend, and infrastructure
Team boundary
Solo project
Evidence visibility
Public repositories and evidence
Contribution evidence
  • 168 commits
  • 117 PRs
  • Public Terraform and performance evidence

Problem

Public data exists, but on a hot day it is still difficult for users to decide quickly where they can go nearby. I unified different nationwide datasets into one location model and built a service that presents distance together with recent reports.

Simply placing locations on a map was not enough. Users need to judge whether a place is within walking distance, whether they can actually rest there, whether recent reports exist, and whether it suits rain or extreme heat. The service connects public POIs, user reports, weather, and amenity signals in one discovery flow.

I built an idempotent ETL pipeline using the natural key source + source_external_id, so repeated runs do not create duplicates. Radius search, nearest-neighbor kNN, and map-bounds queries use PostGIS and GiST indexes. I examined execution plans and tail latency with EXPLAIN ANALYZE and k6.

Nationwide datasets differ in identifiers, coordinates, and update schedules. The pipeline preserves the source and external ID as a natural key and upserts records so ingestion can be rerun safely. Each location is stored once as geometry(Point, 4326); meter-radius and nearest-neighbor queries use a geography(geom) expression index, while current-map bounds use the geometry GiST path.

In a before-and-after production record using the same four-VU, 70-second, read-only gentle load, moving the Fargate task from 0.25 to 0.5 vCPU reduced radius-search p95 from about 2.68 seconds to 1.39 seconds and kNN from 238 ms to 98 ms. These figures diagnose the bottleneck under that data and small-load condition; they do not establish maximum throughput or universal end-user latency.

Real-time behavior and product boundaries

Report changes flow from PostgreSQL LISTEN/NOTIFY to the server’s SSE stream. I treated cross-instance event delivery and client resynchronization after a disconnected stream as separate boundaries. The survival score computes signals in SQL and combines them in a Java policy, keeping data selection separate from product rules rather than mixing both in one query.

Infrastructure

Terraform declares the VPC, public and private subnets, ECS Fargate, ECR, RDS/PostGIS, ElastiCache, ALB, CloudFront, S3, EventBridge, and OIDC deployment permissions. The frontend runs on Vercel, and the API is served through CloudFront.

The ECS service scales from a minimum of 1 task to a maximum of 3 using a 60% CPU target. GitHub Actions assumes its deployment role through OIDC instead of using a long-lived AWS key. ADRs capture CloudFront-to-ALB origin access, RDS encryption, backup and restore, and observability cost so the infrastructure can be explained as a set of operating decisions rather than only as a diagram.

Completed state

I published and verified the web app, API health endpoint, PWA installation path, and signed APK, completing the planned development scope. The public demo, code, design records, and performance evidence remain available for review, but there is no active feature roadmap. Data freshness and continuous infrastructure availability are not guaranteed after completion.

Limitations

The performance numbers come from a production before-and-after restricted to four VUs for 70 seconds with no writes. They do not establish large-load capacity, long-term variance, or absolute latency for every user environment.

Some shade and amenity information depends on public-data update times and user reports. “150,000 places” describes collection coverage; it does not mean that every location’s current condition is guaranteed in real time.

Engineering records

Work logs and troubleshooting

The public repository's README, architecture, DEPLOY, ADRs, and work log are the sources of truth for the completed result. The blog links selected performance, data, and operations cases centered on the problem and its validation.