SlideShare une entreprise Scribd logo
1  sur  11
DI : 의존성 주입
Java예제를 통한 이해
Class A가 제대로 작동하기 위해서 Class B의 기능이 필요하다.
쉽 게 말 하 면 , A Class 는 B Class 가 없 으 면 제 기 능 을 못 한 다 는 소 리 다 .
그림1)
A -> B : 이럴 경우 Class A는 Class B에 의존적이다라고 한다.
그림1은 A가 B에 의존하고 있음을 나타낸다. 의존하고 있다는 것은 곧 A가 B를 사용하고
있다는 것이다.
1. 의존성?
2
1. 의존성?
예제를 살펴보자.
Class Main Class Coffee Class Hot
//Main Class
public class Main {
//main()
public static void main(String[] args) {
Coffee coffee = new Coffee(); //obj
coffee.coffeeType();
}
}
//Coffee Class
public class Coffee {
private Hot hot;
// constructor
public Coffee() {
hot = new Hot();
}
public void coffeeType() {
hot.get();
}
}
//Hot Class
public class Hot {
public void get() {
System.out.println("나는 따듯한
아메리카노");
}
}
Coffee 클래스에서 Hot 클래스의 object를 생성해서 Hot Class의 get()를 호출하고 있다.
좀 더 쉽게 이야기하면, Coffee 클래스의 구현을 위해 현재 Hot 클래스의 객체가 필요한 겁니다.
만약, 여기서 Hot 클래스의 정의된 메소드가 변경이 되면 Coffee 클래스의 호출부 및 코드가 변경이
됩니다.
또는, Hot 클래스 자체가 변경이 될 경우, Coffee 클래스의 코드가 변경이 됩니다.
1. 의존성?
Class Main Class Coffee Class Hot
//Main Class
public class Main {
//main()
public static void main(String[] args) {
Coffee coffee = new Coffee(); //obj
coffee.coffeeType();
}
}
//Coffee Class
public class Coffee {
private Hot_ex hot_ex;
// constructor
public Coffee() {
hot = new Hot_ex();
}
public void coffeeType() {
hot.get2();
}
}
//Hot Class
public class Hot_ex {
public void get2() {
System.out.println(“따듯한
아메리카노");
}
}
Hot 클래스가 변경이 되어서, 수정이 된 화면입니다. Hot_ex 클래스가 변경이 되면, 또 똑같은 작업이
반복이 됩니다. 이것은 코드의 재사용성 및 유지보수 면에서 단점으로 작용 합니다.
그래서, 이러한 문제를 걷어내기 위해 interface를 통해 의존성을 걷어냅니다.
2. 의존성 주입
Class Main Class Coffee Interface Ame Class Hot Class Ice
//Main Class
public class Main {
//main()
public static void
main(String[] args) {
Coffee coffee = new
Coffee(); //obj
coffee.coffeeType();
}
}
//Coffee Class
public class Coffee {
//private Hot hot;
private Ame ame;
//interface obj
// constructor
public Coffee() {
ame = new Ice();
}
public void
coffeeType() {
//hot.get();
ame.get();
}
}
//Ame interface
public interface Ame {
public void get();
}
//Hot Class
public class Hot
implements Ame{
public void get() {
System.out.println("나
는 따듯한 아메리카노");
}
}
public class Ice
implements Ame {
public void get() {
System.out.println("나
는 차가운 아메리카노");
}
}
Interface를 통해, 의존성에 대한 문제를 해결하였다. 이렇게 되면, 기능 또는 코드 변경 시 객체생성만
수정을 하면 된다. (복잡성과 변경성에서 조금은 자유로워졌다고 생각하면 된다.) 하지만, 여전히
객체생성은 Coffee클래스에 의존하는 모습이 보인다. (어떤 구현클래스를 사용할지를 결정하는 코드가
남아있다.) 이를 해결하기 위해 객체를 매개변수로 넘겨주는 방법을 이용한다.
2. 의존성 주입
Coffee Ame
Ice Hot
Coffee가 Ice을 알고
있기 때문에 생긴
불필요한 의존관계
2. 의존성 주입
Class Main Class Coffee Interface Ame Class Hot Class Ice
//Main Class
public class Main {
//main()
public static void
main(String[] args) {
//Coffee coffee = new
Coffee(); //coffee
obj
Hot hot = new Hot();
Ice ice = new Ice();
Coffee coffee = new
Coffee(ice);
coffee.coffeeType();
}
}
//Coffee Class
public class Coffee {
//private Hot hot;
private Ame ame;
//interface obj
// constructor
public Coffee(Ame ame)
{
//ame = new Ice();
this.ame = ame;
}
public void
coffeeType() {
//hot.get();
ame.get();
}
}
//Ame interface
public interface Ame {
public void get();
}
//Hot Class
public class Hot
implements Ame{
public void get() {
System.out.println("나
는 따듯한 아메리카노");
}
}
public class Ice
implements Ame {
public void get() {
System.out.println("나
는 차가운 아메리카노");
}
}
코드를 변경하였다. 기존에 Coffee클래스에서 객체를 생성하였지만, 다른 클래스가 외부에서 주입 또는
담당을 하게 되었다.(이제 기능을 바꾸려면, Main클래스가 변해야 한다.) 이것이 바로 의존성 주입이다.
그리고, 이렇게 해당 객체를 생성할 때, 외부로 전가하는 것을 제어의 역행이라고 생각하면 된다. 역행,
역행 -> 스프링에서는 IoC컨테이너에게 의존성을 몰아줘 버린다.
2. 의존성 주입
Main Ame
Coffee를 사용 : 클라이언트
Coffee
Hot Ice
사용되는 Object : 서비스
클라이언트인 Main이 수고를 덜어줘서, Coffee 변경 없이 Hot, Ice를 사용 할 수 있다.
(생성)
초기 코드를 보면, main()는 Coffee 클래스의 오브젝트를 직접 생성하고, 만들어진 오브젝트의 메소드를
사용했다. Coffee 또한 자신이 사용할 Ame의 구현클래스를 자신이 결정하고, 필요한 시점에 생성하여
이를 사용하였다. 모든 작업을 사용하는 쪽에서 제어하는 구조였다. 하지만, 현재 구조는 모든 제어권한을
자신이 아닌 다른 대상에게 위임하였다. 이것이 제어의 역행이다.
2. 의존성 주입
Class Main Class Coffee Interface Ame Class Hot Class Ice
//Main Class
public class Main {
//main()
public static void
main(String[] args) {
//Coffee coffee = new
Coffee(); //coffee
obj
Hot hot = new Hot();
Ice ice = new Ice();
Coffee coffee = new
Coffee(ice);
coffee.coffeeType();
}
}
//Coffee Class
public class Coffee {
//private Hot hot;
private Ame ame;
//interface obj
// constructor
public Coffee(Ame ame)
{
//ame = new Ice();
this.ame = ame;
}
public void
coffeeType() {
//hot.get();
ame.get();
}
}
//Ame interface
public interface Ame {
public void get();
}
//Hot Class
public class Hot
implements Ame{
public void get() {
System.out.println("나
는 따듯한 아메리카노");
}
}
public class Ice
implements Ame {
public void get() {
System.out.println("나
는 차가운 아메리카노");
}
}
위 코드를 보면, 객체를 삽입해주는 Coffee 클래스를 사용하는 Client를 보면 여전히 new 연산자로 객체를
생성해서 넘겨주고 있다. Coffee를 사용하는 모든 곳에서 이런 일을 하기는 귀찮은 부분이 될 수도 있다.
발상의 전환점은 여기에 있다. 이러한 연관관계를 더 느슨하게 혹은 외부에서 할 수는 없을까?
2. 의존성 주입
Main AmeCoffee
Hot Ice
(생성)
Main 클래스는 이제 더 이상, Hot, Ice 클래스와는 관계가 없다. 단지, Coffee클래스를 호출을 할 뿐이다.
그러므로, Hot, Ice 클래스가 다른 클래스로 변경되어도 Main이 변경이 가해질 일이 없게 된다.
이렇듯, 스프링 DI는 기존 코드가 코드 안에서 객체의 생성과 소멸을 한다고 한다면 DI 개념 안에서는
객체를 생성, 파괴와 객체간의 의존관계를 컨테이너에 의해서 제어한다는 것이 핵심인 것이다.
Container
(Bean Factory 또는
Application Context)
(Injection)
• Bean Factory : 스프링의 IoC를 담당하는 핵심 컨테이너
• Application Context : Bean Factory를 확장한 Ioc 컨테이너
무엇이 달라요?
Bean Factory는 Bean을 관리하는 관점. Application Context는 Bean Factory의 기능 + 스프링이 제공하는 어플리케이션 기능 포함.
주로, 스프링에서 IoC 컨테이너를 사용할 때 Application Context가 Bean Factory보다 선호됨.
참조 : http://stackoverflow.com/questions/243385/beanfactory-vs-applicationcontext
마무리..
객체지향 프로그램에서의 의존관계는 하나의 Class가 다른 Class를 사용하는 관계를
이야기한다. 하지만, 의존관계에 있는 Class가 변경이 될 경우 다른 Class에 영향이 미친다.
이러한 코드들이 많아질수록 코드의 재사용성, 테스트 및 유지보수 측면에서도 악영향을
미친다.
이러한 문제와 Object의 의존관계를 느슨하게 하기 위해 DI(의존성 주입)이 등장하게 된
것이다.
그래서, DI(의존성 주입)을 사용하는 이유는 기능이 추가될때마다 코드의 변경을 최소화
시키고 유지보수 및 테스트 측면에서 효율성을 높이기 위해 사용한다.
• Coupling(결합도) ?
코드의 한 요소가 다른 것과 얼마나 강력하게 연결되어 있는지, 또한 얼마나 의존적인지 나타내는 정도.

Contenu connexe

Plus de ChangHyeon Bae

Plus de ChangHyeon Bae (13)

ES6-01
ES6-01ES6-01
ES6-01
 
javascript03
javascript03javascript03
javascript03
 
javascript02
javascript02javascript02
javascript02
 
javascript01
javascript01javascript01
javascript01
 
Java memory
Java memoryJava memory
Java memory
 
JavaScript 실행컨텍스트와 클로저
JavaScript 실행컨텍스트와 클로저JavaScript 실행컨텍스트와 클로저
JavaScript 실행컨텍스트와 클로저
 
WAS와 웹서버 간단 정리
WAS와 웹서버 간단 정리WAS와 웹서버 간단 정리
WAS와 웹서버 간단 정리
 
REST Concept
REST ConceptREST Concept
REST Concept
 
Srping data rest
Srping data restSrping data rest
Srping data rest
 
Angular 살짝 해보고 발표.
Angular 살짝 해보고 발표.Angular 살짝 해보고 발표.
Angular 살짝 해보고 발표.
 
OOP - Object Oriendted Programing
OOP - Object Oriendted ProgramingOOP - Object Oriendted Programing
OOP - Object Oriendted Programing
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven Development
 
CDN - Content Delivery Network
CDN - Content Delivery NetworkCDN - Content Delivery Network
CDN - Content Delivery Network
 

DI - Dependency Injection

  • 1. DI : 의존성 주입 Java예제를 통한 이해
  • 2. Class A가 제대로 작동하기 위해서 Class B의 기능이 필요하다. 쉽 게 말 하 면 , A Class 는 B Class 가 없 으 면 제 기 능 을 못 한 다 는 소 리 다 . 그림1) A -> B : 이럴 경우 Class A는 Class B에 의존적이다라고 한다. 그림1은 A가 B에 의존하고 있음을 나타낸다. 의존하고 있다는 것은 곧 A가 B를 사용하고 있다는 것이다. 1. 의존성? 2
  • 3. 1. 의존성? 예제를 살펴보자. Class Main Class Coffee Class Hot //Main Class public class Main { //main() public static void main(String[] args) { Coffee coffee = new Coffee(); //obj coffee.coffeeType(); } } //Coffee Class public class Coffee { private Hot hot; // constructor public Coffee() { hot = new Hot(); } public void coffeeType() { hot.get(); } } //Hot Class public class Hot { public void get() { System.out.println("나는 따듯한 아메리카노"); } } Coffee 클래스에서 Hot 클래스의 object를 생성해서 Hot Class의 get()를 호출하고 있다. 좀 더 쉽게 이야기하면, Coffee 클래스의 구현을 위해 현재 Hot 클래스의 객체가 필요한 겁니다. 만약, 여기서 Hot 클래스의 정의된 메소드가 변경이 되면 Coffee 클래스의 호출부 및 코드가 변경이 됩니다. 또는, Hot 클래스 자체가 변경이 될 경우, Coffee 클래스의 코드가 변경이 됩니다.
  • 4. 1. 의존성? Class Main Class Coffee Class Hot //Main Class public class Main { //main() public static void main(String[] args) { Coffee coffee = new Coffee(); //obj coffee.coffeeType(); } } //Coffee Class public class Coffee { private Hot_ex hot_ex; // constructor public Coffee() { hot = new Hot_ex(); } public void coffeeType() { hot.get2(); } } //Hot Class public class Hot_ex { public void get2() { System.out.println(“따듯한 아메리카노"); } } Hot 클래스가 변경이 되어서, 수정이 된 화면입니다. Hot_ex 클래스가 변경이 되면, 또 똑같은 작업이 반복이 됩니다. 이것은 코드의 재사용성 및 유지보수 면에서 단점으로 작용 합니다. 그래서, 이러한 문제를 걷어내기 위해 interface를 통해 의존성을 걷어냅니다.
  • 5. 2. 의존성 주입 Class Main Class Coffee Interface Ame Class Hot Class Ice //Main Class public class Main { //main() public static void main(String[] args) { Coffee coffee = new Coffee(); //obj coffee.coffeeType(); } } //Coffee Class public class Coffee { //private Hot hot; private Ame ame; //interface obj // constructor public Coffee() { ame = new Ice(); } public void coffeeType() { //hot.get(); ame.get(); } } //Ame interface public interface Ame { public void get(); } //Hot Class public class Hot implements Ame{ public void get() { System.out.println("나 는 따듯한 아메리카노"); } } public class Ice implements Ame { public void get() { System.out.println("나 는 차가운 아메리카노"); } } Interface를 통해, 의존성에 대한 문제를 해결하였다. 이렇게 되면, 기능 또는 코드 변경 시 객체생성만 수정을 하면 된다. (복잡성과 변경성에서 조금은 자유로워졌다고 생각하면 된다.) 하지만, 여전히 객체생성은 Coffee클래스에 의존하는 모습이 보인다. (어떤 구현클래스를 사용할지를 결정하는 코드가 남아있다.) 이를 해결하기 위해 객체를 매개변수로 넘겨주는 방법을 이용한다.
  • 6. 2. 의존성 주입 Coffee Ame Ice Hot Coffee가 Ice을 알고 있기 때문에 생긴 불필요한 의존관계
  • 7. 2. 의존성 주입 Class Main Class Coffee Interface Ame Class Hot Class Ice //Main Class public class Main { //main() public static void main(String[] args) { //Coffee coffee = new Coffee(); //coffee obj Hot hot = new Hot(); Ice ice = new Ice(); Coffee coffee = new Coffee(ice); coffee.coffeeType(); } } //Coffee Class public class Coffee { //private Hot hot; private Ame ame; //interface obj // constructor public Coffee(Ame ame) { //ame = new Ice(); this.ame = ame; } public void coffeeType() { //hot.get(); ame.get(); } } //Ame interface public interface Ame { public void get(); } //Hot Class public class Hot implements Ame{ public void get() { System.out.println("나 는 따듯한 아메리카노"); } } public class Ice implements Ame { public void get() { System.out.println("나 는 차가운 아메리카노"); } } 코드를 변경하였다. 기존에 Coffee클래스에서 객체를 생성하였지만, 다른 클래스가 외부에서 주입 또는 담당을 하게 되었다.(이제 기능을 바꾸려면, Main클래스가 변해야 한다.) 이것이 바로 의존성 주입이다. 그리고, 이렇게 해당 객체를 생성할 때, 외부로 전가하는 것을 제어의 역행이라고 생각하면 된다. 역행, 역행 -> 스프링에서는 IoC컨테이너에게 의존성을 몰아줘 버린다.
  • 8. 2. 의존성 주입 Main Ame Coffee를 사용 : 클라이언트 Coffee Hot Ice 사용되는 Object : 서비스 클라이언트인 Main이 수고를 덜어줘서, Coffee 변경 없이 Hot, Ice를 사용 할 수 있다. (생성) 초기 코드를 보면, main()는 Coffee 클래스의 오브젝트를 직접 생성하고, 만들어진 오브젝트의 메소드를 사용했다. Coffee 또한 자신이 사용할 Ame의 구현클래스를 자신이 결정하고, 필요한 시점에 생성하여 이를 사용하였다. 모든 작업을 사용하는 쪽에서 제어하는 구조였다. 하지만, 현재 구조는 모든 제어권한을 자신이 아닌 다른 대상에게 위임하였다. 이것이 제어의 역행이다.
  • 9. 2. 의존성 주입 Class Main Class Coffee Interface Ame Class Hot Class Ice //Main Class public class Main { //main() public static void main(String[] args) { //Coffee coffee = new Coffee(); //coffee obj Hot hot = new Hot(); Ice ice = new Ice(); Coffee coffee = new Coffee(ice); coffee.coffeeType(); } } //Coffee Class public class Coffee { //private Hot hot; private Ame ame; //interface obj // constructor public Coffee(Ame ame) { //ame = new Ice(); this.ame = ame; } public void coffeeType() { //hot.get(); ame.get(); } } //Ame interface public interface Ame { public void get(); } //Hot Class public class Hot implements Ame{ public void get() { System.out.println("나 는 따듯한 아메리카노"); } } public class Ice implements Ame { public void get() { System.out.println("나 는 차가운 아메리카노"); } } 위 코드를 보면, 객체를 삽입해주는 Coffee 클래스를 사용하는 Client를 보면 여전히 new 연산자로 객체를 생성해서 넘겨주고 있다. Coffee를 사용하는 모든 곳에서 이런 일을 하기는 귀찮은 부분이 될 수도 있다. 발상의 전환점은 여기에 있다. 이러한 연관관계를 더 느슨하게 혹은 외부에서 할 수는 없을까?
  • 10. 2. 의존성 주입 Main AmeCoffee Hot Ice (생성) Main 클래스는 이제 더 이상, Hot, Ice 클래스와는 관계가 없다. 단지, Coffee클래스를 호출을 할 뿐이다. 그러므로, Hot, Ice 클래스가 다른 클래스로 변경되어도 Main이 변경이 가해질 일이 없게 된다. 이렇듯, 스프링 DI는 기존 코드가 코드 안에서 객체의 생성과 소멸을 한다고 한다면 DI 개념 안에서는 객체를 생성, 파괴와 객체간의 의존관계를 컨테이너에 의해서 제어한다는 것이 핵심인 것이다. Container (Bean Factory 또는 Application Context) (Injection) • Bean Factory : 스프링의 IoC를 담당하는 핵심 컨테이너 • Application Context : Bean Factory를 확장한 Ioc 컨테이너 무엇이 달라요? Bean Factory는 Bean을 관리하는 관점. Application Context는 Bean Factory의 기능 + 스프링이 제공하는 어플리케이션 기능 포함. 주로, 스프링에서 IoC 컨테이너를 사용할 때 Application Context가 Bean Factory보다 선호됨. 참조 : http://stackoverflow.com/questions/243385/beanfactory-vs-applicationcontext
  • 11. 마무리.. 객체지향 프로그램에서의 의존관계는 하나의 Class가 다른 Class를 사용하는 관계를 이야기한다. 하지만, 의존관계에 있는 Class가 변경이 될 경우 다른 Class에 영향이 미친다. 이러한 코드들이 많아질수록 코드의 재사용성, 테스트 및 유지보수 측면에서도 악영향을 미친다. 이러한 문제와 Object의 의존관계를 느슨하게 하기 위해 DI(의존성 주입)이 등장하게 된 것이다. 그래서, DI(의존성 주입)을 사용하는 이유는 기능이 추가될때마다 코드의 변경을 최소화 시키고 유지보수 및 테스트 측면에서 효율성을 높이기 위해 사용한다. • Coupling(결합도) ? 코드의 한 요소가 다른 것과 얼마나 강력하게 연결되어 있는지, 또한 얼마나 의존적인지 나타내는 정도.