SwiftUI Study – withAnimation과 Transaction을 안전하게 사용하는 법 (의도치 않은 애니메이션·상태 충돌 방지)
Dev Study/SwiftUI 2025. 12. 9. 10:18SwiftUI Study – withAnimation과 Transaction을 안전하게 사용하는 법 (의도치 않은 애니메이션·상태 충돌 방지)
1. 왜 중요한가 (문제 배경)
SwiftUI는 상태 변화가 일어나면 자동으로 애니메이션을 적용할 수 있는 매우 강력한 구조를 갖고 있다.
하지만 다음과 같은 상황에서 예기치 않은 문제가 자주 발생한다.
- 화면 전체가 원하지 않게 애니메이션됨
- 특정 상태만 애니메이션하려 했는데 다른 뷰까지 함께 애니메이션됨
- 빠르게 연속 상태 변경 시 애니메이션이 꼬임
- withAnimation이 중첩되며 트랜잭션 충돌 발생
- transition(삽입/삭제)과 animation이 상호간섭
문제의 핵심은 다음이다.
애니메이션 범위와 Transaction 컨텍스트를 명확히 이해하지 않으면
작은 UI 변경에도 전체 화면이 흔들리는 부작용이 생긴다.
2. 잘못된 패턴 예시
❌ 예시 1: withAnimation을 너무 넓은 범위에 적용
withAnimation {
isExpanded.toggle() // ❌ 이 변경과 관련된 모든 뷰가 애니메이션됨
count += 1 // ❌ 불필요한 숫자 변화까지 애니메이션됨
}
문제점
- 예상치 못한 뷰까지 애니메이션이 전파됨
- 디버깅 어려움
- 특히 리스트나 조건부 렌더링에서 흔히 붕괴 발생
❌ 예시 2: transition과 animation의 충돌
if isVisible {
Text("Hello")
.transition(.opacity) // ❌
}
.animation(.easeInOut, value: isVisible) // 충돌 가능
문제점
- 삽입/삭제 애니메이션과 상태 기반 애니메이션이 싸워서
텍스트가 깜빡이거나 두 번 애니메이션됨
❌ 예시 3: 빠른 상태 변경으로 애니메이션 큐가 꼬임
Button("증가") {
withAnimation {
value += 1 // ❌ 빠른 클릭 시 애니메이션이 누적되어 꼬임
}
}
문제점
- 여러 애니메이션이 겹침
- UI 반응성 저하
- 값 변화와 애니메이션 타이밍 불일치
❌ 예시 4: 뷰 위치 변경이 의도치 않게 animation 디폴트 영향
.animation(.default, value: offset) // ❌ 모든 offset 변경에 애니메이션 적용
문제점
- 스크롤 기반 offset 변경 시 화면이 흔들림
- 레이아웃 변경까지 애니메이션되며 UX 붕괴
3. 올바른 패턴 예시
✅ 예시 1: 애니메이션이 필요한 상태만 정확히 지정
withAnimation(.spring()) {
isExpanded.toggle() // 이 상태 변경만 애니메이션됨
}
장점
- 다른 상태 변화는 애니메이션되지 않음
- 부작용 최소화
- 애니메이션 범위 명확
✅ 예시 2: transition은 insertion/removal에만 사용
if isVisible {
Text("Hello")
.transition(.move(edge: .bottom))
}
.animation(.easeInOut, value: isVisible)
장점
- 삽입/삭제 모션과 상태 변화 애니메이션이 명확히 분리
- 깜빡임, 중복 애니메이션 방지
✅ 예시 3: Transaction으로 애니메이션 비활성화
.transaction { t in
t.animation = nil // 특정 뷰는 애니메이션 제외
}
사용 예:
Text("즉시 변경")
.transaction { t in t.animation = nil }
.onChange(of: value) { _ in immediateChange() }
장점
- 특정 구간만 animation을 끌 수 있음
- 리스트 내 부분적 애니메이션 비활성화 가능
✅ 예시 4: 애니메이션 큐가 꼬일 때는 interpolatingSpring 또는 interactiveSpring
withAnimation(.interpolatingSpring(stiffness: 180, damping: 18)) {
value += 1
}
장점
- 자연스럽고 강건한 모션
- 반복 클릭 상황에서도 안정적
✅ 예시 5: 상태 기반 애니메이션은 value를 명확히 지정
.rotationEffect(.degrees(isRotated ? 180 : 0))
.animation(.easeInOut, value: isRotated)
장점
- 의도한 상태 변화에만 애니메이션 적용
- 불필요한 다른 상태 변경은 애니메이션 없음
4. 실전 적용 팁
✔ 팁 1 – withAnimation은 “하나의 의도된 상태 변화”만 감싸기
여러 상태를 한 번에 감싸면 부작용 발생.
✔ 팁 2 – transition은 삽입/삭제 + animation은 상태 변화로 역할 분리
같이 섞으면 애니메이션 충돌이 매우 흔함.
✔ 팁 3 – Transaction으로 특정 뷰는 애니메이션 제외 가능
리스트 스크롤 시 셀 흔들림 방지에 유용.
✔ 팁 4 – 빠른 연속 애니메이션에는 spring 계열이 안정적
대량의 상태 업데이트에도 자연스럽게 반응.
✔ 팁 5 – 애니메이션 디버깅은 .animationModifier 로그로 검증
어떤 상태가 애니메이션을 트리거했는지 쉽게 추적 가능.
5. 정리
- SwiftUI 애니메이션은 상태 기반이므로, 애니메이션 범위를 명확히 지정하지 않으면 원치 않는 뷰까지 영향을 준다.
- transition과 animation은 각각의 역할을 분리하여 사용해야 충돌이 없다.
- Transaction을 활용하면 애니메이션을 부분적으로 끌 수 있어 복잡한 화면도 안정적으로 구현 가능하다.
- 실전 환경에서는 spring 기반 애니메이션이 가장 강건하고 예측 가능하다.

