콘텐츠로 이동

MSG-356 지도 축소 시 격자 집계 조회 (줌아웃 클러스터링)

티켓: MSG-356 · 작성일: 2026-08-10 · 작성: prd-writer 상태: 검토됨 (2026-08-10 팀원 K 승인 — 집계 단위는 행정 3단(동/구/시), 레이어는 점령 격자 조회 경로만, bbox는 단위별 차등으로 확정. 500m 묶음은 실측 후 확장 지점)

1. 문제 상황

지도 홈을 축소해도 서버에는 개별 100m 격자 조회밖에 없다. 넓은 시야에서 점령 격자가 수백에서 수천 개면 전량을 내려보내며 페이지를 넘기는데, 화면은 그 밀도를 읽지 못하고 전송량만 커진다. 지도 홈 디자인에는 줌아웃 클러스터링[^1] 화면이 있는데 그걸 받쳐 줄 조회가 서버에 없는 상태다.

2026-08-08 멘토링(정리 cf-33685556, 13·14·15·18절)이 방향을 확정했다. 축소 상태에서 100m 격자 전량 전송은 비효율이므로 축척에 따라 집계 표현으로 전환하고, 서버가 적당히 압축한 집계를 내려주면 프론트가 마커[^2] 병합으로 마무리한다. 전환 지점은 줌 레벨 숫자가 아니라 화면당 약 100객체 기준으로 실측해 정한다.

기존에 FE 연동 가이드(8/7)가 적어 둔 "클러스터는 프론트 로컬 산술" 서술은 멘토링 이전 결정이라 이 티켓이 대체한다 (2026-08-10 사용자 지시).

2. 목적 · 목표

  • 목적: 축소한 시야에서도 도감 분포를 한눈에 보여주되, 전송량과 화면 객체 수를 읽을 수 있는 수준으로 유지한다.
  • 목표:
  • FE가 집계 단위(동, 구, 시)를 파라미터로 골라, 뷰포트[^3] 안 점령 격자의 단위별 집계 목록(이름, 대표 좌표, 격자 수)을 한 번에 받는다
  • 친구 도감 레이어도 같은 조회로 집계를 받는다
  • 어느 단위로 묶어 세어도 개별 격자 조회와 총합이 일치한다
  • 구현 후 FE와 함께 전환 기준(화면당 객체 수)을 실측해 기록으로 남긴다 (티켓 완료 조건)
  • 비목표(스코프 제외):
  • 서버가 전환 줌을 정하는 것: 전환은 FE 몫이다. 합의된 축척[^4] 기준은 100m대 개별 격자, 250m~500m 동, 1km~8km 구, 16km~전체 시 (2026-08-10 FE 합의). 서버는 단위 파라미터만 받고 전환점을 갖지 않는다
  • 격자 시프트(500m 묶음) 클러스터: 이번에 만들지 않는다. 멘토링 사다리(13절)의 "중간 집계" 단계를 의도적으로 생략하는 결정이라, 서버가 내려주는 가장 촘촘한 집계는 동 단위가 된다. 동 마커가 너무 성기다는 실측이 나오면 집계 단위 하나를 추가하는 확장으로 대응한다 (2026-08-10 확정)
  • 핫구역 집계: 상위 50개 제한이라 화면당 객체 수 기준을 이미 만족한다. 묶을 것이 없다
  • 전체 공개 지도(타인 데이터 합산): 프라이버시 미확정 그대로 Phase 2
  • 개별 격자 조회의 계약 변경: MSG-73/90 계약 불변

3. 기능 요구사항

ID 요구사항 우선순위
FR-1 사용자는 뷰포트와 집계 단위(동, 구, 시)를 지정해 그 범위 안 자기 점령 격자의 단위별 집계 목록을 페이지 없이 한 번에 받는다 Must
FR-2 집계 항목마다 단위 이름(예: 부전2동, 부산진구, 부산광역시), 마커 표시용 대표 좌표, 점령 격자 수가 담긴다 Must
FR-3 집계의 격자 수 합은 같은 뷰포트 개별 격자 조회의 총 개수와 일치한다. FE가 항목을 더 묶어 합산해도 값이 어긋나지 않는다 Must
FR-4 친구 도감 레이어도 같은 집계를 받는다. 친구 관계 검증은 기존 친구 뷰포트 조회와 동일하게 요청 시점 실시간이다 Must
FR-5 점령 격자가 없는 단위는 응답에 포함되지 않는다. 뷰포트 안에 점령 격자가 하나도 없으면 빈 목록으로 200 응답한다 Must
FR-6 집계 조회의 뷰포트 허용 폭은 단위별로 다르게 두며, 시 단위는 전국 시야까지 허용한다. 개별 격자 조회의 0.5도 상한은 그대로다 (구체 수치는 스펙에서) Must
FR-7 행정동이 판정되지 않은 격자(해상 등)도 집계 총합에서 누락되지 않는다. 어떤 항목으로 묶을지는 스펙에서 정한다 Must

