Booil Jung

제어의 역전(IoC) 원칙

소프트웨어 공학의 발전사는 복잡성을 제어하고 변화에 유연하게 대응하기 위한 끊임없는 추상화와 구조화의 역사라 할 수 있다. 이러한 역사적 흐름 속에서 제어의 역전(Inversion of Control, IoC)은 객체 지향 프로그래밍의 패러다임을 한 단계 진보시킨 핵심적인 설계 원칙으로 자리매김하였다. IoC의 본질을 이해하기 위해서는 먼저 전통적인 프로그래밍 모델이 가진 제어 흐름의 내재적 한계를 명확히 인식해야 한다.

전통적인 프로그래밍 방식에서 제어의 주체는 명백히 개발자가 작성한 코드 자체에 있다.1 객체는 자신의 임무를 수행하기 위해 필요한 다른 객체, 즉 의존성을 스스로 생성하고 그 생명주기를 직접 관리한다. 예를 들어, 자동차(

Car) 객체는 내부에 엔진(Engine) 객체가 필요할 때, 생성자 내부에서 new Engine()과 같은 코드를 통해 직접 인스턴스를 생성한다.3 이러한 방식은 직관적일 수 있으나, 시스템의 규모가 커지고 복잡도가 증가함에 따라 심각한 문제를 야기하는데, 그 핵심에는 ‘강한 결합도(Tight Coupling)’가 있다.

강한 결합은 한 모듈이 다른 모듈의 구체적인 구현에 깊이 의존하는 상태를 의미한다. UserService가 특정 데이터베이스 기술인 OracleDatabase 클래스를 직접 참조하는 경우를 가정해 보자. 이 구조에서 UserServiceOracleDatabase 없이는 컴파일조차 불가능하며, 만약 데이터베이스를 MySqlDatabase로 변경해야 한다면 UserService의 코드를 직접 수정하는 것은 불가피하다.1 이는 다음과 같은 연쇄적인 문제점을 초래한다. 첫째, 유연성이 현저히 저하된다. 하위 수준의 기술적 세부 사항 변경이 상위 수준의 비즈니스 로직에 직접적인 영향을 미치므로 변화에 대응하기 어렵다. 둘째, 테스트의 어려움이 가중된다.

UserService를 단위 테스트하고자 할 때, 실제 데이터베이스 연결 없이 독립적으로 로직을 검증하기가 매우 까다롭다. 모의 객체(Mock Object)를 사용하려 해도, 의존성 생성 로직이 클래스 내부에 하드코딩되어 있어 이를 대체하기가 복잡하다.1 셋째, 코드의 재사용성과 확장성이 심각하게 제한된다.

UserService는 특정 데이터베이스 구현과 한 몸처럼 묶여 있어 다른 맥락에서 재사용하거나 새로운 기능을 확장하기 어렵다.1

제어의 역전은 바로 이러한 강한 결합의 문제를 해결하기 위해 등장한 패러다임의 전환이다. IoC의 핵심 철학은 프로그램의 제어 흐름 주체를 개발자의 코드에서 외부의 독립적인 존재, 즉 프레임워크나 컨테이너(Container)로 이전하는 것이다.3 더 이상 객체는 자신이 사용할 의존 객체를 능동적으로 선택하거나 생성하지 않는다. 대신, 모든 제어 권한을 외부의 특별한 대상에게 위임하고, 자신은 수동적으로 필요한 의존성을 제공받아 자신의 핵심 책임에만 집중한다.1 이러한 구조적 변화는 전통적 방식에서 객체가 스스로 의존성을 찾고 생성하며 자신의 생명주기를 관리하는 ‘능동적(active)’ 행위자였던 것에서, 프레임워크의 결정에 따라 수동적으로 조립되고 사용되는 ‘수동적(passive)’ 존재로 변화함을 의미한다. 이 ‘능동성’에서 ‘수동성’으로의 전환은 개별 객체의 책임을 줄이는 대신, 시스템 전체의 조립과 생명주기 관리를 담당하는 ‘조정자(Orchestrator)’로서 프레임워크의 역할을 극대화한다.

이러한 개념은 종종 ‘헐리우드 원칙(Hollywood Principle)’이라는 비유로 설명된다: “Don’t call us, we’ll call you(우리가 당신을 부를 것이니, 우리에게 전화하지 마시오)”.6 이는 개발자의 코드가 프레임워크의 기능을 호출하는 것이 아니라, 프레임워크가 정해진 흐름에 따라 개발자의 코드를 호출하고 실행하는 구조적 역전을 명확히 보여준다. 이처럼 IoC의 도입은 단순히 결합도를 낮추는 기술적 행위를 넘어, 개발자가 개별 컴포넌트의 미시적 제어에서 벗어나 시스템의 거시적 구조와 비즈니스 로직에 집중하도록 유도하는 아키텍처 수준의 전략적 결정이며, 이는 재사용 가능한 코드의 집합인 라이브러리(Library)와 애플리케이션의 전체 구조를 제어하는 프레임워크(Framework)를 구분하는 핵심적인 차이점이기도 하다.2

결론적으로, 본 보고서는 제어의 역전(IoC) 원칙을 이론적, 실증적 관점에서 심층적으로 고찰하는 것을 목표로 한다. 먼저 IoC와 혼용되는 의존성 주입(Dependency Injection, DI), 의존관계 역전 원칙(Dependency Inversion Principle, DIP)의 개념을 명확히 분리하고 그 관계를 정립할 것이다. 이어서 DI와 서비스 로케이터(Service Locator) 등 IoC를 구현하는 구체적인 패턴들을 비교 분석하고, 마지막으로 Spring,.NET, FastAPI와 같은 현대 프레임워크들이 IoC 컨테이너를 통해 이 원칙을 어떻게 구현하고 있는지 그 내부 동작 원리를 상세히 탐구함으로써, IoC가 현대 소프트웨어 아키텍처에서 차지하는 의의와 가치를 총체적으로 조망하고자 한다.

소프트웨어 설계 원칙을 논할 때, 제어의 역전(IoC), 의존성 주입(DI), 그리고 의존관계 역전 원칙(DIP)은 가장 빈번하게 언급되면서도 그 경계가 모호하게 사용되는 개념들이다. 이 세 가지 개념은 느슨한 결합(Loose Coupling)이라는 동일한 목표를 지향하지만, 서로 다른 추상화 수준에서 각기 다른 측면을 다룬다.7 이들의 관계를 명확히 이해하는 것은 견고하고 유연한 아키텍처를 구축하기 위한 첫걸음이다. 저명한 소프트웨어 공학자 Martin Fowler는 이들의 관계를 각각 ‘Shape(모양)’, ‘Direction(방향)’, ‘Wiring(배선)’이라는 직관적인 비유로 설명하였으며, 이를 중심으로 각 개념의 본질과 상호작용을 심층적으로 분석한다.9

