Files
2nd/10_Wiki/Topics/Coding/iOS_SwiftUI_Lifecycle_View_Identity.md
T
2026-05-09 21:08:02 +09:00

3.3 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
ios-swiftui-lifecycle-view-identity SwiftUI Lifecycle 와 View Identity Coding draft B conceptual 2026-05-09 2026-05-09
ios
swiftui
identity
lifecycle
vibe-coding
language applicable_to
Swift / SwiftUI
iOS 16+
view identity
.id()
onAppear
onChange

SwiftUI Lifecycle 와 View Identity

SwiftUI 는 view 를 identity 로 추적. identity 가 같으면 같은 view (state 보존), 다르면 새 view (state 리셋). if/else 분기, .id() modifier, ForEach id, 그리고 위치 — 이 4가지가 identity 를 결정.

📖 핵심 개념

  • View 는 struct (value type) — render 마다 다시 만들어짐.
  • 그러나 @State 는 identity 가 같으면 보존.
  • identity 가 바뀌면 onAppear → onDisappear → 새 onAppear.

💻 코드 패턴

.id() 로 강제 재생성

struct UserView: View {
    let userId: String
    @State private var draft = ""
    var body: some View {
        TextField("draft", text: $draft)
    }
}

// 부모
UserView(userId: id)
    .id(id) // userId 바뀌면 새 view → draft 리셋

if/else 가 identity 만듦

if isLoggedIn {
    HomeView()  // identity A
} else {
    LoginView() // identity B
}
// 전환 시 onDisappear/onAppear 발생

ForEach 의 id 가 핵심

ForEach(items, id: \.id) { item in
    Row(item: item)
}
// id 가 같으면 같은 row (애니메이션 부드러움)
// index 를 id 로 쓰면 reorder 시 사고

onAppear vs onChange vs task

struct Detail: View {
    let id: String
    @State private var data: Data?

    var body: some View {
        Text("...")
            .onAppear { /* 매 등장마다 호출 */ }
            .task(id: id) {
                // id 바뀌면 이전 task cancel + 새 task. async 가능.
                self.data = try? await load(id: id)
            }
            .onChange(of: id) { oldId, newId in
                // id 바뀐 시점만
            }
    }
}

🤔 의사결정 기준

의도 도구
비동기 작업 + id 변경 시 cancel/restart .task(id:)
매 등장마다 1회 작업 .onAppear
특정 값 변경에 반응 .onChange(of:)
sheet/navigation 등장만 .task (lifecycle 묶임)
강제 view 리셋 .id(value)

안티패턴

  • ForEach 에 id: \.self + 같은 값 가진 항목: 충돌. unique id.
  • .task 에 cancellation 무시 + 긴 loop: id 변경 후에도 옛 task 가 setState. 새 task 가 자동 cancel 하므로 within task에서 checkCancellation.
  • onAppear 에서 fetch 후 setState: id 변경 시 cancel 안 됨. .task(id:) 권장.
  • .id() 남발: 모든 view 강제 재생성 → 애니메이션 깨짐 + 성능 저하.
  • 부모 rebuild 마다 자식 @StateObject 새로: identity 다른 경우. 위치/조건 점검.
  • Animation 안에서 ForEach id 가 index: 항목 추가/삭제 시 잘못된 row animate.

🤖 LLM 활용 힌트

  • "이 view 는 어떤 값에 의해 identity 가 바뀌어야 하는가?" 질문 후 .id() 또는 .task(id:) 결정.
  • 비동기 + cancel 필요 = .task(id:).

🔗 관련 문서