4. 비기능 요구사항

분류 요구사항
성능 시 단위 전국 시야가 가장 많은 행을 스캔한다. 이 경우에도 기존 뷰포트 조회 응답 목표(p95 300ms)를 준용한다. 신규 성능 목표는 세우지 않는다
보안/인가 본인 집계는 로그인 토큰으로, 친구 집계는 ACCEPTED 관계를 요청 시점에 검증한다 (기존 친구 레이어와 동일 정책)
데이터 정합 집계와 개별 조회의 총합 일치(FR-3), 미판정 격자 포함(FR-7)이 정합 기준이다
운영 스키마 변경 없이 기존 데이터(격자의 행정동 라벨과 인덱스)로 성립할 것으로 본다. 마이그레이션이 필요해지면 스펙에서 판단한다

5. 시퀀스 다이어그램

시퀀스 다이어그램
시퀀스 다이어그램

6. 클래스 다이어그램

신규와 변경 타입만. 이름은 스펙에서 확정한다.

클래스 다이어그램
클래스 다이어그램

7. 변경 파일 목록

파일 변경 Owner
src/main/java/com/msg/fillmap/grid/controller/GridController.java 수정 (집계 엔드포인트 추가) A
src/main/java/com/msg/fillmap/grid/service/GridQueryService.java (+Impl) 수정 (계약 메서드 추가, 기존 2종 불변) A
src/main/java/com/msg/fillmap/grid/repository/ 수정 (집계 쿼리 추가) A
src/main/java/com/msg/fillmap/grid/dto/ 신규 (집계 응답 DTO) A
src/main/java/com/msg/fillmap/friend/controller/FriendController.java 수정 (친구 집계 엔드포인트, 위임) B
src/main/java/com/msg/fillmap/friend/service/FriendServiceImpl.java 수정 (위임 추가) B
src/test/java/com/msg/fillmap/grid/, friend/ 신규 테스트 A / B

마이그레이션 없음 예상. 집계 재료는 이미 있다. 격자마다 행정동 코드가 저장되어 있고 (MSG-167), 행정동 이름이 "부산광역시 부산진구 부전2동" 전체 경로 형식이라 구와 시 이름도 저장된 데이터에서 나온다 (코드 앞자리가 구와 시를 가리키는 행정동 코드[^5] 체계).

8. 미해결 질문

  • [ ] 디자인 미확인: 피그마 월 조회 한도 소진(2026-08-07)으로 줌아웃 클러스터 화면을 실측하지 못했다. 마커 표기 형식(이름과 개수 병기 여부 등)은 FE 몫이지만, 응답 필드가 그 조립에 충분한지 스펙 전에 확인한다
  • [ ] 행정동 미판정 격자(FR-7)를 어떤 항목으로 묶을지 (별도 항목으로 낼지, 제외 불가만 보장할지)
  • [ ] 구와 시 마커의 대표 좌표 산출 기준. 스펙 몫이되 FE 마커 위치와 얽히면 FE와 합의

[^1]: 클러스터링: 지도를 축소했을 때 낱개 마커를 개수 딸린 묶음 마커로 합쳐 보여주는 기법. [^2]: 마커: 지도 위에 찍는 표시점. 여기서는 "부전2동 31"처럼 이름과 개수를 단 집계 표시. [^3]: 뷰포트: 지금 화면에 보이는 지도 영역. 남서와 북동 두 모서리 좌표로 표현한다. [^4]: 축척: 지도 축소 정도를 나타내는 눈금(스케일 바). 250m, 1km처럼 화면 눈금 길이가 실제 몇 미터인지로 읽는다. [^5]: 행정동 코드: 행정안전부의 10자리 행정동 식별 코드. 앞 2자리가 시도, 앞 5자리가 시군구를 가리켜 코드만으로 상위 단위를 알 수 있다.