Skip to content

[FEAT] 카카오 맵 기본 사용환경 구성#58

Merged
casper-jr merged 41 commits into
OurMenu:developfrom
casper-jr:feat/kakaomap
May 18, 2025
Merged

[FEAT] 카카오 맵 기본 사용환경 구성#58
casper-jr merged 41 commits into
OurMenu:developfrom
casper-jr:feat/kakaomap

Conversation

@casper-jr

@casper-jr casper-jr commented Apr 2, 2025

Copy link
Copy Markdown
Member

🚀 이슈번호

✏️ 변경사항

  • 카카오 맵 사용 위한 의존성 추가
  • 카카오맵을 Compose에서 사용하기 위한 MapViewWithLifecycle 작성
  • 지도 관련 response, service, repository 작성
  • AddMenuScreen, SearchMenuScreen에 지도 컴포넌트 배치
    <5/15 기준 업데이트된 부분들>
  • 기존 pr commet 반영, dto에서의 type 오류 수정
  • 지도 관련 함수들을 ViewModel로 이동
  • 사용자가 추가한 메뉴들에 대한 검색 화면인 SearchMenuScreen에서 지도를 통한 메뉴 불러오기 구현(기본적인 기능 구현된 상태이고, 세부 내용은 이후 pr에서 수정할 예정입니다)
  • AddMenuScreen의 경우 수정된 부분이 있으나 지도 관련 코드만 수정되었고 기능적으로는 이전과 차이는 없습니다

📷 스크린샷

SearchMenuScreen

Screen_Recording_20250515_072235_OurMenu.mp4

✍️ 사용법

  • ViewModel에서 카카오맵 관련 작업들을 수행합니다.

🎸 기타

  • 카카오맵에서 svg로 된 이미지를 지도의 핀(라벨)로 사용하는 것이 지원되지 않고, 이외의 이미지 파일의 경우 정상적으로 지도에 표시됩니다
  • 화면에서의 세부 디테일은 이후 pr에 반영해두도록 하겠습니다. (핀, 칩 정보들, BottomSheet 높이)
  • 카카오맵 레퍼런스가 없어서 클릭 리스너 같은 부분은 코드베이스 그냥 뒤져보면서 찾았는데 쉽지 않네요
  • SAY NO TO KAKAOMAP
    image

@ikseong00 ikseong00 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

좋습니당

Comment on lines +15 to +18
val response = mapService.getMapDetail(
mapId = mapId
).handleBaseResponse().getOrThrow()
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

runCatching 자체가 블록의 마지막 구문을 반환하는 거여서,

response 라는 변수를 생성해서 할당하지 않아도 정상적으로 원하는 값이 반환이 될 것 같아요.

suspend fun getMapDetail(
    mapId: Int
) = runCatching {
    mapService.getMapDetail(mapId = mapId).handleBaseResponse().getOrThrow()
}

@Serializable
data class MapDetailResponse(
@SerialName("menuId")
val menuId: Int,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Api 명세서 상에는 기술되어 있지 않지만 Swagger 상 $Int64 으로 되어있는 거를 Long 타입이라도 답변 받았습니다!
그래서 Id 관련 및 $Int64 로 되어있는 필드에는 Long 타입으로 변경해야 할 것 같아요.

@casper-jr casper-jr requested a review from ikseong00 May 14, 2025 22:38
@casper-jr casper-jr added ♻️ refactor This doesn't seem right 👌 OK Merge and removed ❌ No Merge labels May 14, 2025

@ikseong00 ikseong00 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

좋습니당.

viewModelScope 가 필요한 지 ,
LaunchedEffect 에서 기본 CoroutineScope 인지 , rememberCoroutineScope() 를 사용해야 하는 상황인 지 확인해주시면 감사하겠습니다.

}

