Environment Value를 통해 의존성 주입하기

의존성 주입이란?

  • 의존성 주입은 클래스 간의 결합도를 낮추고 코드 유연성을 높이는 중요한 개념
  • 클래스 간의 의존성이 있다는 것은 한 클래스가 다른 클래스에 영향을 미친다는 것을 의미
  • 예를 들어, 한 클래스가 변경될 때 다른 클래스도 영향을 받는 상황입니다.

 

프로토콜 의존성 주입

  • 프로토콜 의존성 주입은 클래스 간의 결합도를 낮추기 위해 프로토콜을 사용하는 방법
  • 이를 통해 코드 유연성을 높임
  • 프로토콜을 정의하여 클래스가 특정 기능을 구현하도록 강제하고, 이를 의존성 주입을 통해 클래스에 주입
  1. 유연성 증대: 프로토콜을 통해 클래스의 인터페이스를 추상화하면, 해당 클래스를 변경할 때 다른 클래스에 영향을 덜 줌. 즉, 코드 변경 시 다른 클래스에 영향을 최소화
  2. 테스트 용이성: 프로토콜을 사용하여 클래스의 의존성을 주입하면 테스트할 때 모의 객체(Mock)를 주입하여 테스트하기 용이

 

Environment Value를 통해 ViewModel에 의존성 주입

  • SwiftUI에서는 @Environment@EnvironmentObject 프로퍼티 래퍼를 사용하여 환경 값을 관리
  1. @EnvironmentObject: 임의의 값을 환경에 주입할 수 있도록 도움
    • 예를 들어, 앱 전체에서 공유되는 데이터 모델을 만들고 이를 환경에 주입하여 여러 뷰에서 사용 가능
  2. @Environment: SwiftUI 자체에서 미리 정의된 키와 함께 작동
    • 예를 들어, @Environment(\.colorScheme)은 시스템 설정에 따라 자동으로 업데이트되는 환경 값을 제공

이 글에서 @Environment을 사용하여 ViewModel에 의존성을 주입하는 방법을 소개

1. 환경 키 정의하기

  • 먼저, DIContainer라는 환경 키를 정의
  • 이 키는 services라는 서비스 객체를 환경에 주입하는 역할
struct DIContainer: EnvironmentKey {
    let services: Services

    static var defaultValue: Self { Self.default }

    private static let `default` = Self(services: .init())
}

2. 환경 값 설정하기

  • EnvironmentValues 확장을 통해 injected 프로퍼티를 추가
  • 이 프로퍼티는 DIContainer를 환경에 주입
extension EnvironmentValues {
    var injected: DIContainer {
        get { self[DIContainer.self] }
        set { self[DIContainer.self] = newValue }
    }
}

3. ViewModel에서 환경 값 사용하기

  • 이제 뷰 모델에서 @Environment(\\.injected)를 사용하여 DIContainer를 가져올 수 있음
struct MyView: View {
    @Environment(\.injected) private var diContainer: DIContainer    

    var body: some View {
        // diContainer.services를 사용하여 ViewModel에 의존성 주입
        // ...
    }
}