Kakao Map SwiftUI에서 지도 드래그/카메라 이동 이벤트 감지

안녕하세요 현재 swiftUi로 네트워크통신을 통해 받아온 데이터를 핀으로 표시해줬는데
지도 드래그/카메라 이동 이벤트 감지될때 카메라 위치에 따라서 중심값을 위도, 경도로 받아서 다시 네트워크 통신해서 데이터를 핀으로 보여주고 싶습니다
CameraEventHandlerSample을 보면서 만들었는데 드래그할때 작동하지가 않습니다
혹시 제가 작성한 코드에 이상한 점이 있을까요??
SDK 버전 : 2.10.5 / ID: 1131361

import SwiftUI
import UIKit
import KakaoMapsSDK

struct ContentView: View {
@State private var draw: Bool = false
@State private var placeData: KakaoPlace?
@State private var selectedIndex: Int = 0
@State private var selectedCategoryCode: String = CategoryCode.cafe.rawValue

let buttonLabel = ["카페", "음식점", "숙소", "관광지", "병원", "미용"]

var body: some View {
    VStack {
        placeButtonScrollView()
        KakaoMapView(draw: $draw, placeMapData: $placeData, selectedCategoryCode: $selectedCategoryCode)
            .onAppear {
                print()
                self.draw = true
                if placeData == nil {
                    print("Calling fetchInitialData()🥹🥹🥹🥹🥹")
                    fetchInitialData()
                }
            }
            .onDisappear {
                self.draw = false
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}
func fetchInitialData() {
    print("fetchInitialData")
    guard let latitude = Double(UserDefaultsManager.shared.latY),
          let longitude = Double(UserDefaultsManager.shared.lonX) else {
        print("위치 정보가 저장되어 있지 않습니다.")
        return
    }

// selectedIndex = 0 // 카페 버튼 선택
// selectedCategoryCode = CategoryCode.cafe.rawValue // 기본 카테고리 카페 설정
fetchDataForCoordinates(latitude: latitude, longitude: longitude, categoryCode: selectedCategoryCode)

}
func placeButtonScrollView() -> some View {
    ScrollView(.horizontal, showsIndicators: false) {
        HStack {
            ForEach(0..<buttonLabel.count, id: \.self) { index in
                Button(action: {
                    selectedIndex = index
                    let category = CategoryCode.category(index: index)
                    selectedCategoryCode = category.rawValue
                   
                    print("Button \(index + 1) clicked - Category: \(category)")
                    guard let latitude = Double(UserDefaultsManager.shared.latY),
                          let longitude = Double(UserDefaultsManager.shared.lonX) else {
                        print("위치 정보가 저장되어 있지 않습니다.")
                        return
                    }
                    
                    // 네트워크 요청 보내기
                    fetchDataForCoordinates(latitude: latitude, longitude: longitude, categoryCode: selectedCategoryCode)
                }) {
                    Text("\(buttonLabel[index])")
                        .padding()
                        .background(selectedIndex == index ? Color.white : Color.blue)
                        .foregroundColor(selectedIndex == index ? Color.blue : Color.white)
                        .cornerRadius(10)
                        .overlay(
                            RoundedRectangle(cornerRadius: 10)
                                .stroke(Color.blue, lineWidth: 2)
                        )
                }
            }
        }
        .padding()
    }
    .frame(height: 50)
}
func fetchDataForCoordinates(latitude: Double, longitude: Double, categoryCode: String) {
        let query: String
        if selectedIndex <= 3 {
            query = "애견동반"
        } else if selectedIndex == 4 {
            query = "동물"
        } else if selectedIndex == 5 {
            query = "반려동물미용"
        } else {
            query = "애견동반"
        }

        let router = PlaceRouter.searchKeyword(query: query, page: 1, category: categoryCode, sort: "distance", longitude: longitude, latitude: latitude)
        PlaceNetworkManager.shared.placeRequest(router: router) { result in
            DispatchQueue.main.async {
                switch result {
                case .success(let placeData):
                    self.placeData = placeData
                   // ㅊ.   print("Fetched new data: \(placeData)")
                case .failure(let error):
                    print("Error: \(error.localizedDescription)")
                }
            }
        }
    }

}

struct KakaoMapView: UIViewRepresentable {
@Binding var draw: Bool
@Binding var placeMapData: KakaoPlace?
@Binding var selectedCategoryCode: String

func makeUIView(context: Self.Context) -> KMViewContainer {
    let view: KMViewContainer = KMViewContainer(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
    
    context.coordinator.createController(view)
    return view
}

func updateUIView(_ uiView: KMViewContainer, context: Self.Context) {
    if draw {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            if context.coordinator.controller?.isEnginePrepared == false {
                context.coordinator.controller?.prepareEngine()
            }
            
            if context.coordinator.controller?.isEngineActive == false {
                context.coordinator.controller?.activateEngine()
            }
            
            if let placeMapData = placeMapData {
                print("placeMapData available:☠️☠️☠️☠️☠️ ")
                DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                    context.coordinator.addMarkers(placeMapData)
                }
            } else {
                print("placeMapData is nil👎🏻👎🏻👎🏻👎🏻👎🏻👎🏻👎🏻👎🏻👎🏻")
            }
        }
    } else {
        context.coordinator.controller?.pauseEngine()
        context.coordinator.controller?.resetEngine()
    }
}
func makeCoordinator() -> KakaoMapCoordinator {
    return KakaoMapCoordinator(selectedCategoryCode: selectedCategoryCode)
}

static func dismantleUIView(_ uiView: KMViewContainer, coordinator: KakaoMapCoordinator) {
    
}

class KakaoMapCoordinator: NSObject, MapControllerDelegate {
    var longitude = Double(UserDefaultsManager.shared.lonX) ?? 0.0
    var latitude = Double(UserDefaultsManager.shared.latY) ?? 0.0
    var controller: KMController?
    var container: KMViewContainer?
    var first: Bool
    var auth: Bool
    var selectedCategoryCode: String = CategoryCode.cafe.rawValue
    var existingPoiIDs: [String] = []
    var cameraStartHandler: DisposableEventHandler?
    var cameraStoppedHandler: DisposableEventHandler?
    var _defaultCameraPosition: CameraUpdate?
    
    init(selectedCategoryCode: String) {
        self.first = true
        self.auth = false
        self.selectedCategoryCode = selectedCategoryCode
        super.init()
    }
    func removeExistingMarkers() {
        guard let kakaoMap = controller?.getView("mapview") as? KakaoMap else {
            return
        }
        guard let layer = kakaoMap.getLabelManager().getLabelLayer(layerID: "PoiLayer") else {
            return
        }
        
        for poiID in existingPoiIDs {
            layer.removePoi(poiID: poiID) {
                print("기존 마커 제거 완료: \(poiID)")
            }
        }
        
        existingPoiIDs.removeAll()
    }
    func createController(_ view: KMViewContainer) {
        container = view
        controller = KMController(viewContainer: view)
        controller?.delegate = self
        addCameraEventHandlers()
    }
    func addCameraEventHandlers() {
        guard let view = controller?.getView("mapview") as? KakaoMap else {
            print("KakaoMap 객체를 가져오지 못했습니다.")
            return
        }
        cameraStoppedHandler = view.addCameraStoppedEventHandler(target: self) { param in
            // KakaoMap 객체를 직접 가져오기
            if let mapView = self.controller?.getView("mapview") as? KakaoMap {
                // 카메라가 멈추면 좌표 가져오기
                let position = mapView.getPosition(CGPoint(x: 0.5, y: 0.5))
                print("카메라 이동 멈춤. 현재 위치: 경도: \(position.wgsCoord.longitude), 위도: \(position.wgsCoord.latitude)")
                
                // 새로운 좌표로 네트워크 요청
                self.moveToLocationAndFetchData(latitude: position.wgsCoord.latitude, longitude: position.wgsCoord.longitude)
            } else {
                print("Failed to get KakaoMap view")
            }
        }
        
    }
    func createPois() {
        print("createPois")
        let view = controller?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        let layer = manager.getLabelLayer(layerID: "PoiLayer")
        layer?.visible = true
        
        let poiOption = PoiOptions(styleID: "PerLevelStyle")
        poiOption.rank = 0
        poiOption.clickable = true
        
        let poi1 = layer?.addPoi(option: poiOption, at: MapPoint(longitude: longitude, latitude: latitude))
        poi1?.show()
        
        layer?.showAllPois()
        print("Poi created at: \(longitude), \(latitude)")
    }
    
    func addViews() {
        let defaultPosition: MapPoint = MapPoint(longitude: longitude, latitude: latitude)
        let mapviewInfo: MapviewInfo = MapviewInfo(viewName: "mapview", viewInfoName: "map", defaultPosition: defaultPosition)
        
        
        if controller?.addView(mapviewInfo) == nil {
            print("지도 뷰 추가 실패")
        } else {
            controller?.addView(mapviewInfo)
            print("지도 뷰 추가 성공")
        }
        
    }
    // 지도 드래그/카메라 이동 이벤트 감지
    func mapView(_ mapView: KMViewContainer, cameraDidMoveTo coord: MapPoint) {
        let currentLatitude = coord.wgsCoord.latitude
        let currentLongitude = coord.wgsCoord.longitude
        print("지도 중심 좌표가 변경되었습니다. 위도: \(currentLatitude), 경도: \(currentLongitude)")
        
        // 지도 드래그가 끝나면 새로운 좌표로 네트워크 요청을 보내 데이터를 업데이트
        moveToLocationAndFetchData(latitude: currentLatitude, longitude: currentLongitude)
    }
    
    // 새로운 좌표에 대한 네트워크 요청
    func fetchDataForCoordinates(latitude: Double, longitude: Double, categoryCode: String) {
        let query: String
        switch selectedCategoryCode {
        case "cafe", "restaurant", "hotel", "tourist":
            query = "애견동반"
        case "hospital":
            query = "동물"
        case "beauty":
            query = "반려동물미용"
        default:
            query = "애견동반"
        }
        
        let router = PlaceRouter.searchKeyword(query: query, page: 1, category: categoryCode, sort: "distance", longitude: longitude, latitude: latitude)
        PlaceNetworkManager.shared.placeRequest(router: router) { result in
            DispatchQueue.main.async {
                switch result {
                case .success(let placeData):
                    //print("새로운 좌표에 대한 데이터 가져오기 완료: \(placeData)")
                    // 데이터를 가져온 후 마커 업데이트
                    self.updateMapWithNewData(placeData)
                case .failure(let error):
                    print("데이터 가져오기 실패: \(error.localizedDescription)")
                }
            }
        }
    }
    
    func updateMapWithNewData(_ placeData: KakaoPlace) {
        // 새로운 데이터를 받아서 지도에 마커 업데이트
        print("updateMapWithNewData")
        removeExistingMarkers()
        addMarkers(placeData)
    }
    
    func addMarkers(_ placeData: KakaoPlace) {
        removeExistingMarkers()
        createTextStyle()
        
        guard let view = controller?.getView("mapview") as? KakaoMap else {
            print("Failed to get KakaoMap view or mapview is not KakaoMap type")
            return
        }
        let manager = view.getLabelManager()
        var layer = manager.getLabelLayer(layerID: "PoiLayer")
        
        if layer == nil {
            let layerOption = LabelLayerOptions(layerID: "PoiLayer", competitionType: .none, competitionUnit: .symbolFirst, orderType: .rank, zOrder: 10001)
            layer = manager.addLabelLayer(option: layerOption)
        }
        
        // 새로운 마커 추가
        for place in placeData.documents {
            guard let longitude = Double(place.x), let latitude = Double(place.y) else {
                print("Invalid coordinates for place: \(place.placeName)")
                continue
            }
            
            print("Adding marker for place: \(place.placeName), at \(longitude), \(latitude)")
            
            let poiID = "poi_\(place.id)"
            let poiOption = PoiOptions(styleID: "customStyle1", poiID: poiID)
            poiOption.rank = 0
            poiOption.addText(PoiText(text: place.placeName, styleIndex: 0))
            
            let poi = layer?.addPoi(option: poiOption, at: MapPoint(longitude: longitude, latitude: latitude))
            poi?.show()
            
            // 새로운 마커 ID 저장
            existingPoiIDs.append(poiID)
        }
    }
    func createTextStyle() {
        guard let view = controller?.getView("mapview") as? KakaoMap else {
            print("Failed to get KakaoMap view or mapview is not KakaoMap type")
            return
        }
        
        let manager = view.getLabelManager()
        let resizedImage = UIImage(named: "pin")?.resize(to: CGSize(width: 24, height: 24))
        let iconStyle = PoiIconStyle(symbol: resizedImage, anchorPoint: CGPoint(x: 0.0, y: 0.5))
        var textLineStyles = [PoiTextLineStyle]()
        
        for i in 0...4 {
            let textStyle = TextStyle(
                fontSize: 20,
                fontColor: UIColor.white,
                strokeThickness: 2,
                strokeColor: UIColor.black,
                //font: "Noto Sans KR Bold",
                charSpace: i,
                lineSpace: 1.0 + Float(i) * 0.2,
                aspectRatio: 0.6 + Float(i) * 0.2
            )
            let textLineStyle = PoiTextLineStyle(textStyle: textStyle)
            textLineStyles.append(textLineStyle)
        }
        
        let poiTextStyle = PoiTextStyle(textLineStyles: textLineStyles)
        poiTextStyle.textLayouts = [.center]
        
        let poiStyle = PoiStyle(styleID: "customStyle1", styles: [PerLevelPoiStyle(iconStyle: iconStyle, textStyle: poiTextStyle, level: 0)])
        manager.addPoiStyle(poiStyle)
    }
    
    func addViewSucceeded(_ viewName: String, viewInfoName: String) {
        print("OK")
        let view = controller?.getView("mapview")
        view?.viewRect = container!.bounds
    }
    
    func containerDidResized(_ size: CGSize) {
        let mapView: KakaoMap? = controller?.getView("mapview") as? KakaoMap
        mapView?.viewRect = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: size)
        if first {
            let cameraUpdate: CameraUpdate = CameraUpdate.make(target: MapPoint(longitude: longitude, latitude: latitude), mapView: mapView!)
            mapView?.moveCamera(cameraUpdate)
            first = false
        }
    }
    
    func authenticationSucceeded() {
        auth = true
    }
    func setDefaultOptions() {// 정북방향으로 카메라 방향을 초기화시킨다.
        print("처음위치으로 이동!!!")
        guard let view = controller?.getView("mapview") as? KakaoMap else {
            print("Failed to get KakaoMap view or mapview is not KakaoMap type")
            return
        }
        view.cameraAnimationEnabled = true    //카메라 애니메이션 활성화. 애니메이션을 비활성화하면 animateCamera를 호출해도 moveCamera 처럼 애니메이션 없이 바로 이동한다.
        view.setBackToNorthDuringAutoElevation(true)    //활성화시 Auto Elevation 동작시 정북방향으로 카메라 방향을 초기화시킨다.
        
        _defaultCameraPosition = CameraUpdate.make(mapView: view)   //현재 뷰의 카메라 위치를 기억하는 CameraUpdate 객체를 생성.
    }
    
    func moveToCurrentLocation() { //현재위치로 지도 카메라 이동
        guard let latitude = Double(UserDefaultsManager.shared.latY),
              let longitude = Double(UserDefaultsManager.shared.lonX) else {
            print("유저 위치 정보를 불러오지 못했습니다.")
            return
        }
        
        guard let view = controller?.getView("mapview") as? KakaoMap else {
            print("Failed to get KakaoMap view or mapview is not KakaoMap type")
            return
        }
        let cameraUpdate = CameraUpdate.make(target: MapPoint(longitude: longitude, latitude: latitude), zoomLevel: 15, mapView: view)
        
        // 카메라 애니메이션과 함께 현재 위치로 이동
        view.animateCamera(cameraUpdate: cameraUpdate, options: CameraAnimationOptions(autoElevation: true, consecutive: true, durationInMillis: 2000))
    }
    
    // 지도 이동 후 새로운 위치로 데이터 요청 및 마커 업데이트
    func moveToLocationAndFetchData(latitude: Double, longitude: Double) {

// guard let kakaoMap = controller?.getView(“mapview”) as? KakaoMap else {
// print(“카카오 맵을 찾을 수 없습니다.”)
// return
// }
//
// let cameraUpdate = CameraUpdate.make(target: MapPoint(longitude: longitude, latitude: latitude), zoomLevel: 15, mapView: kakaoMap)
//
// // 카메라 애니메이션으로 새로운 위치로 이동
// kakaoMap.animateCamera(cameraUpdate: cameraUpdate, options: CameraAnimationOptions(autoElevation: true, consecutive: true, durationInMillis: 2000)) {
// // 카메라 이동 완료 후 네트워크 요청
// print(“카메라 이동 완료! 새로운 좌표에 대한 네트워크 요청 시작”)
// self.fetchDataForCoordinates(latitude: latitude, longitude: longitude, categoryCode: self.selectedCategoryCode)
// }
fetchDataForCoordinates(latitude: latitude, longitude: longitude, categoryCode: selectedCategoryCode)
}

}

}
extension UIImage {
func resize(to size: CGSize) → UIImage? {
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
self.draw(in: CGRect(origin: .zero, size: size))
let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resizedImage
}
}

@소영1776
올리신 코드상에 카메라 이벤트와 관련된 부분은 보이지 않습니다. 이벤트 받는 부분을 추가하신 것이 맞나요?