UIKit Dynamics는 iOS(UIKit)의 물리 애니메이션 프레임워크로, View가 실제 물리 법칙(중력, 충돌, 탄성, 인력)에 따라 상호작용할 수 있게 합니다. 이 문서는 UIDynamicAnimator의 구성 요소, 동작(behavior) 유형 및 실제 사용 시나리오를 설명합니다.
주요 포인트
UIKit Dynamics는 Apple이 iOS 7(2013)에서 도입한 물리 시뮬레이션 프레임워크입니다. UIView.animate(선형 전환) 및 Core Animation(레이어 애니메이션)과 달리 UIKit Dynamics는 중력, 충돌, 힘, 탄성 및 마찰과 같은 실제 물리적 상호작용을 시뮬레이션합니다. 개발자가 UIDynamicAnimator에 동작을 추가하면 시스템이 각 프레임의 물리 계산을 자동으로 수행합니다.
이 프레임워크는 60/120 FPS로 작동하며 강체 시뮬레이션을 기반으로 하는 내장 물리 엔진을 사용합니다. UIKit Dynamics는 물리학이나 수학 지식이 필요하지 않습니다 — 준비된 동작을 적용하고 매개변수를 구성하기만 하면 됩니다.
Apple에 따르면 UIKit Dynamics는 UI 효과(카드 스택 애니메이션, 아이콘 흔들림, 인터페이스 물리)에 적합하지만 게임용으로 설계되지 않았습니다 — 게임에는 SceneKit 또는 SpriteKit을 사용하세요.
UIDynamicAnimator는 UIKit Dynamics의 핵심 클래스입니다. reference view(일반적으로 컨트롤러의 view)로 초기화되고 모든 활성 동작을 관리합니다. 각 프레임에서 UIDynamicAnimator는 물리 법칙에 따라 추가된 모든 요소의 위치, 속도 및 가속도를 다시 계산합니다.
addBehavior 메서드는 하나의 동작(또는 복잡한 UIDynamicBehavior)을 추가하고, removeBehavior는 이를 제거합니다. 애니메이터는 모든 객체가 정지 상태에 도달하면 자동으로 일시 중지됩니다(충돌 및 힘 없이 계속). 델리게이트 메서드 — UIDynamicAnimatorDelegate — 시뮬레이션의 일시 중지 및 재개를 알립니다.
물리에 참여하는 모든 객체는 UIDynamicItem 프로토콜을 구현해야 합니다. UIView 및 UICollectionViewLayoutAttributes는 이미 구현하고 있습니다. 프로토콜에는 bounds, center, transform 속성이 필요합니다. 객체가 사용자 정의인 경우 프로토콜을 수동으로 구현하세요.
UIKit Dynamics에는 7가지 내장 동작 유형이 포함되어 있으며, 각각 특정 물리 효과를 모델링합니다. 동작은 결합할 수 있습니다: 예를 들어, 중력 + 충돌 + 탄성은 떨어지고 튕기는 객체의 효과를 만듭니다.
| Behavior | 물리 효과 | 주요 매개변수 |
|---|---|---|
| UIGravityBehavior | 중력(힘 벡터) | gravityDirection (dx, dy), magnitude |
| UICollisionBehavior | 객체 및 경계 충돌 | collisionMode, translucence, collisionDelegate |
| UIAttachmentBehavior | 연결(스프링/케이블) | anchorPoint, length, damping, frequency |
| UISnapBehavior | 감쇠가 있는 스냅 | snapPoint, damping (0-1) |
| UIPushBehavior | 밀기/충격(연속 또는 즉시) | pushDirection, magnitude, mode |
| UIDynamicItemBehavior | 객체 물리 속성 | elasticity, friction, density, resistance |
| UIFieldBehavior | 힘 필드(소용돌이, 자기, 방사형) | position, strength, falloff, region |
현실적인 객체 물리를 위해서는 여러 동작이 동시에 필요합니다. 예를 들어, 떨어지는 카드의 경우: UIGravityBehavior(중력), UICollisionBehavior(바닥과 충돌), UIDynamicItemBehavior(탄성: 튕기기용 0.4). 모든 동작은 하나의 UIDynamicAnimator에 추가됩니다.
UIKit Dynamics용 Swift 코드는 UIDynamicAnimator를 생성하고 동작을 추가합니다. 아래 예제는 여러 객체가 있는 중력, 충돌 및 사용자 정의 물리 속성을 보여줍니다.
import UIKit
class PhysicsViewController: UIViewController {
var animator: UIDynamicAnimator!
override func viewDidLoad() {
super.viewDidLoad()
// 1. reference view로 애니메이터 생성
animator = UIDynamicAnimator(referenceView: view)
// 2. 떨어지는 객체 생성
let redView = UIView(frame: CGRect(x: 100, y: 50, width: 60, height: 60))
redView.backgroundColor = .systemRed
redView.layer.cornerRadius = 8
view.addSubview(redView)
let blueView = UIView(frame: CGRect(x: 200, y: 30, width: 60, height: 60))
blueView.backgroundColor = .systemBlue
blueView.layer.cornerRadius = 8
view.addSubview(blueView)
// 3. 중력
let gravity = UIGravityBehavior(items: [redView, blueView])
gravity.gravityDirection = CGVector(dx: 0, dy: 1)
gravity.magnitude = 0.8
animator.addBehavior(gravity)
// 4. 충돌
let collision = UICollisionBehavior(items: [redView, blueView])
collision.translatesReferenceBoundsIntoBoundary = true
collision.collisionDelegate = self
animator.addBehavior(collision)
// 5. 물리 속성
let itemBehavior = UIDynamicItemBehavior(items: [redView, blueView])
itemBehavior.elasticity = 0.6
itemBehavior.friction = 0.3
itemBehavior.density = 1.0
animator.addBehavior(itemBehavior)
// 6. 탭 시 Snap 동작
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
view.addGestureRecognizer(tap)
}
@objc
func handleTap(_ gesture: UITapGestureRecognizer) {
let point = gesture.location(in: view)
// 각 객체에 대한 Snap 동작
for subview in view.subviews where subview is UIView {
animator.removeAllBehaviors()
let snap = UISnapBehavior(item: subview, snapTo: point)
snap.damping = 0.5
animator.addBehavior(snap)
}
}
}
extension PhysicsViewController: UICollisionBehaviorDelegate {
func collisionBehavior(_ behavior: UICollisionBehavior,
beganContactFor item1: UIDynamicItem,
with item2: UIDynamicItem,
at point: CGPoint) {
print("충돌 위치: (포인트)")
}
}예제는 중력, 충돌 및 물리 속성을 가진 두 개의 View를 만듭니다. 탭 시 UISnapBehavior는 0.5의 감쇠로 객체를 터치 지점으로 스냅합니다. UICollisionBehaviorDelegate는 사운드 및 시각 효과를 위해 충돌 시작을 추적합니다.
UIKit Dynamics는 iOS 애플리케이션에서 게임이 아닌 인터페이스 물리에 사용됩니다. 일반적인 시나리오: 카드 스택 애니메이션(중앙 스냅용 UISnapBehavior), 오류 시 화면 흔들림(UIDynamicItemBehavior + UIPushBehavior), 온보딩의 "별똥별" 효과(gravity + collision + field behavior).
성능을 위해 UIKit Dynamics는 물리 처리가 있는 객체를 동시에 15-20개 이하로 유지할 것을 권장합니다. 각 객체는 매 프레임 충돌 및 힘 계산이 필요합니다. 제한을 초과하면 UIView 대신 CALayer를 사용하세요 — Core Animation이 레이어를 더 효율적으로 처리합니다.
자주 묻는 질문
UIKit Dynamics는 강체 시뮬레이션을 기반으로 물리적 상호작용(중력, 충돌, 힘)을 모델링합니다. Core Animation은 지정된 시간 곡선을 따라 CALayer 속성(position, opacity, transform)을 애니메이션합니다. Dynamics는 대화형 물리에 적합하고 Core Animation은 미리 정의된 전환에 적합합니다.
SwiftUI에는 UIKit Dynamics에 대한 직접적인 지원이 없습니다. 물리 효과를 위해 UIViewRepresentable 내에서 UIKitView + UIDynamicAnimator를 사용하거나 SwiftUI에서 Animation.spring() 및 withAnimation()을 통한 사용자 정의 애니메이션을 사용하세요.
animator.removeAllBehaviors()를 호출하세요 — 이렇게 하면 모든 활성 물리 동작이 제거됩니다. 애니메이터는 모든 객체가 정지 상태에 도달하면 자동으로 일시 중지됩니다. 임시 일시 중지를 위해 animator.isPaused 속성을 사용하거나 개별 동작을 제거하세요.
Apple은 완전한 물리(중력 + 충돌 + 힘)를 가진 객체를 15-20개 이하로 권장합니다. 대량 애니메이션의 경우 UIFieldBehavior를 사용하세요 — 쌍별 충돌 없이 중앙에서 힘을 계산하여 CPU 부하를 줄입니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.