의존관계 역전 원칙(Dependency Inversion Principle, DIP)은 객체 지향 설계의 5대 원칙인 SOLID 중 마지막 ‘D’에 해당하는 핵심 원칙이다. DIP는 소프트웨어 모듈 간의 의존 관계가 가져야 할 바람직한 ‘모양(Shape)’을 규정하는 설계 철학이다.9 이 원칙은 두 가지 명제로 구성된다 13:

  1. 상위 수준 모듈은 하위 수준 모듈에 의존해서는 안 된다. 둘 모두 추상화에 의존해야 한다.
  2. 추상화는 세부 사항에 의존해서는 안 된다. 세부 사항이 추상화에 의존해야 한다.

여기서 ‘상위 수준 모듈’은 애플리케이션의 핵심 비즈니스 로직이나 정책을 담고 있는 모듈을 의미하며, 상대적으로 변동성이 적다. 반면 ‘하위 수준 모듈’은 데이터베이스 접근, 파일 시스템, 네트워크 통신과 같이 상위 모듈의 정책을 구현하기 위한 구체적인 기술이나 세부 사항을 다루는 모듈로, 변동성이 크다.10

전통적인 의존 관계에서는 상위 모듈이 하위 모듈을 직접 참조한다. 예를 들어, 주문 처리 로직을 담은 OrderServiceImpl(상위 모듈)이 고정 금액 할인 정책을 구현한 FixDiscountPolicy(하위 모듈의 구체 클래스)를 new 키워드를 통해 직접 생성하고 사용하는 구조이다.13 이 경우, 할인 정책을 비율 할인 정책(RateDiscountPolicy)으로 변경하려면 상위 모듈인 OrderServiceImpl의 코드를 직접 수정해야만 한다. 이는 안정적이어야 할 상위 모듈이 변덕스러운 하위 모듈에 종속되는, 바람직하지 않은 의존 관계를 형성한다.13

DIP는 이러한 의존성의 방향을 ‘역전’시킨다. 즉, OrderServiceImplFixDiscountPolicy라는 구체 클래스에 직접 의존하는 대신, DiscountPolicy라는 ‘추상화(인터페이스)’에만 의존하도록 구조를 변경한다. 동시에, 하위 모듈인 FixDiscountPolicyRateDiscountPolicy 역시 DiscountPolicy 인터페이스를 구현하도록 만든다. 결과적으로 상위 모듈과 하위 모듈 모두가 추상화에 의존하게 되며, 의존성의 방향은 ‘구체’에서 ‘추상’으로 향하게 된다.7 이처럼 DIP는 의존 관계의 화살표가 구체적인 구현이 아닌 추상적인 인터페이스를 향해야 함을 규정함으로써, 시스템의 구조적 안정성과 유지보수성을 확보하는 것을 궁극적인 목표로 한다.17

제어의 역전(Inversion of Control, IoC)은 프로그램의 실행 흐름, 즉 제어의 주체가 누구인지를 다루는 보다 광범위하고 포괄적인 개념이다.8 이는 제어의 ‘방향(Direction)’에 관한 원칙이다.9

전통적인 절차적 프로그래밍에서 프로그램의 제어 흐름은 개발자가 작성한 main 함수와 같은 진입점에서 시작하여, 필요한 기능이 있을 때마다 라이브러리의 함수를 명시적으로 호출하는 방식으로 진행된다.1 이 구조에서 제어의 주체는 명백히 개발자의 코드이다.

IoC는 이 제어 흐름의 방향을 완전히 뒤집는다.19 IoC가 적용된 아키텍처, 특히 프레임워크 환경에서는 개발자가 작성한 코드가 프레임워크를 호출하는 것이 아니라, 프레임워크가 애플리케이션의 전체 흐름을 주도하며 특정 시점에 개발자의 코드를 호출(callback)한다.6 예를 들어, 웹 프레임워크는 HTTP 요청을 수신하고 분석한 뒤, 해당 요청을 처리하도록 등록된 개발자의 컨트롤러 메서드를 호출한다. 개발자는 전체 요청-응답 사이클을 제어하는 것이 아니라, 프레임워크가 마련한 틀 안에서 특정 이벤트나 요청을 처리하는 로직만 작성하면 된다.

이처럼 IoC는 제어의 주체를 개발자로부터 프레임워크로 위임하는 모든 종류의 설계 방식을 포괄한다. 따라서 의존성 주입(DI)은 IoC를 구현하는 하나의 방법에 불과하며, 그 외에도 템플릿 메서드 패턴(Template Method Pattern), 이벤트 기반 아키텍처(Event-driven Architecture), 콜백(Callback) 메커니즘 등 프레임워크가 프로그램의 흐름을 주도하는 다양한 방식들이 모두 IoC의 범주에 속한다.5

의존성 주입(Dependency Injection, DI)은 IoC 원칙을 구현하는 가장 대표적이고 구체적인 디자인 패턴이다.3 DI는 한 객체가 사용하는 다른 객체(의존성)를 어떻게 제공받을 것인가, 즉 객체 간의 관계를 ‘어떻게 연결(Wiring)’할 것인가에 대한 해법을 제시한다.9

DI의 핵심은 객체가 필요로 하는 의존성을 내부에서 직접 생성(new)하거나 찾는(lookup) 것이 아니라, 외부의 독립된 조립기(Assembler), 즉 IoC 컨테이너가 해당 의존성을 생성하여 객체에게 ‘주입’해주는 것이다.3 앞서 DIP에서 설명한 OrderServiceImpl 예시에서, OrderServiceImplDiscountPolicy 인터페이스에만 의존할 뿐, 그 구현체가 FixDiscountPolicy인지 RateDiscountPolicy인지는 알지 못한다. 어떤 구현체를 사용할지에 대한 결정은 외부 설정 파일(XML, Annotation 등)에 명시되며, IoC 컨테이너는 이 설정을 읽어 적절한 할인 정책 객체를 생성한 뒤, OrderServiceImpl 객체를 생성할 때 생성자나 세터 메서드를 통해 주입해준다.13

