카테고리 없음
DI, IOC
개발자doc
2024. 7. 1. 09:57
목차
1. DI
2. IOC
3. DI 구현
1. DI(Dependency Injection)
- 의존성 주입
- 클래스 내부에서 객체를 생성하는 것이 아닌 생성자를 통해 외부에서 객체를 주입하는 받아 생성하는 방식
기존에 클래스 내에서 다른 클래스의 객체를 사용하기 위해서는 다음과 같은 방법을 사용했을 것이다.
class A{
constructor(){}
}
class B{
constructor(){
this.a = new A();
}
}
const b = new B();
하지만 이와 같은 방식은 여러 문제를 갖고 있는데
1 ) 테스트 어려움
3 ) 코드 중복
3 ) 유연성 부족
이러한 문제를 해결하기 위해 나온 방법이 외부에서 객체를 생성하여 클래스의 생성자를 통해 의존성을 주입해주는 것이다.
class A{
constructor(){}
}
class B{
constructor(a){
this.a = a;
}
}
const a = new A();
const b = new B(a);
2. IOC(Inversion Of Control)
- 객체의 생성과 관리의 책임을 개발자가 아닌 프레임워크 또는 애플리케이션에 위임하는 디자인 원칙
기존에는 개발자가 직접 객체를 생성하여 다루는 것이였다면 DI를 통한 방법은 어떤 클래스에 객체를 넣어줄지만 정해주면 코드가 실행되면서 알아서 넣어준다. 이를 객체의 생성과 관리를 하는 주체가 뒤바뀌었다고 하여 제어의 역전이라고 한다.
왜 제어의 역전 원칙을 지키려는 것인가?
클래스의 독립성을 높여 본인의 기능에 충실하고 결합도를 낮춰 재사용과 유지보수가 용이하게 하기 위함이다.
3. DI 구현
1 ) Controller
class TestController{
contructor(service){
this.server = service;
}
// 라우터를 통해 요청과 응답 객체를 받아 응답을 진행하지만
// 해당 코드에서는 생략
async responseData(){
console.log(await this.service.get());
// 해당 로직에서 클라이언트에 조회된 데이터를 응답
}
}
module.exports = TestController;
2 ) Service
class TestService{
contructor(repository){
this.repository = repository;
}
async getService(){
return await this.repository.getRepository();
}
}
module.exports = TestService;
3 ) Repository
class TestRepository{
constructor(model){
this.model = model;
}
async getModel(){
return await this.model.getData();
}
}
module.exports = TestRepository;
4 ) Model
class TestModel{
getDate(){
// 해당 로직에서 데이터베이스를 통해 데이터 조회하여 반환
}
}
module.exports = TestModel;
5 ) DI 주입
const TestController = require("컨트롤러 경로");
const TestService = require("서비스 경로");
const TestRepository = require("레포지토리 경로");
const TestModel = require("모델 경로");
class DIContainer{
// 각 클래스에 대한 의존성을 주입하여 추가하기 위한 객체
testModules = {};
// 클래스와 의존 클래스에 대한 정보를 저장하는 메서드
register(ModuleName, ModuleClass,dependencies){
this.testModules[ModuleName] = { Module, dependencies }
}
// 의존성이 추가하여 가져오는 메서드
get(name){
const testModule = this.testModules[name]
// 인스턴스가 생성되지 않았다면 생성
if(!testModule.instance){
const dependency = this.testModules.dependencies.map(el=>this.get(el));
testModule.instance = new dependency.ModuleClass(...dependency)
}
return testModule.instance;
}
}
const container = new DIContainer();
container.register("model", TestModel,[]);
container.register("Repository", TestRepository,["model"]);
container.register("service", TestService,["Repository"]);
container.register("controller", TestController,["service"]);
module.exports = container;
6. main
const container = require("DI의 경로");
// get메서드를 통해 service클래스의 의존성이 주입된 controller의 instance를 가져온다.
const controller = container.get("controller");
// instacne를 통해 model까지 접근가능
controller.responseData();