buildrisk-radar

ADR-020 지도 데이터 — 경계와 값 분리 · 버전 URL · HTTP 캐시

배경 단계구분도는 시군구 경계 230개(100 m 단순화)와 지표 값으로 그린다. 처음 만든 GET /regions/geojson?metric= 은 지표마다 같은 경계를 다시 실어 한 번에 1.95 MB(gzip 546 KB)를 보냈다 — 지역 지표 11개를 둘러보면 수 MB 를 받는다. 그런데 경계는 boundaryLoadJob 을 다시 돌릴 때만 바뀌고(연 1회 수준), 값은 매월 바뀐다. 바뀌는 주기가 다른 두 데이터를 한 응답에 묶고 있었다.

결정

Redis 대신 프로세스 안 캐시로 바꾼 이유 (2026-09-26 부하 시험) 처음에는 경계 JSON 을 Redis 조회 캐시에 두었다. 이 캐시는 값을 JSON 으로 직렬화해 저장하므로 문자열 응답이 JSON 문자열 리터럴로 한 번 더 감싸져, 요청마다 1.9 MB 를 Redis 에서 읽고 이스케이프를 풀고 다시 UTF-8 로 인코딩 · 압축했다. 옛 /regions/geojson 을 섞은 부하에서 api 의 힙 밖 메모리(네트워크 버퍼)가 급증해 1 GB 컨테이너 한도를 넘었다(VERIFICATION 47~49번). 버전 키로 불변인 값이므로 인스턴스마다 한 번 만들면 되고, Redis 를 거칠 이유가 없다. 옛 /regions/geojson(지표 값 + 경계를 매번 1.9 MB)은 화면이 쓰지 않고 요청 하나로 큰 응답을 만들 수 있는 경로라 삭제했다.

결과 지표를 바꿀 때 받는 양 546 KB → 약 5 KB. 경계는 버전당 한 번(gzip 약 530 KB), 재방문은 304. 최악 조건(50 VU 가 캐시 없이 경계 전체를 반복 수신)에서도 205 req/s · 111 MB/s · 오류 0, api 메모리 1 GB 한도 안.

대안