반응형

SwiftUI에서 많이 하는 실수 - @EnvironmentObject를 남용하거나 주입을 잊어서 크래시가 나는 실수

 

@EnvironmentObject는 전역에 가까운 상태를 환경으로 흘려보내는 도구입니다.

편리한 만큼 남용하거나 주입을 빼먹기 매우 쉽고, 그럴 경우 런타임 크래시가 바로 발생합니다.

대표 에러 메시지:

No ObservableObject of type XXX found. A View.environmentObject(_:) for XXX may be missing…


1. 문제 원인

  • 작은 화면 전용 상태도 전부 EnvironmentObject로 올려버림
  • 어떤 View가 어떤 EnvironmentObject를 필요로 하는지 문서화/패턴 없이 사용
  • 루트에서 .environmentObject() 주입을 빼먹은 채 @EnvironmentObject만 선언

2. 나타나는 증상

  • 특정 화면으로 진입하는 순간 앱이 곧바로 크래시
  • Preview에서는 잘 되는데, 실제 앱에선 에러 / 혹은 그 반대
  • 팀원끼리 “이 View 들어갈 때 뭐 주입해야 하지?”를 계속 물어봐야 함

3. 잘못된 코드 예시

final class AppStore: ObservableObject {
    @Published var isLoggedIn = false
}

struct HomeView: View {
    // ❌ AppStore가 environment에 주입되지 않았다면 크래시
    @EnvironmentObject var store: AppStore

    var body: some View {
        Text(store.isLoggedIn ? "로그인됨" : "로그인 필요")
    }
}

이 상태에서 HomeView()를 직접 띄우면 런타임에 바로 죽습니다.


4. 올바른 코드 예시

4-1. App 진입점에서 주입

@main
struct MyApp: App {
    @StateObject private var store = AppStore()

    var body: some Scene {
        WindowGroup {
            HomeView()
                .environmentObject(store)   // ✅ 루트에서 한 번만 주입
        }
    }
}

4-2. Preview에서도 동일하게 주입

#Preview {
    HomeView()
        .environmentObject(AppStore())      // ✅ Preview용 Store
}

이제 HomeView에서는 어디에서도 직접 store를 생성하지 않고,

환경에 주입된 AppStore 인스턴스를 안전하게 참조할 수 있습니다.


5. 정리 및 팁

  • EnvironmentObject는 진짜 전역적인 앱 상태(세션, 설정, 사용자 정보 등)에만 사용합니다.
  • 특정 화면에만 필요한 상태는 @StateObject + @ObservedObject + @Binding 계층으로 충분합니다.
  • 항상 “이 View는 어떤 EnvironmentObject에 의존하는지”를 명시적으로 관리하고,
    Preview에도 동일하게 주입하는 습관을 들이면 디버깅 난이도가 크게 줄어듭니다.
반응형
Posted by 까칠코더
,