Jetpack Compose로 Google Map과 ARCore 연동하기: 카메라 방향 화살표 UI 만들기 🗺️ AR

최근 Jetpack Compose를 사용하여 안드로이드 앱을 개발하던 중 흥미로운 아이디어가 떠올랐습니다. 바로 Google Map 위에 AR(증강현실)을 오버레이하여, 내가 바라보는 방향을 화살표로 알려주는 기능이었죠. 이 포스트는 그 아이디어를 현실로 만들어가는 과정을 기록한 것입니다.
1단계: 목표 설정 및 현재 진행 상황
나의 목표: ARCore 예제를 참고해서 Google Map을 Compose로 보여주고, 그 위에 ARCore가 제시하는 정보를 활용해서 내가 바라보는 방향을 향해 화살표를 렌더링하는 UI를 구성하고 싶어. 현재는 Google Map에 나의 마지막 위치를 얻어서 표시하는 기능까지는 구현했어. 이번에 하고 싶은 것은 ARCore의 Session 정보를 활용해서 View를 하나 띄우고 카메라가 바라보는 방향으로 화살표가 가도록 만들어 보고 싶어.
목표는 명확했습니다. 이미 구현된 지도 위에 AR 뷰를 띄우고, ARCore 세션에서 얻은 카메라의 방향 값으로 3D 화살표를 실시간으로 움직이는 것이죠.
2단계: ARCore와 Jetpack Compose 통합하기
가장 먼저 부딪힌 문제는 '어떻게 Jetpack Compose 환경에서 AR 뷰를 자연스럽게 통합할 것인가?' 였습니다. 검색 결과, sceneview-android 라이브러리가 사실상의 표준이라는 것을 알게 되었습니다. 이 라이브러리는 ARCore와 3D 렌더링 엔진인 Filament를 Compose에서 쉽게 사용할 수 있도록 도와줍니다.
구현 계획
- 의존성 추가:
build.gradle파일에sceneview-android라이브러리를 추가합니다. - 뷰 중첩:
BoxComposable을 사용해GoogleMap위에ARScene을 오버레이합니다. - 3D 모델 준비: 화면에 표시할
.glb형식의 3D 화살표 모델을 준비하여assets폴더에 넣습니다. - 카메라 방향 추적 및 렌더링:
ARScene의onFrame콜백을 이용해 매 프레임마다 ARCore 카메라의 위치와 방향을 얻어와 화살표 모델에 적용합니다.
구현 코드 예시
아래는 GoogleMap 위에 AR 화살표를 오버레이하는 전체 코드입니다.
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import com.google.maps.android.compose.GoogleMap
import com.google.maps.android.compose.Marker
import com.google.maps.android.compose.rememberCameraPositionState
import com.google.maps.android.compose.rememberMarkerState
import io.github.sceneview.ar.ARScene
import io.github.sceneview.ar.node.ArModelNode
import io.github.sceneview.ar.rememberARCameraNode
import io.github.sceneview.rememberEngine
import io.github.sceneview.rememberModelLoader
@Composable
fun ArMapScreen() {
val userLocation = LatLng(36.3504, 127.3845) // 대전시청 예시
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(userLocation, 15f)
}
Box(modifier = Modifier.fillMaxSize()) {
// 1. Google Map (배경)
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
) {
Marker(state = rememberMarkerState(position = userLocation), title = "My Location")
}
// 2. AR Scene (오버레이)
ArDirectionOverlay()
}
}
@Composable
fun ArDirectionOverlay() {
val engine = rememberEngine()
val modelLoader = rememberModelLoader(engine)
val cameraNode = rememberARCameraNode(engine)
val arrowNode = ArModelNode(engine).apply {
loadModelGlbAsync(
glbFileLocation = "models/arrow.glb", // assets 폴더 내 경로
onLoaded = { scale(0.3f) }
)
}
ARScene(
modifier = Modifier.fillMaxSize(),
nodes = listOf(cameraNode, arrowNode),
planeRenderer = false, // 바닥 감지 평면 끄기
onFrame = {
// 카메라 앞 1미터에 화살표 위치시키기
arrowNode.position = cameraNode.pose.transformPoint(floatArrayOf(0f, 0f, -1f))
// 화살표 방향을 카메라 방향과 일치시키기
arrowNode.rotation = cameraNode.rotation
}
)
}
3단계: 의존성 문제 해결하기
코드를 작성하고 의존성을 추가하는 과정에서 문제가 발생했습니다. 처음에는 com.google.ar:core만 추가하면 되는 줄 알았지만, sceneview-android 라이브러리가 필수적이라는 것을 깨달았습니다.
질문: 나는 이미 com.google.ar:core를 추가했는데, 따로 추가할 필요는 없는 건가?
이에 대한 답변은 명확했습니다. com.google.ar:core는 AR 기능의 핵심 '엔진'이고, sceneview-android는 이 엔진을 장착하여 Jetpack Compose에서 바로 운전할 수 있게 만든 '완성된 자동차'와 같다는 것입니다. sceneview-android를 사용하면 복잡한 렌더링과 UI 통합을 매우 쉽게 처리할 수 있습니다.
하지만 sceneview-android를 추가하자마자 더 큰 문제에 부딪혔습니다.
빌드 오류: Duplicate class ... found in modules ...
빌드 시 수많은 'Duplicate class' 오류가 발생했습니다. 오류 로그는 com.google.ar.sceneform.rendering.Color 같은 클래스가 서로 다른 두 라이브러리에서 중복으로 발견되었다고 알려주고 있었습니다.
Duplicate class com.google.ar.sceneform.rendering.Color found in modules rendering-1.17.1.aar (com.google.ar.sceneform:rendering:1.17.1) and sceneview-2.3.0.aar (io.github.sceneview:sceneview:2.3.0)
... (수많은 중복 클래스 오류)
원인 및 해결
원인은 명확했습니다. 제 프로젝트에 구글의 **오래된 Sceneform 라이브러리**와 새로운 SceneView 라이브러리가 동시에 포함되어 있었기 때문입니다. SceneView는 Sceneform의 업그레이드 버전이므로, 두 라이브러리 안에는 이름이 똑같은 클래스들이 가득했습니다.
해결 방법은 간단했습니다. build.gradle 파일에서 오래된 Sceneform 관련 의존성을 모두 제거하는 것이었습니다.
// build.gradle (Groovy)
dependencies {
// ...
// 아래와 같은 오래된 Sceneform 의존성들을 모두 삭제!
// implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.17.1'
// implementation 'com.google.ar.sceneform:rendering:1.17.1'
// 최신 SceneView 라이브러리만 남겨둡니다.
implementation("io.github.sceneview:arsceneview:2.3.0")
// ...
}
오래된 의존성을 제거하고 Gradle을 다시 동기화하자, 빌드 오류는 마법처럼 사라졌습니다.
결론
Jetpack Compose 환경에서 ARCore를 연동하는 것은 sceneview-android 라이브러리 덕분에 생각보다 어렵지 않았습니다. 특히 의존성 충돌 문제는 초기에 겪기 쉬운 함정이지만, 라이브러리 간의 관계만 잘 이해하면 쉽게 해결할 수 있었습니다. 이제 지도 위에 내가 바라보는 방향을 알려주는 AR 화살표가 성공적으로 나타납니다!
'모바일 앱(안드로이드)' 카테고리의 다른 글
| 30일 만에 Wear OS 앱 출시 (ft AI) (3) | 2025.08.25 |
|---|---|
| Android 앱 홍보, 더 쉽게 사용자에게 다가가는 방법: 앱 링크와 Play 스토어 공유! (ft 뤼튼의 이야기) (1) | 2025.08.23 |
| Firebase Storage 업로드 (Kotlin + Jetpack Compose) (4) | 2025.08.15 |
| Wear OS Tiles로 실시간 심박수와 운동 시간 표시하기 (1) | 2025.08.13 |
| Wear OS 타일로 실시간 심박수와 운동 시간 표시하기 (ft chatGPT, 예시코드) (2) | 2025.08.11 |