ARKit 공부
- Swift
- ARKit
- RealityKit
- SceneKit
ARKit

ARKit | Apple Developer Documentation
- ARKit은 Apple이 개발한 증강현실(AR) 프레임워크이다.
- ARKit을 통해 Swift을 사용한 iOS 앱에서 현실 세계에 가상 객체를 자연스럽게 오버레이 시킬 수 있다.
- 주요 기능
- ARKit은 환경 인식, 평면 감지, 이미지 및 객체 인식, 얼굴 트래킹, 라이트 추정 등의 기능을 통해 AR 경험을 지원한다.
ARSession이 카메라와 모션 데이터를 처리한다.ARWorldTrackingConfiguration으로현실 세계 추적을 관리한다.
단, ARKit을 사용하기 위해선 특정 하드웨어가 필요하다. (A9 이상)
iPhone 6 이후에 출시된 디바이스에서 동작한다. (iPhone SE, 6s, 6s + 등..)
ARKit 종류
1. Metal
Metal | Apple Developer Documentation
- Metal 프레임워크를 사용하면 앱이 기기의 그래픽 처리 장치(GPU)에 직접 접근할 수 있다.
- Metal을 통해 앱은 GPU를 활용하여 복잡한 요소를 빠르게 렌더링하고 연산 작업을 병렬로 실행할 수 있다.
→ RealityKit과 SpriteKit, Core Image 등 많은 Apple 프레임워크는 Metal의 성능을 활용한다.
2. SpriteKit
SpriteKit | Apple Developer Documentation
- SpriteKit 프레임워크를 사용하여 고성능의 배터리 효율적인 2D 게임을 개발할 수 있다.
- 맞춤형 OpenGL, ES 셰이더 및 조명, SceneKit과의 통합 가능
- 고급 물리 효과 및 애니메이션을 통해 역장을 추가하고 충돌을 감지하며 새로운 조명 효과 생성 가능
SpriteKit은 입자, 텍스트, 이미지 및 비디오룰 2차원으로 그리기 위한 범용 프레임워크이다.
Metal을 활용하여 고성능 렌더링을 진행할 수 있으며 게임 및 그래픽 집약적인 앱을 만들 수 있다.
풍부한 애니메이션을 지원하며 물리적 동작과 함께 시각적 요소 + 우아한 화면 전환 가능
⭐ SpriteKit은 GameplayKit, SceneKit과 같은 프레임워크와 잘 통합된다.
3. SceneKit

