혼자 공부한 내용을 기록으로 남기고 있습니다. 만약에 내용이 틀렸을 경우에 댓글로 알려주시면 바로 수정하겠습니다! 도움이 되셨으면 댓글이나 좋아요 남겨주시면 감사하겠습니다:)
시작하기 전에, Spring 에서 의존성 주입이란 정말정말 어렵고 중요한 개념이다. 내가 이해하기에 너무나 어려웠고 수많은 레퍼런스를 공부했다.
https://mangkyu.tistory.com/150
위의 블로그에서 의존성 주입에 관해 정말 친절히 설명해주셨다. 다들 꼭 들어가서 읽어보는 것을 추천한다. 나는 위의 블로그에서 가르쳐준 걸 내가 이해한 토대로 다시 정리하는 것일 뿐 출처는 위의 블로그 임을 분명히 밝힌다.
몇개월 전, 모기업에 인턴을 지원했고 운좋게 서류와 코딩테스트를 합격해 면접을 보러 갔다. 여러 질문에는 대답을 잘했지만 ‘Spring 에서 의존성 주입에 관련해서 설명해주세요’ 라는 말을 들었을 때 입도 뻥긋하지 못했다. 분명 김영한 강사님께서 그렇게 중요하다고 한건 기억이 나는데 내가 직접 설명을 하려하니 한마디도 못하는 현실이었다.. 그렇게 면접은 광탈했다. 의존성 주입은 Spring 에서 매우 중요한 개념이다. 농구로 치면 레이업 정도의 중요성인 것 같은데 백엔드 스프링 인턴 지원자가 의존성 주입에 입도 뻥긋못했으니 당연히 광탈할만도…
이제 확실히 의존성 주입에 관련해 공부해보도록 하자.
의존성 주입이란 외부에서 두 객체 간의 관계를 결정해주는 디자인 패턴이라고 한다. 아직까지는 무슨 말인지 하나도 모르겠다. 단어 뜻부터 봐보자. ‘의존성’ 이란 한 객체가 다른 객체를 사용할 때 ‘의존성’이 있다고 한다. 예를 들어 아래 코드를 봐보자.
public class Store {
private Pencil pencil;
}
위의 코드를 보면 Store 객체가 있고, Pencil 객체가 있다. 자세히 보면, Store 객체 안에 Pencil 객체가 있고 이를 우리는 ‘Store 객체가 Pencil 객체를 사용하고 있다’ 라고 말한다. 즉 위의 정의를 다시 보면 Store 객체는 Pencil 객체에 의존성이 있다고 말할 수 있다.
아하 이제 ‘의존성’ 이라는 말은 이해가 된다. 그럼 ‘주입’은 ‘무엇을 넣어준다’ 라는 의미인데 대충 유추가 갈 것이다. ‘의존성 주입’은 두 객체 간의 관계(의존성)을 맺어주는 것을 의미한다. 이제 이해가 좀 갈 것이다.
그럼 여기서 드는 의문이 있을 것이다. ‘그래서 이게(의존성 주입) 왜 필요한건데?’ 아래 코드를 보자.
public class Store {
private Pencil pencil;
public Store() {
this.pencil = new Pencil();
}
}
위의 코드에서 달라진 점은 Store 클래스의 생성자가 생긴 것이다. 생성자를 가만 보면 new Pencil()로 결합되어 있다. 만약 가게가 연필말고 Food와 같은 다른 상품을 팔기 시작하면 어떻게 될까? Store 클래스의 생성자를 바꿔줘야하는 번거로움이 생기고 유연성이 떨어지게 된다.
이런 관계를 ‘강하게 결합되어 있다’라고 말한다. 또 다른 위 코드의 단점은 객체들 간의 관계가 아니라 클래스 간의 관계가 맺어져 있는 것이다. 올바른 객체지향적 설계라면 객체들 간에 관계가 맺어져야 한다. 객체들 간에 관계가 맺어졌다면 다른 객체의 구체 클래스(Pencil인지 Food 인지 등)를 전혀 알지 못하더라도, (해당 클래스가 인터페이스를 구현했다면) 인터페이스의 타입(Product)으로 사용할 수 있다.
결국 이는 관심이 분리되지 않았기 때문에 생긴 문제인데 스프링의 의존성 주입이 이를 해결해준다.
우선 Pencil, Food 등 여러 가지 제품을 하나로 표현하기 위해서는 Product 라는 Interface가 필요하다.
public interface Product {
}
public class Pencil implements Product {
}
이제 우리는 Store와 Pencil이 강하게 결합되어 있는 부분을 제거해주어야 한다. 이를 제거하기 위해서는 다음과 같이 외부에서 상품을 주입(Injection)받아야 한다. 그래야 Store에서 구체 클래스에 의존하지 않게 된다.
public class Store {
private Product product;
public Store(Product product) {
this.product = product;
}
}
이러한 이유로 우리는 Spring이라는 DI 컨테이너를 필요로 하는 것이다. Store에서 Product 객체를 주입하기 위해서는 애플리케이션 실행 시점에 필요한 객체(빈)를 생성해야 하며, 의존성이 있는 두 객체를 연결하기 위해 한 객체를 다른 객체로 주입시켜야 한다. 우선 1탄은 여기까지하고 2탄에서 마저하도록 하겠다.. 너무 어렵다 ㅠ