Swinject: 개념, Dependency Injection 원리 및 작동 방식

저자: IT Sectr 게시일: 2026-05-04 읽는 시간: 8 분

Swinject는 iOS 애플리케이션에서 Dependency Injection 패턴을 구현하는 Swift용 DI 컨테이너입니다. 이 프레임워크는 종속성 생성 및 주입을 자동화하여 수동 객체 및 팩토리 관리를 없애줍니다. GitHub의 Swinject에 따르면, 라이브러리는 Constructor Injection, Property Injection 및 Method Injection을 지원하며 유연한 스코프 시스템을 통해 수명을 관리합니다.

핵심 포인트

  • Swinject — iOS 프로젝트에서 종속성 주입을 자동화하는 Swift용 DI 컨테이너입니다.
  • Dependency Injection — 객체가 내부에서 생성하지 않고 외부에서 종속성을 받는 패턴입니다.
  • Container — 등록된 서비스와 해당 팩토리의 레지스트리를 저장하는 Swinject의 중앙 구성 요소입니다.
  • Service — 컨테이너가 구체적인 구현을 저장하는 프로토콜 형태의 추상화입니다.
  • ObjectScope — 인스턴스 수명(graph, container 또는 transient)을 결정하는 메커니즘입니다.

Swinject와 Dependency Injection이란

Swinject는 iOS, macOS 및 watchOS용 애플리케이션에서 종속성 주입을 간소화하기 위해 설계된 Swift 언어용 오픈 소스 DI 컨테이너입니다. 프레임워크는 Service Locator 접근 방식을 사용합니다. 서비스는 중앙 컨테이너에 등록되고, 컨테이너는 인스턴스가 요청될 때 자동으로 종속성 그래프를 해결합니다.

Dependency Injection(DI)은 객체가 내부에서 생성하지 않고 외부에서 종속성을 받는 디자인 패턴입니다. 이는 구성 요소 간의 결합도를 낮추고, 단위 테스트를 간소화하며, 소비자 코드를 수정하지 않고 구현을 교체할 수 있게 합니다.

Martin Fowler(2004)에 따르면, DI는 Inversion of Control의 특정 사례로 생성자, 속성 또는 메서드 주입을 통해 구현됩니다. Swinject는 이 프로세스를 자동화하여 수동으로 팩토리와 서비스 로케이터를 작성할 필요를 없앱니다.

상호 종속성이 있는 세 개 이상의 서비스가 있는 프로젝트에서 Swinject를 사용하세요. 수동 객체 생성은 초기화 코드를 비대하게 만들고 테스트 가능성을 저하시킵니다.

Swinject는 Apple 생태계와 긴밀하게 통합되며 Swift 3.0부터 모든 버전을 지원합니다. 프레임워크는 브릿지를 통해 Objective-C와 호환되어, 전체 코드 마이그레이션 없이 기존 혼합 언어 프로젝트에 도입할 수 있습니다. 이는 5년 이상의 개발 역사를 가진 대규모 애플리케이션에 특히 중요합니다.

Swinject 컨테이너 작동 방식

Swinject 컨테이너는 Container 클래스로 구현되며, 등록된 서비스의 레지스트리를 저장합니다. resolve 메서드가 호출되면 컨테이너는 객체를 생성하고 등록 그래프를 통해 모든 종속성을 재귀적으로 해결합니다.

Container와 Service

Container는 추상화와 구현 간의 매핑이 등록되는 중앙 객체입니다. Service는 계약을 정의하는 프로토콜이며, Component는 이 프로토콜을 구현하는 클래스입니다. 등록은 서비스 유형과 팩토리를 받는 register 메서드를 사용하여 수행됩니다.

swift
let container = Container()
container.register(Networking.self) { _ in
    NetworkService()
}
let service = container.resolve(Networking.self)

resolve 메서드는 지정된 프로토콜에 대해 등록된 구체적인 구현의 인스턴스를 반환합니다. 종속성이 등록되지 않은 경우, 컨테이너는 개발 중 빠른 문제 발견을 위해 치명적 오류를 발생시킵니다.

등록 및 명명된 서비스

등록은 팩토리 함수와 선택된 스코프가 있는 항목을 생성합니다. 하나의 서비스는 다른 이름으로 여러 등록을 가질 수 있어 이름으로 특정 구현을 선택할 수 있습니다 — 다양한 환경(개발, 스테이징, 프로덕션)에 유용합니다.

종속성 해결 프로세스는 재귀적으로 작동합니다. 컨테이너가 Component 인스턴스를 생성할 때, 초기화 프로그램을 분석하고 각 매개변수에 대해 해당 유형으로 resolve를 호출합니다. 종속성에 자체 종속성이 있는 경우, 전체 그래프가 완전히 구축될 때까지 프로세스가 계속됩니다. 중첩 깊이는 사용 가능한 메모리에 의해서만 제한되지만, 실제로는 5단계를 초과하는 경우가 거의 없습니다.