- Deprecated되었으니
RealityKit을 쓰자..
4. RealityKit
RealityKit | Apple Developer Documentation
- RealityKit 프레임워크는 생생한 렌더링과 카메라 효과, 애니메이션, 물리적인 요소를 갖추고
AR을 위해 새롭게 탄생된 도구 - 기본 Swift API와 ARKit의 통합, 사실적인 물리적 요소 기반의 렌더링, 변형 및 스켈레톤 애니메이션, 공간 오디오 및 강체 물리 요소를 통해 AR 개발을 어느 때보다 빠르고 쉽게 수행할 수 있게 해준다.
⭐ 다중 스레드 렌더링을 수행한다.
ARKit의 기본 구성 요소
- ARKit / RealityKit 구조 ✔️
- 벽 Raycast ✔️
- Anchor + 이미지 매핑 ✔️
- WorldMap 저장/복원 ✔️
- Occlusion 설정 (사람 + 메쉬) ✔️
- 아키텍처 분리 (ARManager / View / Picker) ✔️
1. ARSession
ARSession은 AR의 핵심이며 디바이스 와 카메라, 모션 데이터를 처리하고 실제 세계와 가상 컨텐츠를 동기화하는 역할을 수행한다.
import ARKit
let configuration = ARWorldTrackingConfiguration()
sceneView.session.run(configuration)
이때 sceneView 는 ARSCNView의 인스턴스이다.
ARWorldTrackfingConfiguration은 가장 일반적으로 사용되는 AR 구성이다.
2. ARFrame
ARFrame은 AR 세션의 현재 상태를 나타낸다.
각 프레임은 카메라 이미지, 디바이스의 위치 및 방향, 감지된 특징점 등의 정보를 포함한다.
쉽게 말하자면 ARFrame은 시간 단위, ARAnchor은 공간 단위(고정 기준점) 이다.
func session(_ session: ARSession, didUpdate frame: ARFrame) {
let transform = frame.camera.transform
let image = frame.capturedImage
// 프레임 정보를 활용하여 AR 컨텐츠 업데이트
}
-
session(_:didUpdate frame:)func session(_ session: ARSession, didUpdate frame: ARFrame) -
didUpdate는 AR 세션이 실행중일 때 호출되며
카메라 프레임이 갱신될 때마다 호출된다.
→ 보통 초당 60회라고 한다.
- 카메라의 실시간 위치 추적 및 방향 추적, 사용자 이동 감지, GPS + AR 좌표 보정을 담당하며
사람 segmentation과 depth를 처리한다. 조명 변화도 감지한다.
-
대표적으로 함께 사용되는 데이터
frame.camera.transform // 카메라 위치 & 회전 frame.camera.trackingState // 트래킹 상태 frame.capturedImage // 카메라 이미지 (CVPixelBuffer) frame.sceneDepth // LiDAR 깊이 정보 frame.smoothedSceneDepth // 노이즈 제거된 깊이 frame.lightEstimate // 조명 정보 -
💀 주의사항
→ 절대로 didUpdate에서 Entity를 생성하거나 파일 저장, 네트워크 요청을 진행해선 안된다.
→ 계산이나 상태 업데이트, 위치 추적 전용이므로 무거운 작업이 있을 경우 블로킹이 생길 수 있다.
-
session(_:didFailWithError:)func session(_ session: ARSession, didFailWithError error: Error) -
didFailWithError는 트래킹이 실패되거나 카메라 접근 불가, WorldTracking 초기화 실패했을 시 호출된다.
-
didFailWithError을 통해 사용자에게 안내 메세지를 표시하거나 ARSession을 재시작시킬 수 있고 관련된 오류를 로깅할 수 있다.
→ 예를 들어서.. “트래킹이 불안정합니다! 주변을 천천히 비춰주세요.” 같은 문구를 UI로 보여줄 수 있다.
3. ARAnchor
ARAnchor은 실제 세계의 특정 위치와 방향을 나타낸다.
⭐ 가상 객체를 실제 세계에 배치할 때 앵커를 사용한다. (가상 객체는 항상 ARAnchor를 기준으로 한다는 의미)
let anchor = ARAnchor(transform: transform)
sceneView.session.add(anchor: anchor)
-
session(_:didAdd anchors:)func session(_ session: ARSession, didAdd anchors: [ARAnchor]) -
didAdd는 새로운 앵커가 추가될 때 호출된다.
-
아니면 사용자가
session.add(anchor:)을 호출했을 때 호출된다. -
WorldMap이 로드 후 기존 앵커들이 복원될 때나 ARKit이 자동으로 Plane, Image, Object 앵커들을 감지했을 때도 호출된다.
-
didAdd는
가상 객체를 실제 공간에 배치할 때 사용되며저장된 앵커에 컨텐츠를 다시 올릴때도사용된다. -
session(_:didUpdate anchors:)func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) -
didUpdate는 기존 앵커의 위치, 크기, 방향이 업데이트될 때 호출된다.
또는 추적 정밀도가 올라갈 때 호출된다.
-
벽이나 바닥의 크기를 업데이트하거나 컨텐츠 위치를 조정할 때 활용된다.
-
session(_didRemove anchors:)func session(_ session: ARSession, didRemove anchors: [ARAnchor]) -
didRemove는
트래킹 불가로 앵커가 제거될 때,ARSession을 리셋시킬 때,WorldMap을 다시 로드할 때 호출된다. -
주로 화면에서 가상 객체를 제거하거나 메모리를 정리하거나 상태를 동기화하기 위해 활용된다.
4. ARHitTestResult
ARHitTestResult는 화면의 2D 점을 실제 세계의 3D 위치로 변환한 결과를 나타낸다.
⭐사용자의 터치 입력을 AR 공간의 위치로 변환할 때 유용하다
let tapLocation = sender.location(in: sceneView)
let hitTestResults = sceneView.hitTest(tapLocation, types: .existingPlaneUsingExtent)
if let result = hitTestResults.first {
let transform = result.worldTransform
// transform을 사용하여 가상 객체를 배치한다.
}
5. ARConfiguration
ARConfiguration은 AR 세션의 동작을 정의한다. 다양한 구성이 존재하는데 가장 일반적인 것은 ARWorldTrackfingConfiguration 이다.
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = [.horizontal, .vertical]
configuration.environmentTexturing = .automatic
sceneView.session.run(configuration)
6. ⭐ ARWorldMap