이처럼 DI는 의존 객체의 생성과 사용의 책임을 명확하게 분리한다. 객체는 오직 자신의 비즈니스 로직을 수행하는 책임만 지게 되며, 필요한 의존성을 구성하고 조립하는 책임은 전적으로 외부의 IoC 컨테이너가 담당한다. 이를 통해 DI는 DIP가 요구하는 ‘추상화에 대한 의존’ 관계를 실제로 구현하고, 객체 간의 결합도를 효과적으로 낮추는 실질적인 메커니즘으로 작동한다.

결론적으로 DIP, IoC, DI는 서로 밀접하게 연관되어 있지만 명확히 구분되는 개념이다. 이들의 관계는 동의어가 아니라, ‘목표(DIP) - 전략(IoC) - 전술(DI)’의 위계적 관계로 이해할 수 있다.

따라서 “DI를 사용하면 자연스럽게 IoC가 적용되고, 이를 통해 DIP를 준수하기 용이해진다”는 인과 관계가 성립한다. 하지만 DI가 IoC의 유일한 구현 방법은 아니며 8, DI를 사용한다고 해서 반드시 DIP가 완벽하게 지켜지는 것도 아니다. 개발자가 추상화 대신 구체 클래스를 주입하도록 설정한다면 DI를 사용하더라도 DIP를 위반할 수 있다. 이 세 가지 개념의 차이와 관계를 명확히 구분하고 이해할 때, 비로소 각 개념의 진정한 가치를 활용하여 유연하고 확장 가능한 소프트웨어 아키텍처를 설계할 수 있다.

제어의 역전(IoC)이라는 원칙을 실제 코드에 구현하기 위한 방법론은 크게 두 가지 패턴으로 나뉜다: 의존성 주입(Dependency Injection, DI)과 서비스 로케이터(Service Locator)이다. 두 패턴 모두 객체가 자신의 의존성을 직접 생성하지 않도록 하여 결합도를 낮추는 공통된 목표를 가지지만, 의존성을 해결하는 방식과 그로 인해 파생되는 아키텍처의 특성에서 근본적인 차이를 보인다. 본 장에서는 먼저 가장 널리 사용되는 DI의 세 가지 유형을 심층 비교하고, 이어서 서비스 로케이터 패턴의 작동 방식과 그것이 왜 현대 소프트웨어 설계에서 안티패턴(Anti-Pattern)으로 간주되는지를 논리적으로 분석한다.

의존성 주입은 외부의 IoC 컨테이너가 의존 객체를 대상 객체에게 전달하는 방식에 따라 생성자 주입, 세터 주입, 필드 주입으로 구분된다. 각 방식은 뚜렷한 장단점을 가지며, 특히 생성자 주입은 현대 프레임워크에서 가장 권장되는 방식으로 그 이유를 명확히 이해하는 것이 중요하다.23

생성자 주입은 클래스의 생성자(constructor)를 통해 의존성을 주입받는 방식이다.22 객체가 생성되는 시점에 필요한 모든 의존성이 매개변수로 전달되며, 이는 객체가 유효한 상태로 온전하게 생성되기 위한 필수 조건을 명시하는 것과 같다.

이러한 장점들은 단순히 기술적 우위를 넘어, 클래스 설계의 ‘정직성(Honesty)’과 ‘투명성(Transparency)’을 강제하는 효과를 낳는다. 클래스의 생성자는 해당 클래스가 존재하기 위한 ‘최소 필수 조건’을 정의하는 계약(Contract)이며, 생성자 주입은 이 계약에 모든 필수 의존성을 명시하도록 강제한다. 만약 생성자의 매개변수가 과도하게 많아진다면, 이는 해당 클래스가 단일 책임 원칙(SRP)을 위반하고 있을 가능성이 높다는 강력한 ‘코드 스멜(Code Smell)’로 작용하여 개발자에게 리팩토링의 필요성을 알리는 가드레일 역할을 한다.28

세터 주입은 객체가 생성된 이후에 공개된 set 메서드나 프로퍼티를 통해 의존성을 주입하는 방식이다.22

필드 주입은 @Autowired(Spring)나 @Inject와 같은 어노테이션을 클래스의 필드에 직접 선언하여 의존성을 주입하는 방식이다.

이러한 심각한 단점들 때문에 필드 주입은 테스트 코드나 일부 특수한 경우를 제외하고는 애플리케이션 코드에서 사용하는 것이 강력히 비권장된다.

구분 생성자 주입 (Constructor Injection) 세터 주입 (Setter Injection) 필드 주입 (Field Injection)
메커니즘 객체 생성 시점에 생성자를 통해 주입 객체 생성 후 set 메서드를 통해 주입 리플렉션을 통해 필드에 직접 주입
불변성 final 키워드로 보장 가능 (매우 높음) 보장 불가 (낮음) 보장 불가 (낮음)
의존성 명시성 생성자 시그니처에 명확히 드러남 (매우 높음) set 메서드를 통해 노출되나 분산됨 (중간) 외부에서 파악 불가 (매우 낮음)
순환 참조 감지 컨테이너 구동 시점에 감지 가능 (안전) 스택 오버플로우 발생 가능 (위험) 스택 오버플로우 발생 가능 (위험)
테스트 용이성 DI 컨테이너 없이 테스트 용이 (매우 높음) set 메서드 호출 필요 (중간) DI 컨테이너 의존성 높음 (매우 낮음)
권장 사용 사례 필수적이고 불변인 의존성 주입 (강력 권장) 선택적이거나 변경 가능한 의존성 주입 사용 비권장 (테스트 코드 등 예외적 허용)
주요 단점 의존성이 많아지면 생성자가 길어짐 의존성 주입 누락 가능, 불완전한 객체 상태 허용 DI 컨테이너에 강하게 결합, 숨겨진 의존성

서비스 로케이터는 DI와는 다른 방식으로 IoC를 구현하는 패턴이다. 이 패턴은 애플리케이션 전역에서 접근 가능한 중앙 집중화된 ‘서비스 로케이터’ 또는 ‘레지스트리’ 객체를 사용한다.5 의존성이 필요한 클래스는 이 로케이터에게 직접 필요한 서비스의 키(이름 또는 타입)를 전달하여 해당 서비스의 인스턴스를 ‘요청(request)’하고 ‘가져오는(pull)’ 방식으로 의존성을 해결한다.26

// 서비스 로케이터 패턴 예시
public class MovieLister {
    public Movie moviesDirectedBy(String director) {
        // 로케이터에게 직접 MovieFinder 서비스를 요청한다.
        MovieFinder finder = ServiceLocator.getInstance().getFinder();
        return finder.findByDirector(director);
    }
}