@Composable
fun MapViewWithLifecycle(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

image

반환값이 있는 컴포저블 함수의 경우에는 소문자로 시작하는게 좋을 것 같습니다!

import kotlinx.coroutines.flow.StateFlow

class MapController {
val _kakaoMap = MutableStateFlow<KakaoMap?>(null)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

private 빠진 것 같아용

Comment on lines +100 to +121
fun moveCamera(latitude: Double, longitude: Double) {
viewModelScope.launch {
mapController.kakaoMap.value?.let { map ->
val cameraUpdate = CameraUpdateFactory.newCenterPosition(LatLng.from(latitude, longitude))
map.moveCamera(cameraUpdate)
updateCurrentCenter()
}
}
}

// 지도 중앙 좌표 업데이트
fun updateCurrentCenter() {
viewModelScope.launch {
mapController.kakaoMap.value?.let { map ->
val center = map.cameraPosition?.position
_currentCenter.value = center
if (center != null) {
Log.d("SearchMenuViewModel", "현재 지도 중심 좌표: ${center.latitude}, ${center.longitude}")
}
}
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

이 부분에서 viewModelScope 를 쓰지 않아도 될 것 같습니다.

  • kakaMap 이라는 Flow 를 collect 하지 않고 , 그 시점에서의 값만 사용.
  • cameraPosition 을 이동하는 함수는 suspend 함수가 아님.

Comment on lines +130 to +156
// 지도에 핀 추가
fun addMarker(latitude: Double, longitude: Double, resourceId: Int) {
viewModelScope.launch {
mapController.kakaoMap.value?.let { map ->
val style = map.labelManager?.addLabelStyles(
LabelStyles.from(LabelStyle.from(resourceId))
)
val options = LabelOptions.from(LatLng.from(latitude, longitude)).setStyles(style)
map.labelManager?.layer?.addLabel(options)
map.setOnLabelClickListener { kakaoMap, labelLayer, label ->
// TODO: 핀 클릭시 동작 정의
Log.d("SearchMenuViewModel", "핀 클릭됨")
moveCamera(latitude = label.position.latitude, longitude = label.position.longitude)
true
}
}
}
}

// 지도의 전체 핀 제거
fun clearMarkers() {
viewModelScope.launch {
mapController.kakaoMap.value?.let { map ->
map.labelManager?.layer?.removeAll()
}
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

요기도 필요없을 거 같아요

Comment on lines +237 to +251
// 지도에 검색 결과 핀 추가
fun showSearchResultOnMap() {
viewModelScope.launch {
clearMarkers()
searchResult.value?.forEach { store ->
val latitude = store.storeMapY
val longitude = store.storeMapX
addMarker(latitude, longitude, R.drawable.img_popup_dice)
Log.d("SearchMenuViewModel", "마커 추가: ${store.storeTitle} lat: (${latitude}, long: ${longitude})")
}
// 첫 번째 검색 결과로 카메라 이동
searchResult.value?.get(0)?.let { moveCamera(it.storeMapY, it.storeMapX) }
}
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

여기도 코루틴 불필요

Comment on lines +89 to +91
launch {
viewModel.getCrawlingHistory()
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

rememberCoroutineScope() 없이 그냥 기본값의 CoroutineScope 를 선언하면 해당 key 값이 변경될 때 마다
내부의 코루틴 Job 이 삭제되고 새로운 코루틴이 생성될 것 같습니다. (getCrawlingHistory() 함수가 key 값 변경에 따라

  • getCrawlingHistory() 실행 중 searchBarFocused 가 변하는 경우
  1. rememberCoroutineScope() 사용 시 -> 그대로 유지됨.
  2. 사용 X -> 코루틴이 취소되고 다시 새로운 getCrawlingHistory() 를 실행하는 코루틴이 생성됨.

혹시 위 코드 구현 시 2번을 염두하고 구현을 하신 걸까요 ??

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

아직 세부작업까지는 진행하지 않아서 놓친 것 같습니다. 반영해서 수정 후 merge하도록 하겠습니다

@casper-jr casper-jr merged commit df4daef into OurMenu:develop May 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ feat Good for newcomers 👌 OK Merge ♻️ refactor This doesn't seem right 🦦재우

Projects

Status: Waiting For Reviews

Development

Successfully merging this pull request may close these issues.

[FEAT] 카카오맵 사용환경 구성

2 participants