2026/04/25

오늘의 이야기

 


 


📍 Jetpack Compose + ARCore + Google Maps로 위치 기반 AR 구현하기


가이드앱 초안 이미지



 


ARCore의 Geospatial API는 GPS 좌표와 같은 실제 세계의 위치를 기준으로 가상 객체를 배치할 수 있는 기능을 제공합니다. 본 게시물에서는 Jetpack ComposeGoogle Maps Compose를 활용해 지도와 AR 콘텐츠를 동시에 표시하는 방법을 소개합니다.


💡 이 예제는 관광지 안내, 실외 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 내비게이션


🚀 다음으로는 AR 오브젝트가 지도 위에 정확하게 위치하고, 거리/방향을 시각화하는 기능도 확장해보세요!




댓글 없음:

댓글 쓰기

오늘의 이야기

#스치니1000프로젝트 #재미 #행운기원 #Compose #Firebase 🎯 야 너 토요일마다 로또 확인하냐? 나도 맨날 “혹시나~” 하면서 봤거든 ㅋㅋ 근데 이제는 그냥 안 해 AI한테 맡겼어 🤖✨ 그것도 구글 Gemini로다가! ...