Skip to content

Conversation

@MuchanKim
Copy link
Collaborator

@MuchanKim MuchanKim commented Nov 19, 2025

📝 Summary

기존 거대한 NaverMapView의 코드를 기능단위로 쪼개 모듈화를 하였습니다. 그리고 facade로 맵에서 쓰는 여러 모듈을 추상화하여 네이버 맵에서 쓰도록 하였습니다.

우리가 쓰는 redux와 같이 맵에서도 일관된 방식으로 사용하기위해 가이드 문서도 첨부하였습니다.(docc)

🔨 What

커밋메시지랑 DocC에 다 담았습니다.

MapView (SwiftUI)
    ↓
NaverMapView (UIViewRepresentable)
    ↓
Coordinator (Delegate 처리)
    ↓
MapFacade (Facade 패턴)
    ↓
┌─────────────┬─────────────┬─────────────┬─────────────┐
│ Controller  │   Handler   │   Service   │   Updater   │
│             │             │             │             │
│ - Camera    │ - Touch     │ - Data      │ - Layer     │
│ - Location  │             │             │             │
└─────────────┴─────────────┴─────────────┴─────────────┘
                    ↓
              Manager (리소스 관리)

아키텍처 구조

폴더 구조

Sources/Util/NaverMap/
├── Controller/          # 제어 (카메라, 위치)
│   ├── MapCameraController.swift
│   └── MapLocationController.swift
├── Handler/             # 이벤트 처리 (터치)
│   └── MapTouchHandler.swift
├── Utility/             # 유틸리티
│   ├── MapDataService.swift      # 데이터 변환/조회
│   ├── MapLayerUpdater.swift     # 레이어 업데이트
│   └── MapTouchHandler.swift     # 터치 이벤트
├── Manager/             # 리소스 관리
│   ├── CaseLocationMarkerManager.swift
│   └── InfrastructureLayerManager.swift
├── Facade/              # Facade 패턴
│   └── MapFacade.swift
└── NaverMapView.swift   # SwiftUI 래퍼

컴포넌트 역할

  • Controller: 지도 제어 기능 (카메라 이동, 위치 추적)
  • Handler: 사용자 이벤트 처리 (터치, 제스처)
  • Service: 데이터 변환 및 조회 (순수 함수)
  • Updater: 레이어 및 UI 상태 업데이트
  • Manager: 리소스 관리 (마커, 오버레이)
  • Facade: 모든 컴포넌트를 통합하고 단순한 인터페이스 제공

👀 Review Notes

Facade를 쓰는 것이 가독성에는 좋으나 결국 중간 계층을 하나만들어서 통 추상화라 작업량이 미세하게 증가하는 부분이 있습니다. 불편하면 facade를 빼고 UIupdate 로직을 코디네이터에 포함해도 됩니다. 그렇지만 그러면 다시 맵코디네이터의 책임이 커지는 것 같아서리 헤헤

What?
- 맵에서 사용되는 매직넘버들을 Constants 파일로 이동시켰습니다.

Why?
- 관리되는 상태값들이 더 많아질 것인데 중앙 관리가 필요했음!
What?
- 사용자 위치 관리 및 초기 위치 설정의 책임을 가지는 MapLocationController를 구현했습니다.
  - startUpdatingLocation/stopUpdatingLocation: 위치 추적 제어
  - focusOnCurrentLocation: 현재 위치로 카메라 포커싱
  - CLLocationManagerDelegate: 위치 권한 및 업데이트 처리

Why?
- 책임 분리.
What?
- 카메라 이동 제어 및 중복 이동 방지 책임을 가지는 MapCameraController를 구현했습니다.
  - moveCamera: 좌표 기반 카메라 이동 (애니메이션 지원)
  - handleCameraIdle: 카메라 이동 완료 이벤트 처리
  - processCameraTarget: 명령 기반 카메라 이동 처리
What?
-맵 데이터 변환 및 조회 (순수 함수, stateless)의 책임을 가지는 MapDataService를 구현하였습니다.
  - makeVisitedCellMarkers(from:): 방문 데이터에서 셀 위치 추출 후 기지국 마커로 변환
  - findCellTitle(by:in:): 좌표 키로 기지국 셀 주소 조회
  - hash(for:visitFrequencyEnabled:): Location 배열의 해시 계산 (변경 감지용)
  - hash(for:): CellMarker 배열의 해시 계산 (변경 감지용)

