<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Juntiger</title><description>Build notes and engineering retrospectives.</description><link>https://juntiger.pages.dev/en/</link><language>en</language><lastBuildDate>Mon, 29 Jun 2026 00:00:00 GMT</lastBuildDate><atom:link href="https://juntiger.pages.dev/en/rss.xml" rel="self" type="application/rss+xml"/><item><title>Not Simply Trusting API Requests That Come From Outside the App</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/20-app-attest-app-origin-trust/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/20-app-attest-app-origin-trust/</guid><description>I used App Attest to check app-origin trust and treated state-changing requests with extra care.</description><pubDate>Tue, 23 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Rechecking an iOS App on Small iPhones After Looking Only at Large Screens</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/19-ios-visual-qa-small-iphones/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/19-ios-visual-qa-small-iphones/</guid><description>A record of turning discomfort missed in iPhone 17 Pro Max-centered testing into device- and language-based visual QA.</description><pubDate>Tue, 23 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Healthcheck Was Normal, but Notifications Were Not Safe Yet</title><link>https://juntiger.pages.dev/en/engineering/hangangjari-ops/healthcheck-push-recovery-gap/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari-ops/healthcheck-push-recovery-gap/</guid><description>After recovering from K3s DiskPressure, stale parking snapshots were compared like immediate previous values and pushed; I fixed it with a freshness guard</description><pubDate>Fri, 19 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>The Widget Was Not a Smaller Version of the App</title><link>https://juntiger.pages.dev/en/blog/hangangjari-series/08-widget-as-product-surface/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/blog/hangangjari-series/08-widget-as-product-surface/</guid><description>How Hangangjari kept glanceable values and stale-state cues within iOS widget refresh constraints.</description><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Numbers Alone Were Not Enough to Trust Public Data</title><link>https://juntiger.pages.dev/en/blog/hangangjari-series/07-public-data-trust/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/blog/hangangjari-series/07-public-data-trust/</guid><description>Why remaining spaces and congestion needed sources, updated times, and explicit unknown states beside them.</description><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Why I Focused on the Han River Instead of Expanding Nationwide</title><link>https://juntiger.pages.dev/en/blog/hangangjari-series/06-why-focus-hangang/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/blog/hangangjari-series/06-why-focus-hangang/</guid><description>I chose a scope I could verify directly and explain responsibly over a broader park app.</description><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Turning a Home Server Into a Production Environment</title><link>https://juntiger.pages.dev/en/blog/hangangjari-series/05-infra-launch-and-retrospective/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/blog/hangangjari-series/05-infra-launch-and-retrospective/</guid><description>A record of adding deployment, observability, and backup routines to a home server and reaching an App Store launch.</description><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Why the App Did Not Call Public Data Directly</title><link>https://juntiger.pages.dev/en/blog/hangangjari-series/04-backend-cache-and-workers/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/blog/hangangjari-series/04-backend-cache-and-workers/</guid><description>How slow collection, prediction, and notification preparation moved into server workers so the screen could stay light.</description><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>An iOS Experience That Had to Continue Before Opening the App</title><link>https://juntiger.pages.dev/en/blog/hangangjari-series/03-ios-client-and-widgets/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/blog/hangangjari-series/03-ios-client-and-widgets/</guid><description>How widgets, notifications, deep links, and local cache kept the same park state connected.</description><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Why the Parking App Became a Hangang Visit App</title><link>https://juntiger.pages.dev/en/blog/hangangjari-series/02-product-scope-and-data-trust/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/blog/hangangjari-series/02-product-scope-and-data-trust/</guid><description>The product decisions behind adding events, congestion, facilities, and notices while separating car and general screens.</description><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>The Hangang Parking Widget I Built After Buying a Car</title><link>https://juntiger.pages.dev/en/blog/hangangjari-series/01-origin-and-parking-widget/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/blog/hangangjari-series/01-origin-and-parking-widget/</guid><description>How I reduced the parking checks I repeated before leaving into an app home screen and widget.</description><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Hangangjari System Overview</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/00-system-overview/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/00-system-overview/</guid><description>How collection, API, cache, and widgets share responsibility for the user&apos;s first screen</description><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Running a Mini-PC Server Like a Real Service</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/18-public-sre-retrospective/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/18-public-sre-retrospective/</guid><description>A retrospective on separating user request paths, GitOps state, observability, and backups</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Telemetry That Does Not Send Location Coordinates to the Server</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/17-privacy-minimal-telemetry/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/17-privacy-minimal-telemetry/</guid><description>For a login-free app, I first decided what not to collect and kept only operational signals</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Public-Data Translation Cache and Preserving Source Text</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/16-localization-source-and-translation-cache/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/16-localization-source-and-translation-cache/</guid><description>I separated UI strings, curated translations, machine translations, and Korean fallback</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Push Outbox and Suppression Audit</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/15-push-suppression-outbox-delivery-audit/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/15-push-suppression-outbox-delivery-audit/</guid><description>I recorded sent notifications and stopped notifications with their reasons in the same system</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Why Parking Forecasts Need Confidence</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/14-parking-forecast-baseline-confidence-backtest/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/14-parking-forecast-baseline-confidence-backtest/</guid><description>I used p10, p50, p90, risk, and backtests so forecasts do not look like one correct answer</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Keeping Stale Responses from Looking Fresh: Redis Cache</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/13-redis-hot-stale-cache-fallback/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/13-redis-hot-stale-cache-fallback/</guid><description>I separated fast responses from last-success values so cache does not mislead users</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>source catalog and ingestion run</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/12-source-catalog-and-ingestion-runs/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/12-source-catalog-and-ingestion-runs/</guid><description>I separated collection plans from execution results to explain freshness and failures by source</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Bundling First-Screen Values into One Response: home-summary</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/11-home-summary-api-contract/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/11-home-summary-api-contract/</guid><description>I put parking, outing, forecast, and source status into one response so the app and widgets start from the same values</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Snapshot Storage for WidgetKit</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/10-widget-snapshot-architecture/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/10-widget-snapshot-architecture/</guid><description>I let widgets outside the app safely read the last display value and refresh state</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>The Order I Check When Data Looks Stale</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/09-infrastructure-and-observability/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/09-infrastructure-and-observability/</guid><description>I narrowed stale-data causes by checking the edge, API, workers, cache, and DB in order</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Leaving Deployment as Records, Not Memory</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/08-ci-cd-and-release/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/08-ci-cd-and-release/</guid><description>Tests, images, desired state, and migration order became one repeatable release path</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>What I Filtered Before Sending Push Notifications</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/07-push-notification-architecture/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/07-push-notification-architecture/</guid><description>Subscription settings, quiet hours, freshness, and audit records choose what not to send first</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>How Not to Present Forecasts as Current Values</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/06-forecast-and-data-science/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/06-forecast-and-data-science/</guid><description>Forecast workers, confidence, and backtests expose uncertainty before arrival</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>A Parser That Separates No Data From Collection Failure</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/05-data-parsing-and-source-policy/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/05-data-parsing-and-source-policy/</guid><description>Official source grades, schema drift, and ingestion runs explain why a screen is empty</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Workers and CronJobs Running Outside the API</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/04-workers-and-jobs/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/04-workers-and-jobs/</guid><description>Collection, forecasts, push, and reference-data sync run separately from user requests</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>How I Split Responsibilities Between Postgres and Redis</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/03-cache-and-db-architecture/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/03-cache-and-db-architecture/</guid><description>Records and audit trails stay durable, while rebuildable responses live in cache</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>Designing Thin FastAPI Routes</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/02-backend-api-architecture/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/02-backend-api-architecture/</guid><description>HTTP routes handle requests and responses while screen composition moves into application use cases</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item><item><title>How the SwiftUI App and WidgetKit Read the Same State</title><link>https://juntiger.pages.dev/en/engineering/hangangjari/01-ios-client-architecture/</link><guid isPermaLink="true">https://juntiger.pages.dev/en/engineering/hangangjari/01-ios-client-architecture/</guid><description>A structure where SwiftData and App Group snapshots keep values consistent outside the app</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><atom:updated>2026-06-29T00:00:00.000Z</atom:updated></item></channel></rss>