반응형
SwiftUI에서 많이 하는 실수 - List 셀 내부에서 상태 변경/로직을 수행해 무한 렌더링이 발생하는 실수
SwiftUI의 List/ForEach는 각 셀을 필요할 때마다 재사용/재생성합니다.
셀 View의 body에서 상태를 변경하거나 네트워크 호출을 수행하면,
렌더링 → 상태 변경 → 다시 렌더링 → … 무한 루프가 발생할 수 있습니다.
1. 문제 원인
- 셀 View 내부에서 onAppear/onChange로 상태를 직접 바꿈
- View 생성 자체가 부수효과를 일으키도록 설계
- “셀 당 초기화가 한 번만 될 것”이라고 가정
2. 나타나는 증상
- 스크롤만 살짝 해도 API가 계속 호출됨
- 로그를 찍어보면 같은 셀에서 onAppear가 여러 번 실행
- CPU 사용량이 높고, 스크롤이 심하게 버벅거림
3. 잘못된 코드 예시
struct CardRow: View {
let card: Card
@ObservedObject var viewModel: CardsViewModel
var body: some View {
HStack {
Text(card.title)
}
.onAppear {
// ❌ 셀이 보일 때마다 통계를 올리는 API 호출
viewModel.trackImpression(for: card)
}
}
}
List 쪽:
List(viewModel.cards) { card in
CardRow(card: card, viewModel: viewModel)
}
스크롤할 때마다 같은 셀에 대해 trackImpression이 여러 번 호출됩니다.
4. 올바른 코드 예시
4-1. 셀 외부에서 제어하거나, 한 번만 실행되도록 방어
final class CardsViewModel: ObservableObject {
private var trackedIDs: Set<Card.ID> = []
func trackImpressionIfNeeded(for card: Card) {
guard !trackedIDs.contains(card.id) else { return }
trackedIDs.insert(card.id)
// 실제 트래킹 호출
}
}
struct CardRow: View {
let card: Card
@ObservedObject var viewModel: CardsViewModel
var body: some View {
HStack {
Text(card.title)
}
.onAppear {
viewModel.trackImpressionIfNeeded(for: card) // ✅ id 기반 방어
}
}
}
4-2. 단순 UI 상태만 셀에 두고, 비즈니스 로직은 밖으로
셀 내부에서 네트워크 호출/DB 업데이트를 하지 말고,
ViewModel/UseCase에 이벤트만 보내도록 설계합니다.
5. 정리 및 팁
- 셀 View는 최대한 순수 UI에 가깝게 유지하는 것이 좋습니다.
- onAppear/onDisappear에서 비즈니스 로직을 호출해야 한다면,
“같은 셀에 대해 여러 번 불려도 안전한지”를 항상 고려해야 합니다. - “한 번만 실행되어야 하는 로직”은 ViewModel 쪽에서 id 기반으로 방어하는 패턴이 필수입니다.
반응형
'Dev Study > SwiftUI' 카테고리의 다른 글
| SwiftUI에서 많이 하는 실수 - 도메인 모델과 UI 전용 모델을 구분하지 않는 실수 (0) | 2025.12.05 |
|---|---|
| SwiftUI에서 많이 하는 실수 - Preview에서 실제와 다른 상태를 구성해 놓고 디버깅이 꼬이는 실수 (0) | 2025.12.05 |
| SwiftUI에서 많이 하는 실수 - onChange(of:)를 잘못 사용해 과도한 리렌더링이 일어나는 실수 (0) | 2025.12.05 |
| SwiftUI에서 많이 하는 실수 - animation()을 남발해 의도치 않은 애니메이션이 발생하는 실수 (0) | 2025.12.05 |
| SwiftUI에서 많이 하는 실수 - ScrollView 안에서 LazyVStack을 사용하지 않아 성능이 나빠지는 실수 (0) | 2025.12.05 |
| SwiftUI에서 많이 하는 실수 - offset을 레이아웃 도구로 사용해서 반응형이 깨지는 실수 (0) | 2025.12.05 |
| SwiftUI에서 많이 하는 실수 - GeometryReader를 오용해 레이아웃이 엉망이 되는 실수 (0) | 2025.12.05 |
| SwiftUI에서 많이 하는 실수 - ViewModel에 비즈니스 로직과 UI 상태를 모두 섞어버리는 실수 (0) | 2025.12.05 |