상태를 가질 필요가 없어서 enum으로 주었습니다!
What?
- 맵 레이어 업데이트 중앙 관리 및 변경 감지 책임을 가지는 MapLayerUpdater를 구현하였습니다.
  - updateCaseLocations(locations:visitFrequencyEnabled:isVisible:zoomLevel:on:): CaseLocation 마커 업데이트 (home, work, custom, 방문 셀)
  - updateCellLayer(cellMarkers:isVisible:on:): 기지국 셀 레이어 업데이트
  - updateCellRangeOverlay(cellMarkers:coverageRange:isVisible:on:): 기지국 범위 오버레이 업데이트
  - updateCCTVLayer(cctvMarkers:isVisible:on:): CCTV 레이어 업데이트
  - updateMarkerVisibility(isCaseLocationVisible:isCellMarkerVisible:isCCTVVisible:): 마커 가시성 상태 추적 및 적용

- InfrastructureMarkerManager와 CaseLocationMarkerManager를 통한 실제 업데이트를 수행합니다.
What?
- 책임: 맵 터치 이벤트 처리 책임을 가지는 MapTouchHandler를 구현하였습니다.
  - handleMapTap(latlng:): 맵 터치 이벤트 처리
  - 터치 활성화 상태 확인
  - 마커 선택 해제
  - 타임라인 시트 최소화 요청 (NotificationCenter) < 이 부분은 미니가 시트관련 작업을 하면 수정 될 듯합니다.
  - 타임라인 시트 상태에 따른 PlaceInfoSheet 표시 제어

- 터치 활성화/비활성화 상태 관리
- 타임라인 시트 상태 추적
- 마커 선택 해제와 시트 제어 통합
What?
- 복잡한 맵 서브시스템(카메라, 위치, 레이어, 터치)을 단순한 인터페이스로 제공하는 파사드 패턴 도입.
- 모든 컴포넌트 생성 및 라이프사이클 관리
  - MapCameraController, MapLocationController, MapTouchHandler, MapLayerUpdater
- 통합 업데이트 메서드 (update)
  - 의존성 주입, 카메라 이동, 현위치 포커싱, 레이어 업데이트, 마커 선택 해제
- 콜백 설정 중앙화 (configureCallbacks)
  - 모든 컴포넌트 이벤트 콜백을 한 곳에서 관리
- Delegate 메서드 접근 (handleCameraIdle, handleMapTap)
- LayerData 구조체로 레이어 데이터 캡슐화

Why?
- NaverMapView.Coordinator의 과도한 책임으로 복잡도가 심각하게 증가하였습니다. 이로인해 updateUIView에서 모든 맵 로직이 혼재되어 유지보수 어려움을 겪었고, 컴포넌트 간 의존성 관리가 필요했습니다.
- 음... 이전 챌린지도 그렇고 의존성이 많아지면 파사드 같이 추상화해주는 패턴이 깔끔한 것 같아 도입해봄 ~@~#~
What?
- 맵 기능 추가에 대한 가이드 문서를 작성하였습니다.
- DocC를 위한 첫걸음.

Why?
- Redux도 그렇고 여러가지 일관된 패턴을 사용하려고 노력하고 있으나, 지켜지지 않는 부분들. 어려움을 겪는, 나만 아는 코드들!을 방지하기 위해 맵의 피처를 추가할 때 어떤 식으로 하면 될지에 대한 가이드 문서작성!!!!!!!!!!!!!!!!!
@MuchanKim MuchanKim self-assigned this Nov 19, 2025
@MuchanKim MuchanKim added ♻️ Refactor 전면 수정이 있을 때 사용합니다 🥬 Moo 김무찬 바 ~ 보 labels Nov 19, 2025
What?
- 사용되지 않는 success 변수를 와알드카드패턴으로 처리

Why?
- success 변수가 사용되지않아 노란 경고가 발생. 노 경 싫 어
Copy link
Member

@delightPIP delightPIP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다~~~!

@delightPIP delightPIP merged commit 05bd136 into main Nov 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🥬 Moo 김무찬 바 ~ 보 ♻️ Refactor 전면 수정이 있을 때 사용합니다

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[🛠️ Refactor] Map & NaverMap 모듈 분리

3 participants