Swinject의 종속성 주입 방법

Swinject는 세 가지 주요 종속성 주입 방법을 지원하며, 각각 아키텍처 컨텍스트에 따라 적용됩니다.

Constructor Injection

Constructor Injection은 초기화 프로그램 매개변수를 통해 종속성을 주입합니다. 이는 선호되는 방법으로, 객체가 생성 순간부터 항상 유효한 상태에 있음을 보장합니다. Swinject는 생성자에 전달된 모든 종속성을 자동으로 해결합니다.

swift
class LoginViewModel {
    private let authService: AuthProtocol

    init(authService: AuthProtocol) {
        self.authService = authService
    }
}

container.register(AuthProtocol.self) { _ in
    AuthService()
}
container.register(LoginViewModel.self) { r in
    LoginViewModel(authService: r.resolve(AuthProtocol.self)!)
}

Property Injection

Property Injection은 초기화 후 객체 속성을 설정하여 종속성을 주입합니다. 종속성이 선택적이거나 생성자를 통해 전달할 수 없는 경우에 사용됩니다(예: view controller가 자동으로 생성되는 Storyboard 작업 시). Swinject는 명시적 resolve 호출 없이 런타임에 자동 속성 주입을 위한 @Inject 어노테이션을 지원합니다.

Property Injection을 사용할 때는 객체에 처음 접근하기 전에 종속성이 설정되었는지 확인하는 것이 중요합니다. 그렇지 않으면 속성이 nil로 남아 예기치 않은 충돌이 발생합니다. Swinject는 Implicitly Unwrapped Optional 메커니즘과 종속성 그래프 해결 단계에서의 엄격한 검증을 통해 이 문제를 해결합니다.

Method Injection

Method Injection은 메서드 매개변수를 통해 종속성을 주입합니다. 단일 작업을 수행하는 데만 필요하고 객체의 영구 상태로 저장되어서는 안 되는 서비스에 사용됩니다. 가장 일반적이지는 않지만 콜백에 유용한 주입 방법입니다.

Swinject의 스코프와 목적

ObjectScope는 Swinject 컨테이너 내에서 생성된 인스턴스의 수명을 결정하는 메커니즘입니다. 프레임워크는 ObjectScopeProtocol을 통해 사용자 정의 스코프를 생성하는 기능과 함께 세 가지 내장 스코프를 제공합니다.

ObjectScope.graph

graph 스코프는 기본값입니다. 각 resolve 호출은 종속성 그래프 해결 기간 동안만 유지되는 새 인스턴스를 생성합니다. 캐싱으로 인한 메모리 누수를 제거하므로 상태 비저장 서비스에 안전한 선택입니다.

ObjectScope.container

container 스코프는 컨테이너 내의 싱글톤입니다. 인스턴스는 첫 번째 resolve 시 한 번 생성되고 이후 모든 요청에서 반환됩니다. 공유 상태가 있는 서비스(데이터 캐시, 로거, 애플리케이션 설정)에 적합합니다.

ObjectScope.transient

transient 스코프는 캐싱 없이 모든 resolve 호출에서 새 인스턴스를 생성합니다. 재사용할 필요가 없는 경량 객체(예: 특정 HTTP 요청을 처리하는 모듈)에 사용됩니다.

스코프수명권장 사용
graph그래프 해결 기간 동안기본적으로 상태 비저장 서비스
container컨테이너의 전체 수명싱글톤: 캐시, 로거, 네트워크 클라이언트
transient캐싱 없음일회용 경량 객체

iOS 프로젝트에서 Swinject

실제 iOS 프로젝트에 Swinject를 통합하는 것은 애플리케이션 시작 시(AppDelegate 또는 씬에서) 컨테이너를 초기화하는 것으로 시작됩니다. Assembly를 사용하여 등록을 구조화하는 것이 좋습니다. 관련 서비스를 그룹화하는 별도의 클래스 또는 구조체입니다.

Swift Developer Community 설문조사(2025)에 따르면, 43%의 iOS 개발자가 상용 프로젝트에서 네트워크 계층, 리포지토리 및 탐색 코디네이터의 종속성 관리를 위해 DI 컨테이너를 사용합니다. Swinject는 최소한의 구문과 Objective-C 호환성으로 가장 인기 있는 솔루션으로 남아 있습니다.

Storyboard Injection은 Swinject의 고유한 기능입니다. 컨테이너는 AppDelegate에 추가 코드 없이 Storyboard에서 생성된 view controller에 자동으로 종속성을 주입합니다. 이는 init(container:) 메서드를 통해 UIStoryboard에 전달되는 특수 리졸버를 사용하여 view controller 생성을 가로채고 등록된 종속성을 주입합니다.

