티스토리 뷰

iOS 개발을 하다 보면 ViewController에서 네트워크 요청을 직접 호출하거나, 데이터베이스를 직접 접근하는 코드를 본 적이 있을 것이다.
이렇게 하면 간단한 기능은 빠르게 구현할 수 있지만, 코드가 복잡해질수록 유지보수가 어렵고 테스트하기도 어려워진다.

이 문제를 해결하는 방법이 바로 의존성 주입(Dependency Injection, DI) 이다!
DI를 활용하면 유지보수가 쉬워지고, 유닛 테스트가 편리해지며, 코드의 결합도가 낮아져 더 유연한 아키텍처를 만들 수 있다.

이번 포스팅에서는 DI의 개념과 활용하는 방법을 정리해보겠다.


1️⃣ 의존성이란?

✅ "의존성"이 뭘까?

객체가 다른 객체를 사용할 때, 이를 "의존성(Dependency)" 이라고 한다.
예를 들어, ViewController가 NetworkService를 직접 생성해서 사용한다면, ViewController는 NetworkService에 의존한다고 볼 수 있다.

class ViewController: UIViewController {
    let networkService = NetworkService() // 직접 객체 생성
    
    override func viewDidLoad() {
        super.viewDidLoad()
        networkService.fetchData()
    }
}

이 코드의 문제점은?

  • ViewController가 NetworkService에 강하게 결합되어 있어서 다른 네트워크 서비스로 교체하기 어려움
  • 유닛 테스트가 어렵다 (NetworkService를 실제로 호출하기 때문에 Mocking이 어려움)

이런 문제를 해결하려면 객체를 직접 생성하는 것이 아니라, 외부에서 주입받아야 한다.
이 개념이 바로 의존성 주입(Dependency Injection, DI) 이다.


2️⃣ 의존성 주입(Dependency Injection)이란?

✅ DI의 개념

의존성 주입(Dependency Injection)객체가 직접 의존성을 생성하는 것이 아니라, 외부에서 주입받도록 하는 설계 패턴이다.

이렇게 하면

  • 코드의 결합도가 낮아지고
  • 다른 구현체로 쉽게 변경할 수 있으며
  • 유닛 테스트도 쉽게 작성할 수 있다

3️⃣ 의존성 주입의 3가지 방법

DI를 적용하는 방법에는 3가지 방법이 있다.

방법 설명 코드  코드 예제
1. 생성자 주입 (Constructor Injection) 객체를 생성할 때, 의존성을 주입 init(service: NetworkService)
2. 프로퍼티 주입 (Property Injection) 객체 생성 후, 외부에서 의존성을 설정 vc.service = NetworkService()
3. 메서드 주입 (Method Injection) 특정 메서드를 호출할 때, 의존성을 주입 vc.setup(service: NetworkService())

이제 각각의 방법을 코드로 살펴보자.

✅ 1. 생성자 주입 (Constructor Injection)

가장 선호되는 방법으로, 객체가 생성될 때 의존성을 주입하는 방식이다.

protocol NetworkService {
    func fetchData()
}

class APIService: NetworkService {
    func fetchData() {
        print("네트워크에서 데이터 가져오기")
    }
}

// ✅ 생성자 주입을 사용하여 의존성 주입
class ViewController {
    let service: NetworkService
    
    init(service: NetworkService) {
        self.service = service
    }
    
    func loadData() {
        service.fetchData()
    }
}

// 사용 예제
let apiService = APIService()
let vc = ViewController(service: apiService) // 의존성을 주입
vc.loadData()

📌 이 방법이 좋은 이유

  • ViewController가 NetworkService 프로토콜에만 의존 → 의존성 역전 원칙(DIP)를 준수
  • APIService 대신 MockService를 주입하면 유닛 테스트가 가능
class MockService: NetworkService {
    func fetchData() {
        print("Mock 데이터 가져오기")
    }
}

let mockService = MockService()
let testVC = ViewController(service: mockService) // 테스트에서 Mock 객체 주입
testVC.loadData()

📌 언제 사용하면 좋을까?

  • 불변(immutable) 의존성을 다룰 때 (한 번 주입되면 변경되지 않는 경우)
  • 객체의 생명주기가 길 때 (서비스 레이어, 유틸리티 클래스 등)

✅ 2. 프로퍼티 주입 (Property Injection)

객체를 생성한 후, 외부에서 의존성을 설정하는 방식이다.

class ViewController {
    var service: NetworkService? // 처음에는 nil
    
    func loadData() {
        service?.fetchData()
    }
}

// 사용 예제
let vc = ViewController()
vc.service = APIService() // 외부에서 주입
vc.loadData()

📌 언제 사용하면 좋을까?

  • 의존성이 선택적(optional)일 때
  • 뷰 컨트롤러와 같은 UI 관련 클래스에서 사용 (예: Storyboard 사용 시)

✅ 3. 메서드 주입 (Method Injection)

특정 메서드를 호출할 때 의존성을 주입하는 방식이다.

class ViewController {
    func loadData(service: NetworkService) {
        service.fetchData()
    }
}

// 사용 예제
let vc = ViewController()
vc.loadData(service: APIService()) // 실행할 때마다 다른 서비스 주입 가능

📌 언제 사용하면 좋을까?

  • 매번 다른 의존성을 주입해야 하는 경우 (예: 전략 패턴)
  • 유닛 테스트에서 특정 시점에 의존성을 변경할 필요가 있을 때

4️⃣ 의존성 주입이 실무에서 중요한 이유

  1. 테스트가 쉬워진다!
    • 실제 NetworkService 대신 MockService를 주입하면, 네트워크 요청 없이 테스트 가능
  2. 코드의 유연성이 증가한다!
    • 네트워크 서비스 변경 시 APIService 구현체만 교체하면 됨
    • DI가 없으면 ViewController를 수정해야 하는데, DI를 적용하면 기존 코드 수정 없이 가능
  3. 아키텍처 패턴과의 궁합이 좋다!
    • MVVM, Clean Architecture, TCA 등의 패턴에서는 DI가 필수적
    • 특히 Dependency Injection Container(예: Swinject)를 활용하면 객체 생성을 더 간편하게 관리 가능

정리

의존성(Dependency)이란? 한 객체가 다른 객체를 사용할 때의 관계
의존성 주입(DI)이란? 객체가 직접 의존성을 생성하는 것이 아니라, 외부에서 주입하는 설계 패턴
DI를 적용하면 코드의 유지보수가 쉬워지고, 테스트가 간편해지며, 결합도가 낮아진다

DI의 3가지 방법

  • 생성자 주입: 객체 생성 시 의존성 주입 (가장 선호되는 방식)
  • 프로퍼티 주입: 객체 생성 후 의존성 설정 (UI 관련 클래스에 적합)
  • 메서드 주입: 특정 메서드 실행 시 의존성 전달 (전략 패턴에 유용)

DI를 잘 활용하면 더 유지보수하기 쉬운 iOS 앱을 만들 수 있다.
이제 직접 프로젝트에서 적용해보자! 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/04   »
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
글 보관함