DI와 서비스 로케이터의 근본적인 차이는 의존성을 다루는 방식에 있다. DI가 의존성을 외부에서 대상 객체에게 ‘밀어 넣어주는(Push)’ 수동적인 방식이라면, 서비스 로케이터는 대상 객체가 능동적으로 로케이터에게 의존성을 ‘끌어오는(Pull)’ 방식이다.26 이로 인해 DI를 사용하는 클래스는 DI 컨테이너의 존재 자체를 인지할 필요가 없지만, 서비스 로케이터를 사용하는 모든 클래스는 서비스 로케이터라는 특정 구현체에 대한 명시적인 의존성을 갖게 된다.26

서비스 로케이터는 의존성 생성을 중앙화한다는 점에서 강한 결합을 일부 해소하는 것처럼 보이지만, 실제로는 더 교묘하고 심각한 문제들을 야기하여 많은 전문가들에 의해 안티패턴으로 간주된다.31

구분 의존성 주입 (Dependency Injection) 서비스 로케이터 (Service Locator)
의존성 해결 주체 외부 컨테이너 (수동적, Push 방식) 클래스 자신 (능동적, Pull 방식)
의존성 명시성 생성자/메서드에 명시적으로 드러남 (투명) 클래스 내부에 숨겨짐 (불투명)
결합도 의존성의 ‘추상’에 의존 (느슨한 결합) ‘서비스 로케이터’라는 ‘구현’에 의존 (강한 결합)
테스트 용이성 모의 객체 주입이 용이 (높음) 로케이터 상태 관리의 어려움 (낮음)
오류 감지 시점 컴파일 또는 구동 시점 런타임 시점
SOLID 원칙 준수하기 용이함 SRP, ISP 등 위반 가능성 높음

결론적으로, 의존성 주입, 특히 생성자 주입은 의존성을 명시적으로 드러내고, 불변성을 보장하며, 테스트 용이성을 극대화하는 등 견고한 객체 지향 설계를 촉진하는 반면, 서비스 로케이터는 의존성을 숨기고 런타임 오류 가능성을 높이는 등 여러 설계 원칙을 위반하여 시스템을 취약하게 만드는 경향이 있다. 따라서 현대적인 소프트웨어 개발에서는 서비스 로케이터 패턴의 사용을 지양하고 의존성 주입 패턴을 채택하는 것이 압도적으로 권장된다.

제어의 역전(IoC) 원칙은 이론에 머무르지 않고, 현대의 주요 소프트웨어 프레임워크에 깊숙이 내장되어 개발의 근간을 이룬다. 각 프레임워크는 저마다의 철학과 언어적 특성을 반영하여 독자적인 IoC 컨테이너와 의존성 주입(DI) 메커니즘을 구현하고 있다. 본 장에서는 엔터프라이즈 애플리케이션의 표준으로 자리 잡은 Java의 Spring, 플랫폼 차원의 통합을 중시하는 C#의.NET, 그리고 동적 언어의 유연성을 극대화한 Python의 FastAPI를 중심으로, 이들 프레임워크가 IoC 원칙을 어떻게 실현하는지 그 내부 동작 원리를 비교 분석한다. 이를 통해 추상적인 원칙이 실제 엔지니어링 환경에서 어떻게 구체화되는지 실증적으로 탐구한다.

Spring 프레임워크의 심장은 단연 IoC 컨테이너이며, 이는 ApplicationContext 인터페이스로 대표된다. Spring의 IoC 컨테이너는 단순한 객체 생성 및 DI 기능을 제공하는 BeanFactory의 역할을 포함하면서, 관점 지향 프로그래밍(AOP) 통합, 이벤트 발행, 국제화(i18n) 메시지 처리 등 엔터프라이즈급 애플리케이션 개발에 필수적인 포괄적인 기능을 제공하는 고도화된 컨테이너이다.38 Spring에서 IoC 컨테이너가 관리하는 객체는 특별히 ‘Bean’이라 칭한다.39

Spring IoC 컨테이너의 내부 동작 과정은 다음과 같은 단계로 이루어진다.

  1. 설정 메타데이터 로딩: 컨테이너는 애플리케이션을 구성하는 Bean과 그들 간의 의존 관계를 정의한 설정 정보를 읽어들인다. 이 정보는 전통적인 XML 파일(<bean> 태그), 어노테이션 기반(@Component, @Service, @Repository 등), 또는 Java 기반 설정(@Configuration, @Bean) 등 다양한 형태로 제공될 수 있다.40
  2. Bean Definition 생성: 로드된 메타데이터는 각 Bean의 ‘설계도’에 해당하는 BeanDefinition 객체로 변환된다. BeanDefinition에는 Bean의 클래스 이름, 스코프(scope), 생성자 인자, 프로퍼티 값 등 Bean을 생성하고 구성하는 데 필요한 모든 정보가 담겨 있으며, 컨테이너 내부의 BeanDefinitionRegistry에 저장된다.
  3. Bean 인스턴스화 및 조립: ApplicationContext가 초기화될 때, 컨테이너는 BeanDefinition 정보를 바탕으로 실제 Bean 객체를 인스턴스화한다. 이 과정은 주로 리플렉션(Reflection) API를 통해 클래스의 생성자를 호출하는 방식으로 이루어진다.39 의존 관계에 있는 다른 Bean이 필요할 경우, 해당 Bean을 먼저 생성하거나 이미 생성된 Bean을 찾아 주입(DI)하여 객체 그래프를 완성한다.
  4. 생명주기 관리: Bean이 생성된 후, 컨테이너는 @PostConstruct 어노테이션이 붙은 메서드나 InitializingBean 인터페이스의 afterPropertiesSet() 메서드를 호출하여 초기화 작업을 수행할 기회를 제공한다. 마찬가지로 애플리케이션이 종료되어 컨테이너가 닫힐 때는 @PreDestroy 어노테이션이 붙은 메서드나 DisposableBean 인터페이스의 destroy() 메서드를 호출하여 자원 해제와 같은 소멸 작업을 수행하도록 한다. 이처럼 Spring 컨테이너는 Bean의 생성부터 소멸까지 전 생명주기를 체계적으로 관리한다.24

또한 Spring은 Bean의 생명주기를 더욱 정밀하게 제어하기 위해 다양한 스코프(Scope)를 제공한다. 기본값인 singleton은 컨테이너 내에서 단 하나의 인스턴스만 생성되어 공유되며, prototype은 요청할 때마다 새로운 인스턴스를 생성한다. 웹 환경에서는 request(HTTP 요청마다 생성), session(HTTP 세션마다 생성) 등의 스코프를 통해 상태를 관리할 수 있다.42 이처럼 Spring의 IoC 컨테이너는 강력하고 유연한 설정 방식과 정교한 생명주기 관리 기능을 통해 복잡한 엔터프라이즈 애플리케이션의 근간을 이룬다.