ARWorldMap | Apple Developer Documentation
Managing Session Life Cycle and Tracking Quality | Apple Developer Documentation
ARWorldMap은 ARKit에서 제공하는 클래스이다.
⭐ ARSession이 인식한 실제 공간을 하나의 데이터 구조로 캡쳐한 스냅샷 이다.
즉 카메라가 인식한 공간의 구조 + 디바이스의 위치 및 방향 + ARAnchor 들의 상대적 위치 정보를 함께 저장한다.
- ARWorldMap은 ARWorldTrackingConfiguration의 전용 데이터이다.
→ 월드 좌표계(world coordinate system)의 상태를 그대로 보존한다.
→ 동일한 공간에서 다시 AR 세션을 시작하면 이전과 동일한 위치에 AR 컨텐츠를 복원할 수 있다.
💀 AR 공간 자체를 저장하는 것이 아닌 “공간을 인식한 결과”를 저장하는 것이다.
- 주요 기능
- 공간 저장(스냅샷 캡처)
ARSession.getCurrentWorldMap(_:)을 사용하여 현재 인식된 공간과 모든 ARAnchor을 저장한다.- 공간 복원(스냅샷 Restore)
ARWorldTrackingConfiguration.initialWorldMap을 통해 앱이 재실행되어도 동일한 AR 공간을 재현할 수 있다.- 기본 사용 흐름
- WorldMap 저장 흐름
- ARSession에서 현재 WorldMap을 요청한다.
- ARWorldMap을 NSKeyedArchiver로 직렬화시킨다.
- 파일 또는 로컬 저장소에 저장한다.
- WorldMap 로드 흐름
- 저장된 데이터를 NSKeyedUnarchiver로 복원한다.
- 복원한 데이터를
ARWorldTrackingConfiguration.initialWorldMap에 할당한다. - 세션을 재실행한다.
session.run
💀 ARWorldMap은 GPS 개념이 아니므로 다른 장소나 전혀 다른 공간에서는 의미가 없다.
- ⚠️ ARWorldMap의 한계
- 동일한 물리적 공간에서만 유효하다.
- 환경이 크게 바뀌면 복원 정확도가 감소된다.
- 용량이 커질 수 있다.
- 실외 대규모 환경에는 부적합하다.
RealityKit의 주요 요소
1. raycast
RealityKit의 Scene에는 가상 광선(Ray)를 쏴서 엔티티 또는 충돌 지점과의 교차를 계산하는 레이 캐스트라는 메서드가 존재한다.
RealityKit의 raycast는 ARKit의 Raycast(현실 평면 탐지) 와는 다른 개념이다.
⭐ RealityKit의 raycast 는 이미 Scene 안에 존재하는 Entity(충돌 컴포넌트 포함) 를 대상으로 동작한다.
🤔 RealityKit의 raycast 메서드와 ARKit의 Raycast의 차이점
ARKit Raycast
ARKit의 Raycast는 실제 세계(현실 공간) 를 대상으로 한다.
카메라 화면의 한 지점이나 3D 방향으로 광선을 쏘아, 현실 세계의 표면(평면, 특징점 등) 을 감지한다.
특징
raycastQuery,raycast(_:),trackedRaycast등을 사용- 실제 환경의
existingPlane,estimatedPlane등을 탐지 - 결과로 얻은 위치에
ARAnchor또는AnchorEntity를 생성 - AR 추적(Tracking)과 강하게 결합됨
주 사용 목적
- 바닥 / 벽 / 책상 등 현실 표면 위에 가상 객체 고정
- AR 오브젝트 배치의 기준점 생성
RealityKit raycast
RealityKit의 scene.raycast는 가상 3D 장면 내부 를 대상으로 한다.
Scene 안에 존재하는 엔티티(Entity)의 Collision Shape 을 기준으로 광선 충돌 테스트를 수행한다.
특징
Scene.raycast(...)API 사용CollisionCastQueryType,CollisionGroup으로 필터링 가능CollisionCastHit결과 반환- ARKit 추적과는 독립적
주 사용 목적
- 가상 객체 터치 감지
- 가상 오브젝트 간 상호작용
- 버튼, UI, 물리 기반 인터랙션 처리
주요 차이점 정리
| 구분 | ARKit Raycast | RealityKit raycast |
|---|---|---|
| 대상 | 실제 세계의 표면 / 평면 | 가상 장면의 엔티티 |
| 동작 계층 | AR 추적 시스템 | 렌더링 / 물리 시스템 |
| API 위치 | ARSession, ARFrame, ARView | Scene, Entity |
| 결과 활용 | ARAnchor, AnchorEntity 생성 | 충돌 지점, 거리 계산 |
| 주요 목적 | 현실 공간에 AR 오브젝트 고정 | 가상 객체 상호작용 |
한 줄 요약
- ARKit Raycast → 현실을 맞춘다
- RealityKit raycast → 가상을 맞춘다
raycast(origin:direction:length:query:mask:relativeTo:)

한 점(origin)에서 한 방향(direction)으로 정해진 거리(length)만큼 레이저(Ray)를 발사한다.
→ 레이저를 직접 투과하거나 시선을 추적하거나, 카메라 정면 방향으로 맞은 객체를 찾을 때 사용한다.
→ 1인칭 AR 인터랙션이나 거리 제한이 명확할 때 사용된다.
-
단, 방향 벡터를 직접 계산해야해서 수학적 제어가 매우 강하다.
```swift // 카메라 정면으로 raycast 진행 let origin = cameraTransform.translation let direction = cameraTransform.matrix.forwardVector let results = arView.scene.raycast( origin: origin, direction: direction, length: 5.0 ) ``` -
raycast(from:to:query:mask:relativeTo:)
developer.apple.com/documentation/realitykit/scene/raycast(from:to:query:mask:relativeto:

시작점(from)과 끝점(to)를 명시하여 두 점을 잇는 선분(line segment) 기준으로 raycast를 진행한다.
- 두 객체 사이의 가시성을 판단하거나, 특정 두 위치간 방해물을 체크하거나, 계산된 좌표 기반 인터랙션을 수행시킬 때 활용한다.
→ 방향 계산은 따로 필요 없으며 결과 예측이 직관적이다.
```swift
// 카메라에서 특정 오브젝트로
let start = cameraTransform.translation
let end = targetEntity.position(relativeTo: nil)
let results = arView.scene.raycast(
from: start,
to: end
)
```