티스토리 뷰

 

 

 

오늘은 상태 관리하는 방법 중 하나인 EnvironmentObject에 대해 알아보고자 한다.

 

 

 

EnvironmentObject란?

 

애플공식문서에서는 EnvironmentObject를 부모 뷰나 조상뷰에서 observable object 타입으로 제공하는 프로퍼티라고 한다.

 

SwiftUI에서 전역으로 상태를 관리하며 데이터 공유 메커니즘 중에 하나이다!

앱에서 하나의 데이터를 여러 뷰에서 사용할 때 유용하며, observedObject로 하나의 값을 하위 뷰에 계속 전달전달전달 하는 방식이 아니라 상위 뷰에서 새로운 인스턴스를 한번 생성하고 하위 뷰에서 데이터 값에 접근하도록 하는 구조이다!

 

사용방법

  • 공유할 데이터를 가진 클래스는 @ObservableObject 프로토콜을 채택하고 있어야 하며, 관찰 가능한 속성은 @Published로 표현해주어야 한다.
  • 앱의 최상위 뷰에서 .environmentObject()를 사용하여 공유하고자 하는 객체를 환경 객체로 추가한다.
  • 하위 뷰에서는 @EnvironmentObject로 변수를 선언해 데이터에 접근하여 값을 읽고 업데이트할 수 있다.

예제로 한번 알아보자!

 

로그인 상태를 감지하여 로그아웃 됐을 경우 루트뷰를 바꿔주는 예제이다! 실제 프로젝트에 적용했었던 코드들이다

 

struct pennyway_client_iOSApp: App {
    @StateObject private var appViewModel = AppViewModel()

    init() {
        let kakaoAppKey = Bundle.main.infoDictionary?["KakaoAppKey"] as! String
        KakaoSDK.initSDK(appKey: kakaoAppKey, loggingEnable: false)
    }

    var body: some Scene {
        WindowGroup {
            if appViewModel.isLoggedIn {
                MainTabView()
                    .onAppear(perform: UIApplication.shared.addTapGestureRecognizer)
                    .onOpenURL { url in
                        GIDSignIn.sharedInstance.handle(url)
                    }
                    .environmentObject(appViewModel)

 

 

App파일에서 appViewModel이 로그인 됐을 경우 MainTabView를 루트뷰로 설정하고 있다.

즉 MainTabView 전체에서 쓰이는 뷰에 의존성을 주입한다. -> 최상단 뷰에서 environmentObject를 주입한다

 

(인스턴스는 한번만 생성해 주면 됨!!!)

 

struct MainTabView: View {
    @State private var selection = 0
    @EnvironmentObject var authViewModel: AppViewModel
    ...
}


struct ProfileSettingListView: View {
    @EnvironmentObject var authViewModel: AppViewModel
    ...
}

 

App파일(최상위 뷰)에 의존성을 주입했기 때문에 그에 대한 하위뷰에서는 @EnvironmentObject를 선언하고 이용할 수 있다!

 

데이터에 대한 접근이 필요하지 않는 뷰에서는 선언하지 않아도 됨

 

class AppViewModel: ObservableObject {
    @Published var isLoggedIn: Bool = false
    @Published var isSplashShown: Bool = false

    func logout() {
        isLoggedIn = false
    }

    func login() {
        isLoggedIn = true
    }
}

 

AppViewModel에서는 로그인 상태인지, 아닌지를 감지하고 이에 대한 함수가 작성돼있다.

 

1. App 파일에서 StateObject로 AppViewModel에 대한 뷰모델에 인스턴스를 생성해 준다.
2. viewModel안에서 @Published로 로그인 상태를 감지해 주고 최상위뷰인 App파일에서 루트뷰를 바꿔주고 있다.
3. 최상위뷰(App파일)에 사용되는 뷰 MainTabView랑 LoginView 안에 @EnvironmentObject를 선언해 준다.
4. UserProfileViewModel이 아닌, ProfileSettingListView에서 @EnvironmentObject로 appViewModel 데이터에 접근하여 로그아웃 버튼을 눌렀을 경우 logout 메서드에 접근한다.
    : ProfileSettingListView에 로그아웃 버튼을 눌렀을 때 처리하는 로직이 있기 때문에

 

 

로그아웃 화면에서 EnvironmentObject를 사용하였던 예시였는데 전체 로직은 위와 같다!

UserProfileViewModel 안에서 로그아웃 api를 연결하고 있어서 로그아웃 api에 성공했다면 isLoggedIn을 false로 바꿔주려고 처음에 생각하였다. 근데 안 됐음!!!!!!

왜냐하면 ViewModel안에서는 EnvironmentObject를 사용할 수 없다고 한다.. ㅋㅋ

그래서 뷰모델이 아닌, view에서 환경 객체를 주입하니 바로 됐었다 

 

view에 대한 상태를 감지하는 애라서 그런가 하하

 

 

EnvironmentObject의 장점

 

1️⃣ 간결한 코드

제일 큰 장점으로는 복잡하게 데이터값을 전달하지 않아도 돼서 간결한 코드 구조를 가지는 것이라고 할 수 있다.

 

예를 들어 A->B->C->D 구조를 가지는 뷰가 존재할 때 A가 로그인 화면이라 치고, D가 로그아웃 화면이라고 가정했을 때 A의 정보를 D에서 날려주면 되기 때문에 B와 C에 계속 값을 전달할 필요가 없다는 것이다! 

 

ObservedObject로 선언하여 데이터를 하위 뷰에 계속 전달하는 방식도 있지만, 만약 더 많은 뷰 구조가 형성되어 있다면 불필요한 데이터값을 계속해서 전달해줘야 하니 리소스가 낭비된다!

 

이럴 때 상위 뷰에서 EnvironmentObject를 사용하면 적합하다!!

 

2️⃣ 앱 전체에 공유 데이터로 쓰일 때

EnvironmentObject는 의존성 주입을 쉽게 할 수 있다. 최상위 뷰에 객체를 주입하면 다른 뷰에서 따로 선언하거나 다른 프로퍼티를 채택하지 않아도 사용가능하다. 

그래서 접근성이 쉽다!

 

또한, 전역 상태이기 때문에 데이터가 변경될 때 관련된 뷰에 한해서는 자동으로 업데이트가 된다는 점도 있다.

 

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함