.NET(과거.NET Core)은 프레임워크 차원에서 표준화된 DI 컨테이너를 내장하여 개발자에게 일관된 개발 경험을 제공하는 데 중점을 둔다. 핵심 구성 요소는 IServiceCollectionIServiceProvider이다. 개발자는 애플리케이션 시작 지점(일반적으로 Program.cs)에서 IServiceCollection에 서비스(의존성의 추상 타입)와 그 구현체를 등록하고, BuildServiceProvider 메서드를 호출하여 실제 IoC 컨테이너인 IServiceProvider를 생성한다. 이후 IServiceProvider는 등록된 서비스의 인스턴스를 생성하고 의존성을 해결(Resolve)하는 역할을 수행한다.44

.NET의 DI 시스템에서 가장 중요한 개념은 서비스 생명주기(Service Lifetime)이며, 이는 서비스 인스턴스가 언제 생성되고 폐기되는지를 결정한다. 세 가지 주요 생명주기는 다음과 같다.45

.NET DI 컨테이너는 생명주기 규칙을 엄격하게 관리한다. 특히 수명이 긴 서비스가 수명이 짧은 서비스를 직접 의존성으로 주입받는 것을 방지하는데, 이를 ‘포획된 의존성(Captive Dependency)’ 문제라고 한다. 예를 들어, Singleton 서비스가 Scoped 서비스를 생성자에서 주입받으면, Scoped 서비스는 Singleton 서비스와 함께 애플리케이션 전체 생명주기 동안 살아남게 되어 의도치 않은 싱글톤처럼 동작하게 된다..NET은 개발 환경에서 이러한 문제를 감지하고 예외를 발생시킨다. 이 문제를 해결하기 위해서는 Singleton 서비스가 IServiceScopeFactory를 주입받아, 필요할 때마다 명시적으로 새로운 스코프를 생성하고 그 안에서 Scoped 서비스를 해결하여 사용해야 한다.45

Python 웹 프레임워크인 FastAPI는 Python의 동적 특성과 타입 힌트(Type Hint)를 영리하게 활용하여 매우 직관적이고 강력한 DI 시스템을 제공한다. 복잡한 설정 파일이나 명시적인 컨테이너 구성 없이, 함수의 매개변수를 선언하는 것만으로 DI가 이루어진다. 이 시스템의 핵심은 Depends 함수이다.50

FastAPI의 DI는 다음과 같은 내부 원리로 동작한다.

  1. 의존성 선언: 개발자는 재사용하고자 하는 로직(예: 데이터베이스 세션 관리, 사용자 인증)을 일반적인 Python 함수(이를 ‘dependable’이라 칭함)로 작성한다. 그리고 이 의존성을 사용하려는 경로 작동 함수(route handler)의 매개변수 타입 힌트 뒤에 Depends(dependable_function)를 명시한다.52
  2. 의존성 해결: API 요청이 들어오면, FastAPI는 해당 경로 작동 함수의 시그니처를 분석하여 Depends로 선언된 매개변수를 식별한다.54 FastAPI는 Depends에 지정된 dependable 함수를 호출하여 그 결과를 얻어낸다. 만약 이 dependable 함수가 또 다른 의존성을 Depends로 선언하고 있다면, FastAPI는 이 의존성 트리를 재귀적으로 탐색하며 필요한 모든 의존성을 순서대로 해결한다.54
  3. 결과 주입 및 캐싱: dependable 함수의 반환 값은 경로 작동 함수의 해당 매개변수에 인자로 주입된다. 이 모든 과정은 단일 요청의 생명주기 내에서 일어나며, 동일한 요청 내에서 같은 dependable이 여러 번 필요할 경우, 그 결과는 캐싱되어 한 번만 실행되므로 성능 저하를 방지한다.53

FastAPI는 yield 문을 사용하여 의존성의 생명주기를 더욱 정교하게 관리하는 기능도 제공한다. dependable 함수에서 return 대신 yield를 사용하면, yield 이전의 코드는 경로 작동 함수가 실행되기 전에 실행되고(예: 데이터베이스 커넥션 획득), yield 이후의 코드는 경로 작동 함수의 실행이 완료된 후에 실행된다(예: 데이터베이스 커넥션 반환). 이는 Python의 컨텍스트 관리자(with 문)와 유사한 방식으로, 자원의 안전한 획득과 해제를 보장한다.56

결론적으로, Spring,.NET, FastAPI는 IoC라는 동일한 원칙을 구현하지만, 그 방식은 각 기술 생태계의 철학을 뚜렷하게 반영한다. Spring은 엔터프라이즈 환경의 복잡성을 다루기 위한 강력하고 명시적인 제어 기능을 제공한다..NET은 플랫폼 차원에서 표준화되고 일관된 DI 경험을 제공하며 웹 애플리케이션에 최적화된 생명주기 관리를 강조한다. FastAPI는 Python의 동적인 특성을 극대화하여 ‘코드가 곧 설정’이라는 철학 아래 최소한의 코드로 최대의 표현력과 생산성을 추구한다. 이러한 차이점을 이해하는 것은 각 프레임워크의 강점을 최대한 활용하는 아키텍처를 설계하는 데 중요한 지침이 된다.

본 보고서는 제어의 역전(IoC)이 전통적인 프로그래밍의 강한 결합 문제를 해결하기 위한 패러다임의 전환에서 시작하여, 의존성 주입(DI)과 의존관계 역전 원칙(DIP)과 같은 관련 개념들과의 관계 속에서 어떻게 현대 소프트웨어 아키텍처의 핵심 원칙으로 자리 잡았는지를 다각적으로 고찰하였다. IoC는 단순히 객체 생성의 책임을 이전하는 기술적 패턴을 넘어, 시스템의 유연성, 확장성, 그리고 유지보수성을 근본적으로 향상시키는 아키텍처 철학이다. 그 현대적 의의는 관점 지향 프로그래밍(AOP)이나 마이크로서비스 아키텍처(MSA)와 같은 최신 패러다임과의 시너지를 통해 더욱 명확해진다.

IoC와 AOP는 서로 다른 문제를 해결하지만, 함께 사용될 때 강력한 시너지를 발휘하는 상호 보완적인 관계이다.58 AOP는 로깅, 트랜잭션 관리, 보안과 같이 여러 모듈에 걸쳐 반복적으로 나타나는 ‘횡단 관심사(Cross-cutting Concerns)’를 핵심 비즈니스 로직으로부터 분리하여 별도의 모듈(Aspect)로 관리하는 것을 목표로 한다.60

