객체가 자신의 의존성(다른 객체)을 스스로 생성하지 않고, 외부에서 객체를 생성하여 전달받는 디자인 패턴이다.
일반적으로 클래스는 new 로 직접 생성하여 사용한다.
private MySQLRepository repo = new MySQLRepository();
}
하지만 이 코드의 문제 점이 있다.
직접 생성을 하면 결합도가 무지하게 올라간다.
MysqlReopsitory() 에서 -> OracleRepository() 로 바뀐다면
UserService 코드를 직접 수정해야한다.
private OracleRepository repo = new OracleRepository();
}
그럼 하나가 바뀌면 다른 로직을 담당하는 하나를 또 수정해야한다는 것이다.
해결방법은 중간에 인터페이스를 두고 역할(추상화) 를 고정하는 것이다.
즉, UserService는 “어떤 저장소를 쓸지”가 아니라 “저장소라는 역할”만 알고 있도록 만드는 것이다.
public interface Repository {
void save();
}
그리고 MySQLRepository, OracleRepository는 이 인터페이스를 구현한다.
public class MySQLRepository implements Repository { ... }
public class OracleRepository implements Repository { ... }
이제 UserService는 인터페이스만 의존한다.
class UserService {
private final Repository repo;
public UserService(Repository repo) {
this.repo = repo; // 외부에서 주입
}
}
포인트는 UserService가 구체 클래스(MySQLRepository)를 전혀 모른다는 점이다.
이제 저장소를 바꾸고 싶다면 UserService가 아니라 주입해주는 외부 코드만 바꾸면 된다.
내가 이해한 바로는
의존성 주입은 어떤 클래스가 의존성(기능을 위해 인스턴스가 필요한 다른 클래스)을 가지고 있을 때, 해당 의존성은 클래스 자체에서 생성되는 대신 외부에서 주입되어야 한다는 의미라는것이다. 이렇게 하는 이유는 간단하게 클래스가 불필요하게 다른 클래스의 구체적인 생성방식이나 내부 구현을 '알' 필요 자체가 없기 때문에 의존성주입을 하는것이다.
의존성을 new로 직접 만들기 시작하면 어떤 객체를 써야하는지, 그 객체를 어떻게 만들어야하는지, 내부 구조가 어떻게 생겼는지 이런것들을 전부 알아야해서 결합도가 높아진다.
각 클래스는 자기 역할 만하고 자기 역할만 알아야 한다.