제어 역전(Inversion of Control, IoC)과 의존성 주입(Dependency Injection, DI)의 개념 및 차이점
1. 제어 역전(Inversion of Control, IoC)
제어 역전(IoC)은 객체의 흐름(제어)을 개발자가 직접 관리하는 것이 아니라 외부에서 제어권을 가져가고, 필요한 시점에 객체를 실행하는 디자인 패턴을 의미합니다.
쉽게 말해, 객체의 생성과 실행 흐름을 프레임워크나 컨테이너에 맡기는 방식입니다.
예제 1: 제어 역전이 없는 코드 (개발자가 직접 객체를 제어)
class Service {
run() {
console.log("Service is running!");
}
}
class Application {
constructor() {
this.service = new Service(); // 직접 객체 생성
}
start() {
this.service.run();
}
}
const app = new Application();
app.start();
- 여기서
Application
은Service
의 생성 및 실행을 직접 제어합니다. - 즉, 의존성을 직접 관리하는 방식입니다.
예제 2: 제어 역전이 적용된 코드
class Service {
run() {
console.log("Service is running!");
}
}
class Application {
constructor(service) {
this.service = service; // 외부에서 주입
}
start() {
this.service.run();
}
}
// 프레임워크나 외부 컨테이너에서 Service 인스턴스를 생성하여 주입
const serviceInstance = new Service();
const app = new Application(serviceInstance);
app.start();
Application
이Service
를 직접 생성하지 않고, 외부에서 전달(주입)받도록 변경되었습니다.- 즉, 객체의 생명 주기를 외부 컨테이너(프레임워크)가 관리할 수 있도록 설계되었습니다.
✅ 핵심 개념:
- IoC는 "흐름(제어권)을 개발자가 직접 관리하는 것이 아니라, 외부 프레임워크나 컨테이너에 맡기는 것"입니다.
- 대표적인 예: Spring, NestJS, Angular, React의 useEffect 등
2. 의존성 주입(Dependency Injection, DI)
의존성 주입(DI)은 제어 역전(IoC)의 한 가지 구현 방식으로, 객체가 필요로 하는 의존성을 직접 생성하지 않고 외부에서 주입(Injection)받는 방식입니다.
의존성 주입의 3가지 방법
- 생성자 주입(Constructor Injection)
- 메서드 주입(Method Injection)
- 속성(필드) 주입(Property Injection)
예제 3: 생성자 주입 (Constructor Injection)
class Service {
run() {
console.log("Service is running!");
}
}
class Application {
constructor(service) {
this.service = service; // 생성자를 통해 의존성 주입
}
start() {
this.service.run();
}
}
// 외부에서 의존성을 주입
const serviceInstance = new Service();
const app = new Application(serviceInstance);
app.start();
Application
이Service
를 직접 생성하지 않고, 외부에서 주입받음.Service
가 변경될 경우,Application
의 코드 변경 없이 의존성만 변경하면 적용 가능.
예제 4: 메서드 주입 (Method Injection)
class Service {
run() {
console.log("Service is running!");
}
}
class Application {
setService(service) {
this.service = service; // 메서드를 통해 주입
}
start() {
this.service.run();
}
}
const app = new Application();
const serviceInstance = new Service();
app.setService(serviceInstance); // 외부에서 주입
app.start();
setService()
메서드를 이용해 필요한 시점에 의존성을 주입 가능.- 동적으로 변경할 가능성이 있는 객체에 유용.
예제 5: 속성(필드) 주입 (Property Injection)
class Service {
run() {
console.log("Service is running!");
}
}
class Application {
service; // 속성 선언
start() {
this.service.run();
}
}
const app = new Application();
app.service = new Service(); // 외부에서 속성을 직접 할당 (주입)
app.start();
- 객체 생성 후 필드를 직접 할당하여 의존성을 주입.
- 다만, 생성자 주입보다 테스트 및 유지보수 측면에서 불리할 수 있음.
3. 제어 역전(IoC)과 의존성 주입(DI)의 차이
구분 | 제어 역전 (IoC) | 의존성 주입 (DI) |
---|---|---|
개념 | 제어권을 개발자가 아닌 프레임워크/컨테이너가 가짐 | 의존성을 직접 생성하지 않고, 외부에서 주입받음 |
역할 | 객체의 흐름(생명주기, 실행)을 외부에서 관리 | IoC의 한 가지 구현 방식 |
예제 | React의 useEffect , Spring, NestJS, Angular 등 |
생성자 주입, 메서드 주입, 속성 주입 |
결과 | 코드의 결합도를 낮추고 유지보수를 쉽게 함 | 의존성 변경 시, 최소한의 수정으로 유연하게 적용 가능 |
4. 실무에서의 활용 예시
React에서의 의존성 주입
function App({ service }) {
return <button onClick={() => service.run()}>Click</button>;
}
// 외부에서 의존성 주입
const serviceInstance = { run: () => console.log("Service Running!") };
ReactDOM.render(<App service={serviceInstance} />, document.getElementById("root"));
App
컴포넌트는service
를 직접 생성하지 않고 외부에서 props로 주입받음.
NestJS (TypeScript 기반 프레임워크)에서의 DI
@Injectable()
class Service {
run() {
console.log("Service is running!");
}
}
@Controller()
class Application {
constructor(private readonly service: Service) {} // 생성자 주입
@Get()
start() {
this.service.run();
}
}
NestJS
의 DI 컨테이너가Service
인스턴스를 자동으로 생성하여Application
에 주입.
5. 정리
✅ 제어 역전(IoC): 객체의 실행 흐름(제어권)을 개발자가 아닌 외부 프레임워크나 컨테이너가 관리하도록 하는 개념.
✅ 의존성 주입(DI): IoC를 구현하는 방법 중 하나로, 객체가 필요한 의존성을 외부에서 주입받도록 설계하는 방식.
✅ 의존성 주입이 적용되면:
- 유지보수성 증가: 의존성 변경이 쉽고, 코드 수정이 최소화됨.
- 테스트 용이: 의존성을 주입받아 Mocking(가짜 객체 생성)이 가능.
- 결합도 감소: 한 객체가 특정 클래스를 직접 생성하지 않아, 모듈 간 결합도가 낮아짐.
📌 한 줄 요약:
제어 역전(IoC) → "객체의 실행 흐름을 외부에서 제어"
의존성 주입(DI) → "필요한 객체를 직접 생성하지 않고 외부에서 주입받음"
✅ IoC는 큰 개념이고, DI는 IoC의 한 가지 구현 방식
✅ React, NestJS, Spring 등 다양한 프레임워크에서 활용
✅ 코드 결합도를 낮추고 유지보수성을 높이는 핵심 설계 원칙
'TIL' 카테고리의 다른 글
[250212 TIL] 애자일 방법론(개념정리) (0) | 2025.02.13 |
---|---|
[250211 TIL] React Synthetic Event (0) | 2025.02.11 |
[250205 TIL] 냄새나는 코드? (0) | 2025.02.05 |
[250131 TIL] Composition Event (0) | 2025.01.31 |
[250110 TIL] jest, react-testing 기본(1) (0) | 2025.01.14 |