IoC 컨테이너는 이러한 AOP의 적용을 위한 완벽한 기반 인프라를 제공한다. 컨테이너가 애플리케이션의 모든 객체(Bean)의 생성과 관계 설정을 전담하기 때문에, AOP 프레임워크는 이 과정에 개입하여 원본 객체 대신 횡단 관심사 로직이 추가된 프록시(Proxy) 객체를 생성하고 주입할 수 있다.60 예를 들어, Spring 프레임워크에서 개발자가 서비스 메서드에

@Transactional 어노테이션을 추가하면, IoC 컨테이너는 해당 서비스의 원본 Bean 대신 트랜잭션 시작과 종료 로직이 포함된 프록시 Bean을 생성하여 다른 객체들에게 주입한다. 이로 인해 개발자는 비즈니스 로직 코드에 단 한 줄의 트랜잭션 관련 코드도 작성하지 않고도 선언적으로 트랜잭션 관리를 적용할 수 있다. 이처럼 IoC는 객체 그래프의 제어권을 가짐으로써 AOP가 비즈니스 로직의 수정 없이 부가 기능을 투명하게 적용할 수 있는 토대를 마련하며, 두 원칙은 함께 시스템의 모듈성을 극대화하는 데 기여한다.62

각각의 서비스가 독립적으로 개발, 배포, 확장되는 것을 목표로 하는 마이크로서비스 아키텍처(MSA)에서 ‘느슨한 결합’은 시스템의 성공을 좌우하는 가장 중요한 원칙 중 하나이다. 만약 하나의 서비스가 다른 서비스의 구체적인 구현(예: 특정 IP 주소, 내부 클래스 구조)에 직접 의존한다면, 의존 대상 서비스의 작은 변경만으로도 의존하는 서비스의 코드를 수정하고 재배포해야 하는 연쇄 장애가 발생하여 MSA의 핵심 가치인 ‘독립성’과 ‘민첩성’이 심각하게 훼손된다.

IoC와 DI는 이러한 문제를 해결하는 핵심적인 도구이다. 각 마이크로서비스는 다른 서비스와 통신할 때, 해당 서비스의 구체적인 구현이 아닌 추상화된 인터페이스(예: API 명세)에만 의존해야 한다. DI 컨테이너는 서비스 디스커버리(Service Discovery) 메커니즘과 연동하여, 런타임에 해당 인터페이스를 구현한 실제 서비스의 네트워크 위치를 찾아 통신을 위한 클라이언트 객체(예: Spring Cloud의 Feign Client)를 생성하고 이를 필요로 하는 서비스에 주입해준다.63 이를 통해 서비스 간의 결합은 컴파일 시점이 아닌 런타임에 동적으로 결정되며, 인터페이스 계약만 유지된다면 개별 서비스의 내부 구현 변경, 스케일 아웃, 또는 신규 버전으로의 교체가 다른 서비스에 미치는 영향을 최소화할 수 있다.64 즉, DI는 MSA 환경에서 서비스 간의 자율성과 회복탄력성(Resilience)을 보장하는 필수적인 아키텍처 패턴이다.

소프트웨어 시스템은 시간이 흐름에 따라 요구사항 변경, 기능 추가, 기술 스택 변화 등으로 인해 필연적으로 복잡도가 증가하고 구조가 무너지는 경향, 즉 ‘엔트로피(Entropy)’가 증가하는 경향이 있다. IoC는 이러한 소프트웨어 엔트로피에 저항하는 핵심적인 아키텍처 메커니즘으로 작용한다. IoC와 DI는 모든 의존성 관리를 ‘컴포지션 루트(Composition Root)’라는 단일한 장소(또는 설정)로 중앙화하여, 시스템의 전체적인 구조와 객체 간의 관계를 명시적인 청사진으로 관리한다. 새로운 의존성을 추가하거나 기존 의존성을 교체할 때, 시스템 전체에 흩어져 있는 코드를 수정하는 대신 이 중앙 설정만 변경하면 되므로 변경의 파급 효과를 제어하고 국소화(Localize)할 수 있다.

