--- id: ios-visionos-basics title: visionOS — 공간 컴퓨팅 / RealityKit / Window category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [ios, visionos, vision-pro, realitykit, vibe-coding] tech_stack: { language: "Swift / SwiftUI / RealityKit", applicable_to: ["visionOS"] } applied_in: [] aliases: [visionOS, Vision Pro, immersive space, window group, RealityKit] --- # visionOS > Apple Vision Pro. **3가지 mode: Window (2D 패널) / Volume (3D 박스) / Immersive (전체)**. SwiftUI 같은 코드로 시작 가능. RealityKit 으로 3D. ## 📖 핵심 개념 - Window: 일반 SwiftUI window — visionOS 가 자동 floating panel. - Volume: 작은 3D 공간 (박스). - Immersive: 전체 환경 (mixed / full). - Eye + pinch: 보고 + 손가락 핀치 = 탭. ## 💻 코드 패턴 ### Window ```swift @main struct VisionApp: App { var body: some Scene { WindowGroup(id: "main") { ContentView() } // 일반 SwiftUI 작동 — 3D 공간 floating window } } ``` ### Volume (3D 컨테이너) ```swift WindowGroup(id: "globe") { GlobeView() } .windowStyle(.volumetric) .defaultSize(width: 0.5, height: 0.5, depth: 0.5, in: .meters) ``` ```swift struct GlobeView: View { var body: some View { Model3D(named: "Earth") { model in model.resizable().scaledToFit() } placeholder: { ProgressView() } } } ``` ### Immersive Space ```swift @main struct VisionApp: App { var body: some Scene { WindowGroup { ContentView() } ImmersiveSpace(id: "world") { ImmersiveView() } .immersionStyle(selection: .constant(.mixed), in: .mixed, .full) } } struct ContentView: View { @Environment(\.openImmersiveSpace) var open var body: some View { Button("Enter") { Task { await open(id: "world") } } } } ``` ### RealityKit (3D scene) ```swift struct ImmersiveView: View { var body: some View { RealityView { content in let earth = ModelEntity(mesh: .generateSphere(radius: 0.2)) earth.model?.materials = [SimpleMaterial(color: .blue, isMetallic: false)] earth.position = [0, 1.5, -1] content.add(earth) } update: { content in // 매 frame } } } ``` ### Gesture (RealityKit) ```swift RealityView { content in ... } .gesture( DragGesture() .targetedToAnyEntity() .onChanged { value in value.entity.position = value.convert(value.location3D, from: .local, to: value.entity.parent!) } ) ``` ### Hover 효과 ```swift Image(systemName: "heart") .hoverEffect(.lift) // 사용자가 보면 lift ``` ```swift .hoverEffect(.highlight) // 윤곽 ``` ### 안경 / 환경 감지 ```swift import ARKit let session = ARKitSession() let handTracking = HandTrackingProvider() try await session.run([handTracking]) for await update in handTracking.anchorUpdates { // hand pose } ``` ### Anchor ```swift let anchor = AnchorEntity(.hand(.left, location: .palm)) content.add(anchor) // 손에 따라다님 ``` ### Spatial audio ```swift let audioRes = try await AudioFileResource.load(named: "ambient.wav") let player = entity.prepareAudio(audioRes) player.gain = -10 player.play() ``` ### Eye tracking 권한 - Privacy 강함. Direct gaze 위치는 OS 처리, 앱은 hover 만. ### Sharing window between iOS / visionOS ```swift #if os(visionOS) .windowStyle(.volumetric) #endif ``` ## 🤔 의사결정 기준 | 콘텐츠 | mode | |---|---| | 기존 iPad app | Window (Compatible) | | 일반 productivity | Window | | 3D 모델 viewer | Volume | | 게임 / 몰입 | ImmersiveSpace | | AR 위 가상 객체 | Mixed immersion | | 완전 가상 | Full immersion | ## ❌ 안티패턴 - **iOS UI 그대로**: visionOS hover / spatial 활용 X. - **Eye tracking 데이터 수집 가정**: 가능 X. privacy. - **Modal 거대 화면 가운데**: Window depth 고려 + glass material 사용. - **Audio 평면 stereo**: spatial 권장. - **Hand tracking 없는 immersive**: 사용자 손 보임 — 방해. - **RealityKit ECS 무시 + Entity 만**: 큰 scene 성능. - **Glass material 안 사용**: visionOS UI 와 어색. ## 🤖 LLM 활용 힌트 - 시작 = Window (iOS app 그대로). - 3D = Volume + Model3D / RealityView. - 몰입 = ImmersiveSpace + RealityKit. ## 🔗 관련 문서 - [[iOS_SwiftUI_State_Property_Wrappers]] - [[iOS_Live_Activities]] - [[iOS_TipKit_Patterns]]