docs(10_Wiki): 위키 전체 재구성 — Topic_* 폴더를 4개 카테고리로 통합 + 대규모 중복 제거

Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를
Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류.

- 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로
  자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거,
  동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거.
- 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming,
  Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business,
  Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로,
  나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는
  title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백).
  원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지.
- 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서.
- 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는
  지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지.
- Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경.
- 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
This commit is contained in:
Antigravity Agent
2026-07-05 00:33:48 +09:00
parent 1cfd3bbb56
commit 9148c358d0
6455 changed files with 1 additions and 86875 deletions
@@ -0,0 +1,402 @@
---
id: ios-swiftui-animation-deep
title: SwiftUI Animation — implicit / explicit / matchedGeometry
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [ios, swiftui, animation, vibe-coding]
tech_stack: { language: "Swift", applicable_to: ["iOS"] }
applied_in: []
aliases: [SwiftUI animation, withAnimation, matchedGeometryEffect, transition, PhaseAnimator, KeyframeAnimator]
---
# SwiftUI Animation
> SwiftUI 의 animation 가 declarative. **`.animation()`, `withAnimation`, transition, matchedGeometry**. iOS 17+ 의 PhaseAnimator / KeyframeAnimator.
## 📖 핵심 개념
- Implicit: state 변경 = 자동.
- Explicit: `withAnimation` block.
- Transition: appear / disappear.
- matchedGeometry: 두 view 간 morph.
## 💻 코드 패턴
### Implicit animation
```swift
struct ContentView: View {
@State var scale = 1.0
var body: some View {
Circle()
.scaleEffect(scale)
.animation(.spring(), value: scale)
.onTapGesture {
scale = scale == 1.0 ? 2.0 : 1.0
}
}
}
```
`.animation(_, value:)` 가 modern API. Value 변경 = animate.
### Explicit (withAnimation)
```swift
@State var isExpanded = false
Button("Toggle") {
withAnimation(.spring(response: 0.5, dampingFraction: 0.7)) {
isExpanded.toggle()
}
}
```
→ Block 안 변경 가 animate.
### 모든 animation type
```swift
.animation(.linear(duration: 0.3), value: x)
.animation(.easeInOut(duration: 0.5), value: x)
.animation(.spring(response: 0.5, dampingFraction: 0.7), value: x)
.animation(.bouncy, value: x) // iOS 17
.animation(.smooth, value: x) // iOS 17
.animation(.snappy, value: x) // iOS 17
.animation(.interactiveSpring(), value: x)
```
### Transition
```swift
struct Toast: View {
@State var show = false
var body: some View {
VStack {
if show {
Text("Hello")
.transition(.move(edge: .top).combined(with: .opacity))
}
}
.animation(.spring(), value: show)
}
}
```
→ Appear / disappear 의 animation.
### Built-in transitions
```swift
.transition(.opacity)
.transition(.scale)
.transition(.slide)
.transition(.move(edge: .leading))
.transition(.push(from: .top)) // iOS 17
.transition(.scale.combined(with: .opacity))
```
### Custom transition (iOS 17 movePhase)
```swift
struct BlurTransition: Transition {
func body(content: Content, phase: TransitionPhase) -> some View {
content
.blur(radius: phase.isIdentity ? 0 : 20)
.opacity(phase.isIdentity ? 1 : 0)
}
}
//
.transition(BlurTransition())
```
### matchedGeometryEffect (morph)
```swift
@Namespace var namespace
@State var expanded = false
VStack {
if expanded {
Image("hero")
.matchedGeometryEffect(id: "hero", in: namespace)
.frame(width: 300, height: 300)
} else {
Image("hero")
.matchedGeometryEffect(id: "hero", in: namespace)
.frame(width: 100, height: 100)
}
}
.onTapGesture {
withAnimation(.spring()) { expanded.toggle() }
}
```
→ 같은 ID = morph. Hero animation 의 답.
### PhaseAnimator (iOS 17+)
```swift
struct PulseView: View {
var body: some View {
Circle()
.phaseAnimator([1.0, 1.5, 1.0]) { content, phase in
content
.scaleEffect(phase)
.opacity(phase == 1.5 ? 0.5 : 1.0)
} animation: { phase in
.easeInOut(duration: 0.5)
}
}
}
```
→ 자동 cycle. Loop 식 animation.
### KeyframeAnimator (iOS 17+)
```swift
struct WaveView: View {
@State var trigger = false
var body: some View {
Circle()
.keyframeAnimator(initialValue: AnimationValues(), trigger: trigger) { content, value in
content
.scaleEffect(value.scale)
.rotationEffect(value.rotation)
} keyframes: { _ in
KeyframeTrack(\.scale) {
LinearKeyframe(1.5, duration: 0.5)
SpringKeyframe(1.0, duration: 0.5)
}
KeyframeTrack(\.rotation) {
CubicKeyframe(.degrees(360), duration: 1.0)
}
}
.onTapGesture { trigger.toggle() }
}
}
struct AnimationValues {
var scale = 1.0
var rotation = Angle.zero
}
```
→ 복잡 multi-property animation.
### Animatable protocol (custom)
```swift
struct CounterShape: Shape, Animatable {
var value: Double
var animatableData: Double {
get { value }
set { value = newValue }
}
func path(in rect: CGRect) -> Path {
// value frame draw
}
}
```
→ Custom shape 도 animate.
### AnimatableModifier
```swift
struct ShakeEffect: GeometryEffect {
var amount: CGFloat = 10
var animatableData: CGFloat
func effectValue(size: CGSize) -> ProjectionTransform {
ProjectionTransform(CGAffineTransform(translationX:
amount * sin(animatableData * .pi * 5), y: 0))
}
}
//
.modifier(ShakeEffect(animatableData: CGFloat(attempts)))
```
### Spring (커스텀)
```swift
.animation(.spring(
response: 0.5, // duration approximation
dampingFraction: 0.7, // overshoot (0 = bounce, 1 = no bounce)
blendDuration: 0
), value: x)
```
`response` + `dampingFraction` 가 일반.
### Animation interruption
```swift
// animation :
withAnimation(.easeInOut) { x = 100 }
// 0.2 sec
withAnimation(.spring()) { x = 50 }
// 2 1 (smooth).
```
→ SwiftUI 가 자동.
### Animation curve
```swift
extension Animation {
static var customCurve: Animation {
.timingCurve(0.2, 0.8, 0.2, 1.0, duration: 0.5)
}
}
```
`.timingCurve(c1x, c1y, c2x, c2y)` = bezier.
### Disable animation (specific)
```swift
.transaction { tx in
tx.animation = nil
}
// Or
withTransaction(Transaction(animation: nil)) {
x = 100
}
```
→ 일부 변경 가 animate X.
### List / scroll animation
```swift
List(items, id: \.id) { item in
Row(item)
}
.animation(.spring(), value: items)
// onDelete + animation
.swipeActions {
Button("Delete") {
withAnimation { items.removeAll { $0.id == item.id } }
}
}
```
### Scroll 의 visual effect (iOS 17)
```swift
ScrollView {
ForEach(items) { item in
Card(item)
.scrollTransition { content, phase in
content
.opacity(phase.isIdentity ? 1 : 0.3)
.scaleEffect(phase.isIdentity ? 1 : 0.8)
}
}
}
```
→ Scroll 위치 따라 modify.
### Repeat animation
```swift
.animation(.linear(duration: 1).repeatForever(autoreverses: true), value: x)
// Or
withAnimation(.linear(duration: 1).repeatForever()) {
rotation = 360
}
```
### Performance
```
- 매 frame draw 안 비싸게.
- Complex shape = lazy.
- Background work + animation 가 main thread X.
- Instruments > Animation Hitches.
```
### Geometry effect (transform)
```swift
struct RotationEffect: GeometryEffect {
var angle: Double
var animatableData: Double {
get { angle }
set { angle = newValue }
}
func effectValue(size: CGSize) -> ProjectionTransform {
ProjectionTransform(CGAffineTransform(rotationAngle: angle))
}
}
```
### 함정
```
- @State 변경 + animation 없음: 즉시.
- ObservableObject 변경: 자동 X (withAnimation 명시).
- async work 후 변경: main thread + withAnimation.
- 큰 list animation: 성능.
- transition 없이 conditional: 즉시 fade.
```
### Reduce motion (a11y)
```swift
@Environment(\.accessibilityReduceMotion) var reduce
withAnimation(reduce ? nil : .spring()) {
x.toggle()
}
```
→ User 가 motion ↓ 옵션 — 존중.
### iOS 17 추가 (modern)
```
- ContainerRelativeShape
- Shader Library (Metal 통합)
- Symbol effects
- Gradient animatable
→ SwiftUI 매년 발전.
```
### Symbol effect
```swift
Image(systemName: "heart.fill")
.symbolEffect(.bounce, value: trigger)
.symbolEffect(.pulse)
.symbolEffect(.variableColor.iterative)
```
→ SF Symbol 가 자체 animate.
## 🤔 의사결정 기준
| 작업 | 추천 |
|---|---|
| State 변경 | Implicit `.animation(_, value:)` |
| 명시 control | `withAnimation` |
| Appear/disappear | `.transition()` |
| Hero / morph | `matchedGeometryEffect` |
| Loop | `phaseAnimator` |
| 복잡 timeline | `keyframeAnimator` |
| Custom geometry | `Animatable` protocol |
| Symbol | `symbolEffect` |
## ❌ 안티패턴
- **animation(:value:) 없는 implicit**: 모든 거 animate.
- **withAnimation 안 의 async work**: race.
- **Complex shape + 매 frame redraw**: 성능.
- **Transition 없이 conditional**: 갑작 사라짐.
- **Reduce motion 무시**: a11y 위반.
- **Spring response 가 너무 작음**: jittery.
- **Stack 의 모든 child 가 animate**: 폭발.
## 🤖 LLM 활용 힌트
- `.animation(_, value:)` 가 modern (iOS 16+).
- matchedGeometryEffect 가 Hero 답.
- iOS 17 의 phaseAnimator / keyframe 가 powerful.
- Reduce motion 항상 존중.
## 🔗 관련 문서
- [[iOS_SwiftUI_State_Property_Wrappers]]
- [[Frontend_Animation_Motion]]
- [[React_Animation_Performance]]