결론적으로, 제어의 역전은 단순히 코딩 기법이나 디자인 패턴을 넘어, 변화에 유연하고 지속 가능한 시스템을 구축하기 위한 근본적인 아키텍처 ‘규율’이다. 성공적인 IoC의 적용은 단순히 프레임워크를 사용하는 행위에서 그치지 않는다. 의존관계 역전 원칙(DIP)에 기반한 추상화 중심의 설계, 단일 책임 원칙(SRP)에 입각한 역할과 책임의 명확한 분리, 그리고 시스템의 특성을 고려한 의존성 주입 방식의 전략적 선택이 반드시 동반되어야 한다. 이러한 원칙들을 체화하고 실천할 때, 비로소 우리는 시간이 지나도 그 가치를 잃지 않는 견고하고 우아한 소프트웨어 시스템을 구축할 수 있을 것이다.참고 자료

  1. ABOUT.Series (12) IoC (Inversion of Control; 제어의 역전) & DI (Dependency Injection; 의존성 주입) - THE DEVELOPER - 티스토리, 8월 17, 2025에 액세스, https://bitkunst.tistory.com/entry/ABOUTSeries-12-IoC-Inversion-of-Control-%EC%A0%9C%EC%96%B4%EC%9D%98-%EC%97%AD%EC%A0%84-DI-Dependency-Injection-%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%A3%BC%EC%9E%85
  2. 제어의 역전(IOC) 이란? - 코딩 석세스 - 티스토리, 8월 17, 2025에 액세스, https://stonehee99.tistory.com/15
  3. IoC (제어의 역전) 이해하기 - 행복한코딩생활 - 티스토리, 8월 17, 2025에 액세스, https://jki09871.tistory.com/56
  4. rei050r.tistory.com, 8월 17, 2025에 액세스, https://rei050r.tistory.com/232#:~:text=%EC%A0%9C%EC%96%B4%EC%9D%98%20%EC%97%AD%EC%A0%84%EC%9D%B4%EB%9E%80%3F,%EC%9D%84%20%EC%9C%84%EC%9E%84%ED%95%98%EB%8A%94%20%EA%B2%83%EC%9E%85%EB%8B%88%EB%8B%A4.
  5. Understanding Inversion of Control (IoC): A Key Principle for Decoupled Architecture by Deewakar Kumar Medium, 8월 17, 2025에 액세스, https://medium.com/@deewakar.kmr/understanding-inversion-of-control-ioc-a-key-principle-for-decoupled-architecture-47063899177c
  6. 제어의 역전(Inversion of Control, IoC) 파헤치기 - 카미유 테크블로그, 8월 17, 2025에 액세스, https://june0122.tistory.com/18
  7. Dependency Injection, Dependency Inversion, IoC SSENSE-TECH - Medium, 8월 17, 2025에 액세스, https://medium.com/ssense-tech/dependency-injection-vs-dependency-inversion-vs-inversion-of-control-lets-set-the-record-straight-5dc818dc32d1
  8. Inversion of Control vs Dependency Injection - Stack Overflow, 8월 17, 2025에 액세스, https://stackoverflow.com/questions/6550700/inversion-of-control-vs-dependency-injection
  9. How is Inversion of Control related to Dependency Inversion - Software Engineering Stack Exchange, 8월 17, 2025에 액세스, https://softwareengineering.stackexchange.com/questions/311674/how-is-inversion-of-control-related-to-dependency-inversion
  10. Breaking Down Dependency Inversion, IoC, and DI - DEV Community, 8월 17, 2025에 액세스, https://dev.to/ehsanahmadzadeh/breaking-down-dependency-inversion-ioc-and-di-5dh9
  11. Demystifying Inversion of Control (IoC) - DEV Community, 8월 17, 2025에 액세스, https://dev.to/parasmm/demystifying-inversion-of-control-ioc-3670
  12. Difference between “Inversion of Control”, “Dependency inversion” and “Decoupling” - Stack Overflow, 8월 17, 2025에 액세스, https://stackoverflow.com/questions/3912504/difference-between-inversion-of-control-dependency-inversion-and-decouplin
  13. DIP(Dependency Inversion Principle),의존관계 역전 원칙, 8월 17, 2025에 액세스, https://gyuhoonk.github.io/dependency-inversion-principle
  14. Dependency inversion principle - Wikipedia, 8월 17, 2025에 액세스, https://en.wikipedia.org/wiki/Dependency_inversion_principle
  15. Inversion of Control (IOC) Dependency Injection (DI) by Tarun Jain - Medium, 8월 17, 2025에 액세스, https://tarunjain07.medium.com/inversion-of-control-ioc-dependency-injection-di-9155a4151db9
  16. gyuhoonk.github.io, 8월 17, 2025에 액세스, https://gyuhoonk.github.io/dependency-inversion-principle#:~:text=%EA%B0%9D%EC%B2%B4%20%EC%A7%80%ED%96%A5%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%97%90%EC%84%9C%20%EC%9D%98%EC%A1%B4,%EB%8F%85%EB%A6%BD%EB%90%98%EA%B2%8C%20%ED%95%A0%20%EC%88%98%20%EC%9E%88%EB%8B%A4.
  17. 의존성 역전(Dependency Inversion)이란? - Unknownpgr, 8월 17, 2025에 액세스, https://unknownpgr.com/posts/dependency-inversion/index.html
  18. [iOS - Swift] 의존 관계 역전 원칙 (DIP, Dependency Inversion Principle) - 코딩과 사람 사는 이야기 - 티스토리, 8월 17, 2025에 액세스, https://newwave.tistory.com/219
  19. Inversion of control - Wikipedia, 8월 17, 2025에 액세스, https://en.wikipedia.org/wiki/Inversion_of_control
  20. inversion of control (IoC) is a programming principle. IoC inverts the flow of control as compared to traditional control flow. In IoC, custom-written portions of a computer program receive the flow of control from a generic framework. : r/ProgrammerHumor - Reddit, 8월 17, 2025에 액세스, https://www.reddit.com/r/ProgrammerHumor/comments/t6swga/inversion_of_control_ioc_is_a_programming/
  21. dependency injection - Spring definition of “Inversion of Control” vs Wikipedia definition - why exactly DI is a form of IoC (in terms of control flow)? - Stack Overflow, 8월 17, 2025에 액세스, https://stackoverflow.com/questions/57771574/spring-definition-of-inversion-of-control-vs-wikipedia-definition-why-exactl
  22. Inversion of control vs. dependency injection in modern applications - Dev Learning Daily, 8월 17, 2025에 액세스, https://learningdaily.dev/inversion-of-control-vs-dependency-injection-in-modern-applications-982cb02e038a
  23. 파이썬 디자인 패턴과 디펜던시 인젝션 패턴 Dependency Injection Pattern - bramilch, 8월 17, 2025에 액세스, https://bramilch.github.io/posts/kr-python-design-patterns/
  24. IOC(제어의 역전) - Jay의 기술 블로그, 8월 17, 2025에 액세스, https://pjh3749.tistory.com/14
  25. [DI] DI에서 생성자 주입과 setter 주입 중 더 선호되는 방식, 8월 17, 2025에 액세스, https://lifework-archive-reservoir.tistory.com/m/206
  26. What’s the difference between the Dependency Injection and Service Locator patterns?, 8월 17, 2025에 액세스, https://stackoverflow.com/questions/1557781/whats-the-difference-between-the-dependency-injection-and-service-locator-patte
  27. [Spring] DI(의존성 주입)의 3가지 유형 - velog, 8월 17, 2025에 액세스, https://velog.io/@fastdodge7/Spring-DI%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%A3%BC%EC%9E%85%EC%9D%98-3%EA%B0%80%EC%A7%80-%EC%9C%A0%ED%98%95
  28. [Spring] 의존성 주입(DI) 시 생성자 주입(Constructor Injection)을 사용해야하는 이유, 8월 17, 2025에 액세스, https://dev-jwblog.tistory.com/118
  29. [Spring] 생성자 주입 VS 필드 주입 VS Setter 주입: 당신의 선택은?, 8월 17, 2025에 액세스, https://kdong0712.tistory.com/23
  30. [Spring] 의존성 주입 - 세터 주입, 생성자 주입방식과 비교 - 러닝개발자의 기술블로그, 8월 17, 2025에 액세스, https://muscleking3426.tistory.com/entry/Spring-%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%A3%BC%EC%9E%85-%EC%84%B8%ED%84%B0-%EC%A3%BC%EC%9E%85-%EC%83%9D%EC%84%B1%EC%9E%90-%EC%A3%BC%EC%9E%85%EB%B0%A9%EC%8B%9D%EA%B3%BC-%EB%B9%84%EA%B5%90
  31. Dependency Injection vs. Service Locator Baeldung on Computer Science, 8월 17, 2025에 액세스, https://www.baeldung.com/cs/dependency-injection-vs-service-locator
  32. Service Locator vs Dependency Injection by Nay Lin Aung - Medium, 8월 17, 2025에 액세스, https://medium.com/@naylinaung/service-locator-vs-dependency-injection-5e7e6427111d
  33. Dependency Injection vs Service Locator by Igor Vorobiov - Medium, 8월 17, 2025에 액세스, https://medium.com/@ivorobioff/dependency-injection-vs-service-locator-2bb8484c2e20
  34. What’s the difference between using dependency injection with a container and using a service locator? - Software Engineering Stack Exchange, 8월 17, 2025에 액세스, https://softwareengineering.stackexchange.com/questions/390755/whats-the-difference-between-using-dependency-injection-with-a-container-and-us
  35. [Android] Koin의 Service Locator 패턴 - 태크민의 우당탕탕 개발 블로그 - 티스토리, 8월 17, 2025에 액세스, https://jtm0609.tistory.com/305
  36. DI 라이브러리 “Koin” 은 DI가 맞을까?. Dependency Injection Pattern 과 Service… - kimji1, 8월 17, 2025에 액세스, https://dev-kimji1.medium.com/di-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-koin-%EC%9D%80-di%EA%B0%80-%EB%A7%9E%EC%9D%84%EA%B9%8C-66f974fead4f
  37. NPC 생성 (aka. Service Locator Pattern) - Daniel’s Dev Record, 8월 17, 2025에 액세스, https://jhoon8903.github.io/unity/2023/11/27/2-NPC.html
  38. Spring - IoC Container - GeeksforGeeks, 8월 17, 2025에 액세스, https://www.geeksforgeeks.org/advance-java/spring-ioc-container/
    1. The IoC container - Spring, 8월 17, 2025에 액세스, https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/beans.html
  39. How does ApplicationContext work internally in Spring Boot? by Axel García - Medium, 8월 17, 2025에 액세스, https://medium.com/@axel.garcia/how-does-applicationcontext-work-internally-in-spring-boot-d8826b549ab
  40. Spring - IoC Container (With Examples) - Simplilearn.com, 8월 17, 2025에 액세스, https://www.simplilearn.com/tutorials/spring-tutorial/spring-ioc-container
  41. Spring IoC, Spring Bean Example Tutorial - DigitalOcean, 8월 17, 2025에 액세스, https://www.digitalocean.com/community/tutorials/spring-ioc-bean-example-tutorial
  42. How is Spring IoC container able to create new Objects? Or does Spring IoC container work internally? - Stack Overflow, 8월 17, 2025에 액세스, https://stackoverflow.com/questions/18940232/how-is-spring-ioc-container-able-to-create-new-objects-or-does-spring-ioc-conta
  43. Dependency injection in ASP.NET Core Microsoft Learn, 8월 17, 2025에 액세스, https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-9.0
  44. Dependency injection - .NET Microsoft Learn, 8월 17, 2025에 액세스, https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection
  45. Asp.Net Core Dependency Injection and Service Lifetimes - PEAKUP TEKNOLOJİ A.Ş., 8월 17, 2025에 액세스, https://peakup.org/blog/asp-net-core-dependency-injection-and-service-lifetimes/
  46. Dependency Injection life cycles: Singleton, Scoped, and Transient by Ercan Erdoğan, 8월 17, 2025에 액세스, https://ercanerdogan.medium.com/types-of-dependency-injection-singleton-scoped-and-transient-8d42dab4a122
  47. Dependency Injection Lifetime: Transient, Singleton & Scoped - Tektutorialshub, 8월 17, 2025에 액세스, https://www.tektutorialshub.com/asp-net-core/asp-net-core-dependency-injection-lifetime/
  48. Understanding Dependency Injection in .NET Core - Auth0, 8월 17, 2025에 액세스, https://auth0.com/blog/dependency-injection-in-dotnet-core/
  49. Introduction to Dependency Injection In FastAPI - YouTube, 8월 17, 2025에 액세스, https://www.youtube.com/watch?v=Tyhtp1Ou_Pk
  50. Dependencies - FastAPI, 8월 17, 2025에 액세스, https://fastapi.tiangolo.com/tutorial/dependencies/
  51. dependency source specification in FastAPI’s Dependency Injection system #3230 - GitHub, 8월 17, 2025에 액세스, https://github.com/tiangolo/fastapi/discussions/3230
  52. Dependencies - Depends() and Security() - FastAPI, 8월 17, 2025에 액세스, https://fastapi.tiangolo.com/reference/dependencies/
  53. Understanding FastAPI’s Built-In Dependency Injection - Developer Service Blog, 8월 17, 2025에 액세스, https://developer-service.blog/understading-fastapis-built-in-dependency-injection/
  54. Introduction to FastAPI: A Deep Dive into Dependency Injection by Frederic Juppont, 8월 17, 2025에 액세스, https://medium.com/@frederic.juppont/introduction-to-fastapi-a-deep-dive-into-dependency-injection-feb356e82df4
  55. FastAPI Dependency Injection: 21 Examples Using Depends() with AI Answers, 8월 17, 2025에 액세스, https://lexxai.blogspot.com/2024/10/fastapi-dependency-injection-21.html
  56. Dependencies with yield - FastAPI, 8월 17, 2025에 액세스, https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/
  57. Spring AOP vs Spring IOC - GeeksforGeeks, 8월 17, 2025에 액세스, https://www.geeksforgeeks.org/springboot/spring-aop-vs-spring-ioc/
  58. Difference between Spring IOC and Spring AOP - Stack Overflow, 8월 17, 2025에 액세스, https://stackoverflow.com/questions/15675331/difference-between-spring-ioc-and-spring-aop
  59. Understanding Spring Framework: Core Philosophy, IoC/DI, and AOP - Medium, 8월 17, 2025에 액세스, https://medium.com/@kouta9369/understanding-spring-framework-core-philosophy-ioc-di-and-aop-4d1080397610
  60. AOP Principle and Application of IOC-golang - Alibaba Cloud Community, 8월 17, 2025에 액세스, https://www.alibabacloud.com/blog/aop-principle-and-application-of-ioc-golang_599796
  61. What is the relationship of IoC and AOP? - Stack Overflow, 8월 17, 2025에 액세스, https://stackoverflow.com/questions/57814402/what-is-the-relationship-of-ioc-and-aop
  62. Mastering Dependency Injection in Spring Boot Microservices - DevOps.dev, 8월 17, 2025에 액세스, https://blog.devops.dev/mastering-dependency-injection-in-spring-boot-microservices-c148ee87dac9
  63. What are the benefits and challenges of using dependency injection in .NET - Medium, 8월 17, 2025에 액세스, https://medium.com/predict/what-are-the-benefits-and-challenges-of-using-dependency-injection-in-net-d29444903420