대규모 프로젝트에서는 Swinject를 탐색 코디네이터와 결합할 수 있습니다. 코디네이터는 컨테이너를 받아 resolve를 통해 종속성을 해결하여 화면을 생성하며, 전체 씬에 대한 단일 구성 지점을 유지합니다.

Assembly 아키텍처는 등록을 구성하기 위한 권장 패턴입니다. 각 Assembly는 관련 서비스(예: NetworkingAssembly, DatabaseAssembly)를 그룹화하고 다른 Assembly에 종속될 수 있습니다. 컨테이너 초기화 시 모든 Assembly가 로드되어 서비스를 등록하여 명확한 책임 분리를 제공하고 수십 개의 서비스가 있는 대규모 프로젝트에서 DI 구성을 쉽게 탐색할 수 있게 합니다.

DI 그래프 디버깅을 위해 Swinject는 plist 파일에서 구성을 로드하는 SwinjectPropertyLoader 확장과 특수 버전의 UIStoryboard를 통한 스토리보드 통합인 SwinjectStoryboard를 제공합니다. 이러한 도구는 기존 프로젝트를 수동 객체 생성에서 DI로 마이그레이션할 때 특히 유용합니다. 개발자는 주요 기능 개발을 중단하지 않고 테스트 및 해결 오류 로깅을 통해 종속성 그래프를 확인하면서 점진적으로 서비스를 등록할 수 있습니다.

Swinject는 또한 명시적 팩토리 등록 없이 초기화 프로그램 매개변수 유형에 기반한 자동 종속성 해결을 위한 SwinjectAutoregistration 확장을 통해 RxSwift 및 Combine과의 통합을 제공합니다. 이는 단순한 서비스의 등록 코드 양을 줄입니다. 팩토리를 지정하지 않고 container.register(ServiceProtocol.self)를 호출하기만 하면 Swift 런타임이 제공하는 Signal 리플렉션을 기반으로 Swinject가 자동으로 팩토리를 구축합니다. 이 접근 방식은 생성자가 기본 유형만 허용하고 복잡한 생성 로직이 필요하지 않은 서비스에 권장됩니다.

자주 묻는 질문

Swinject는 다른 Swift DI 프레임워크와 어떻게 다른가요?

Swinject는 코드 생성이나 리플렉션 없이 순수 Swift로 작성되었습니다. Needle과 달리 소스 생성이 필요하지 않으며, Dip과 비교하여 내장 Storyboard Injection 지원을 제공하여 기존 UIKit 프로젝트에 통합을 간소화합니다.

Swift Package Manager를 통해 Swinject를 설치하려면?

Xcode의 File → Add Packages 메뉴에서 URL github.com/Swinject/Swinject로 패키지를 추가하세요. CocoaPods 및 Carthage를 통한 설치도 가능합니다. 설치 후 Swinject 모듈을 가져오고 Container 인스턴스를 생성하세요.

SwiftUI 프로젝트에서 Swinject를 사용할 수 있나요?

네, Swinject는 SwiftUI와 완벽하게 호환됩니다. 종속성은 View 초기화 프로그램 또는 Environment를 통해 주입되며, 컨테이너는 EnvironmentObject로 전달됩니다. Swinject는 UIKit에 의존하지 않으며 두 프레임워크 모두에서 동일하게 작동합니다.

단위 테스트에 Swinject를 사용하려면?

테스트용으로 별도의 컨테이너를 만들고 실제 서비스를 모의 객체로 대체하세요. Swinject는 소비자 코드를 변경하지 않고 등록을 재정의할 수 있습니다. 각 테스트는 최소한의 종속성 세트로 격리된 컨테이너를 받습니다.

분석 서비스에는 어떤 스코프를 선택해야 하나요?

분석의 경우 container 스코프를 사용하여 모든 화면이 단일 인스턴스를 통해 이벤트를 보내도록 하세요. 이는 다양한 소비자 간 데이터 중복 없이 통합된 전송 큐와 올바른 배치 집계 작업을 보장합니다.

요약

  • Swinject — Container와 ObjectScope를 통해 종속성 주입을 자동화하는 Swift용 DI 컨테이너입니다.
  • Dependency Injection은 코드 결합도를 낮추고, 테스트를 간소화하며, 소비자를 변경하지 않고 구현을 교체할 수 있게 합니다.
  • Container — 등록을 위한 register와 인스턴스 검색을 위한 resolve를 지원하는 서비스 레지스트리입니다.
  • Constructor Injection은 선호되는 주입 방법으로, 객체의 유효한 상태를 보장합니다.
  • ObjectScope는 수명을 관리합니다: graph(기본값), container(싱글톤), transient(캐시 없음).
  • Storyboard Injection은 수동 설정 없이 UIKit 씬에 자동으로 종속성을 주입합니다.
  • 단위 테스트를 위해 서비스의 모의 구현으로 별도의 컨테이너를 사용하세요.

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기