📍 Jetpack Compose + ARCore + Google Maps로 위치 기반 AR 구현하기
ARCore의 Geospatial API는 GPS 좌표와 같은 실제 세계의 위치를 기준으로 가상 객체를 배치할 수 있는 기능을 제공합니다. 본 게시물에서는 Jetpack Compose와 Google Maps Compose를 활용해 지도와 AR 콘텐츠를 동시에 표시하는 방법을 소개합니다.
1️⃣ 프로젝트 구성 및 의존성 추가
build.gradle.kts에 다음 라이브러리들을 추가합니다.
dependencies {
implementation("com.google.maps.android:maps-compose:4.1.1")
implementation("com.google.android.gms:play-services-maps:18.2.0")
implementation("com.google.ar:core:1.43.0")
}
추가적으로 ARCore
사용을 위한 권한 및 카메라 기능도 AndroidManifest에 설정해야 합니다.
2️⃣ ARCore 렌더러 구현 (ArCoreRenderer)
ARCore 프레임을 받아서 SurfaceView 위에 AR 객체를 렌더링하는 ArCoreRenderer
클래스를 작성합니다. Geospatial API를 통해 현재 위치의 위도, 경도, heading 값을 받아 지도 위치와 연동할 수 있습니다.
if (earth?.trackingState == TrackingState.TRACKING) {
val pose = earth.cameraGeospatialPose
Log.d("Geo", "Lat: ${pose.latitude}, Lng: ${pose.longitude}, Heading: ${pose.heading}")
}
지도의 좌표를 클릭했을 때 해당 위치에 Anchor를 생성해 AR 콘텐츠를 띄울 수 있습니다.
fun onMapClick(latLng: LatLng) {
val earth = session?.earth ?: return
if (earth.trackingState != TrackingState.TRACKING) return
earthAnchor?.detach()
earthAnchor = earth.createAnchor(
latLng.latitude, latLng.longitude, 0.0,
0f, 0f, 0f, 1f // 회전값 (Quaternion)
)
}
3️⃣ AR SurfaceView를 Compose에 포함시키기
Jetpack Compose에서는 AndroidView
를 통해 SurfaceView를 삽입합니다.
렌더링 준비가 완료되면 SampleRender
를 실행해 OpenGL 렌더링 루프를 시작합니다.
@Composable
fun ArSurfaceView(
modifier: Modifier = Modifier,
onSurfaceReady: (SurfaceView) -> Unit
) {
AndroidView(
factory = { context ->
val renderer = HelloArRenderer(
context = context,
sessionProvider = sessionProvider,
latLng = currentLocation?.let {
LatLng(
it.latitude,
it.longitude
)
} ?: LatLng(37.5665, 126.9780),
tapQueue = tapQueue // 🔥 renderer로 전달
) // 예시
sessionProvider.setOnRendererEventCallback { event ->
rendererEvent = event
}
sessionProvider.setOnTrackingMessageCallBack { message ->
trackingMessage = message
}
SampleRender(glSurfaceView, renderer, context.assets)
glSurfaceView.renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY
glSurfaceView
},
modifier = Modifier.fillMaxSize()
.pointerInteropFilter { motionEvent ->
if (motionEvent.action == MotionEvent.ACTION_UP) {
tapQueue.offer(motionEvent) // 🔥 터치 이벤트 큐에 전달
}
true
}
)
}
4️⃣ 지도와 AR 통합 Compose 화면 만들기
GoogleMap과 AR SurfaceView를 하나의 Compose 화면에 겹쳐서 배치합니다. 지도를 클릭하면 해당 좌표에 Anchor를 생성하고 AR로 렌더링합니다.
@Composable
fun ArWithMapScreen(activity: MainComposeActivity) {
val lifecycleOwner = LocalLifecycleOwner.current
val arRenderer = remember { ArCoreRenderer(activity) }
DisposableEffect(Unit) {
lifecycleOwner.lifecycle.addObserver(arRenderer)
onDispose { lifecycleOwner.lifecycle.removeObserver(arRenderer) }
}
Box(modifier = Modifier.fillMaxSize()) {
var clickedLatLng by remember { mutableStateOf<LatLng?>(null) }
GoogleMap(
modifier = Modifier.fillMaxSize(),
onMapClick = { latLng ->
clickedLatLng = latLng
arRenderer.onMapClick(latLng)
}
)
ArSurfaceView(
modifier = Modifier
.fillMaxSize()
.zIndex(1f),
onSurfaceReady = { surfaceView ->
SampleRender(surfaceView, arRenderer, activity.assets)
}
)
}
}
5️⃣ MainActivity 설정
Jetpack Compose와 ARCore를 통합한 MainActivity입니다. ArCoreSessionHelper
는 세션 초기화 및 생명주기 처리를 돕습니다.
@AndroidEntryPoint
class MainComposeActivity : ComponentActivity() {
lateinit var arCoreSessionHelper: ArCoreSessionHelper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arCoreSessionHelper = ArCoreSessionHelper(this)
arCoreSessionHelper.initialize()
setContent {
ArWithMapScreen(this)
}
}
override fun onResume() {
super.onResume()
arCoreSessionHelper.session?.resume()
}
override fun onPause() {
super.onPause()
arCoreSessionHelper.session?.pause()
}
}
✅ 마무리
Jetpack Compose로 Google Map과 ARCore를 동시에 사용할 수 있다는 점은 매우 큰 장점입니다. UI를 선언적으로 작성하면서도 실시간 위치 기반 AR 콘텐츠를 렌더링할 수 있어, 차세대 사용자 경험을 만드는 데 적합한 아키텍처입니다.
- 지도 기반 AR 관광 가이드
- 위치 기반 보물 찾기 게임
- 실외 AR 내비게이션
'모바일 앱(안드로이드)' 카테고리의 다른 글
외국인 관광객을 위한 앱 만들기 : 카테고리 검색 화면 구현 (6) | 2025.06.11 |
---|---|
외국인 관광객들은 한국에 와서 어떻게 여행 정보를 얻을까? (10) | 2025.06.09 |
외국인 관광객을 위한 앱 만들기 : Jetpack Compose에서 Google Maps로 실시간 위치 추적 및 야간 모드 적용하기 (0) | 2025.06.01 |
외국인 관광객을 위한 한국 여행 가이드 앱 개발 일지 - 위치 권한과 구글맵 화면 구현 (Jetpack Compose + Hilt) (1) | 2025.05.28 |
외국인관광객을 위한 다국어 환영 앱 첫 화면, Jetpack Compose로 구현하기 (4) | 2025.05.26 |