IOC/DI

기록하는 용도·2022년 11월 17일
0

IOC/DI

IOC (Inversion of Control) : 제어의 역전
DI (Dependency Injection) : 의존 관계 주입
"컴포넌트를 구성하는 인스턴스의 생성과 의존 관계 연결처리를 IOC 컨테이너에게 위임"
OO Design Principles
-Loose coupling and high cohesion

IOC

Inversion Of Control 제어의 역행, 제어의 반전, 역제어
소프트웨어 디자인 패턴으로 컴포넌트를 구성하는 인스턴스 생성과 의존관계 연결 처리를 IOC Container에 위임
IOC Container 는 Singleton 방식으로 Bean 을 생성해 관리한다.

  • Singleton Design Pattern : 시스템 상에서 단 하나의 인스턴스만 생성해 공유해 사용하고자하는 설계 패턴

DI

Dependency Injection 의존성 주입 필요로 하는 의존성(component or bean..)을 주입(injection)을 통해 확보
즉 IOC를 DI 기법을 통해 실현한다.

기존 제어 방식 - 일반적인 의존 관계



DI 적용 제어 방식 - IOC 컨테이너 환경의 의존 관계



IOC/DI 특징

  1. 인스턴스의 생명 주기 제어
  2. Bean Scope관리(Singleton이 기본)
  3. 컴포넌트간의 결합도를 낮춤
  4. 단위 테스트 용이
  5. AOP 적용하여 공통 기능을 제공




Spring과 소통하기 위해서는 설정이 필요하다.
설정은 xml, annotation, java 스타일이 있다.
xml보다는 annotation이나 java를 더 많이 쓰는 추세이다.
DAO, Controller, VO 등을 business object라고 한다.

Spring Bean Life Cycle


application 시작 -> container 시작 -> bean 생성과 DI 주입 -> init() 초기화 메소드 실행 -> component에서 만들었던 service() 동작 -> destroy()

Bean 설정 방법

XML 기반 설정 방식

<bean id=”” class=””> 으로 bean 생성
<constructor-arg> or <property> 요소를 사용해 의존성주입

Annotation 기반 설정 방식

@Component 계열 어노테이션이 명시된 클래스를
Component-Scan해서 IOC 컨테이너에 bean으로 자동 등록

Java 기반 설정 방식

@Configuration 을 자바 클래스에 명시하여 설정을 하고
@Bean 을 사용해 bean 을 정의

XML + Annotation 또는 Java class + Annotation 의 조합으로 주로 설정한다.




Hammer.java

package model;
// 현 시스템의 주요 컴포넌트 or bean(독립적 기능 단위를 갖는 주요한 도구)
public class Hammer {
	public void work() {
		System.out.println("망치 도구로 일하다.");
	}
}

TestWorker.java

package test;

public class TestWorker {
	public static void main(String[] args) {
	
		Hammer hammer = new Hammer();
		hammer.work();				
	}
}

만약 Hammer에서 Spade로 도구를 바꾼다면?

Spade.java

package model;
/*
* 		시스템에서 사용하는 주요 컴포넌트 or bean
*/
public class Spade {
	public void work() {
		System.out.println("삽 도구로 일하다.");
	}
}
package test;

import model.Poclain;
import model.Spade;

public class TestWorker {
	public static void main(String[] args) {
		/*
		Hammer hammer = new Hammer();
		hammer.work();
		*/ 
		
		//도구를 망치(Hammer)에서 삽(Spade)으로 변경해야 한다면 아래와 같이 작성한다.
		Spade spade = new Spade();
		spade.work();
	}
}

위와 같이 도구(컴포넌트 or bean)가 변경이 될 때 그를 사용하는 측의 코드 또한 함께 변경되어야 하는 구조
-> IOC를 적용하지않은 기존 제어 방식 -> 결합도가 높은 상태로 볼 수 있다.

IOC 적용 단계

  1. 대상 컴포넌트 (Bean)를 계층구조화한다. (캡슐화한다.)
  2. Hammer와 Spade와 같은 도구를 Tool이라는 인터페이스로 추상화해서 관리한다.
  3. Spring IOC 설정을 명시한다. (xml or annotation or java config)
    4.Spring IOC Container를 실행해서 프로그램을 구동한다.

Tool.java

package model;

public interface Tool {
	public void work(); // 지금은 해머, 삽이지만 더 늘어난다.
}

Hammer.java

package model;
// 현 시스템의 주요 컴포넌트 or bean(독립적 기능 단위를 갖는 주요한 도구)
public class Hammer implements Tool{
	public void work() {
		System.out.println("망치 도구로 일하다.");
	}
}

Spade.java

package model;
/*
* 		시스템에서 사용하는 주요 컴포넌트 or bean
*/
public class Spade implements Tool{
	public void work() {
		System.out.println("삽 도구로 일하다.");
	}
}

ioc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="tool" class="model.Spade"></bean>
</beans>

Bean설정 방식 중 XML 기반 설정 방식으로 의존성 주입 대상을 명시한다.

TestWorkerIOC2.java

public class TestWorker2IOC {
	public static void main(String[] args) {
		// Spring IOC Container : spring xml 설정 파일을 스프링 IOC Container 시작시점에 로드한다.
		ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("ioc.xml");
		Tool tool=(Tool) ctx.getBean("tool"); 
		//bean id를 이용해 IOC Container에서 생성한 bean을 받아온다.
		//위의 getBean(bean id)는 DL 즉 Dependency Lookup 의존성 검색이다.
		// IOC를 적용했으므로 기존 제어방식과는 다르게 설정 변경만으로 도구(Bean)를 변경할 수 있다.
		//즉 소스코드에 별도의 수정은 필요없다.
		//제공하는 측과 사용하는 측의 결합도가 낮아진다. -> 유지보수성 향상
		tool.work();
		System.out.println(ctx.getBean("tool"));
		System.out.println(ctx.getBean("tool"));
		System.out.println(ctx.getBean("tool")); //여러번 getBean을 해도 동일한 객체의 주소값이 반환
		//Spring IOC Container는 Singleton 방식으로 bean을 운용한다.
		ctx.close();
	}
}

삽 도구로 일하다.
model.Spade@5e5d171f
model.Spade@5e5d171f
model.Spade@5e5d171f
getBean 여러 번으로 spring의 IOC Container는 기본적으로 싱글톤이 적용된다. 그러므로 동일한 주소가 출력된다.

싱글톤 패턴?

 시스템 상에서 단 하나의 인스턴스만 만들어서 공유해 사용하기 위한 디자인 패턴 
동일한 용도의 객체를 수만번 만들지않고 한번만 만들어서 자원을 효과적으로 사용할 수 있다.
ClassPathXmlApplicationContext ctx;

스프링으로 구성되어있는 자바 어플리케이션의 환경(context)이다.

객체의 역할도 하고, Lifecycle 역할도 하고, 스프링의 컨테이너 역할을 한다고 볼 수 있다.

아주 초기에는 xml로 설치했으므로 ioc.xml 설정 파일을 이용했다.

Tool interface를 생성하고, implements tool로 1단계인 계층구조를 한것이다.

<bean id="tool" class="model.Hammer"></bean>

2단계인 IOC 설정을 명시한것이다.

기존 제어 방식

이처럼 기존 제어방식일때 일꾼들이 한명이 아니라 수백 수천명인 상황에서 시스템의 요구사항이 바뀐다면(망치에서 삽으로 삽에서 포크레인으로 도구의 변화가 생긴다면) 이를 사용하는 다른 모듈 또는 다른 컴포넌트에서는 변화가 생길 때마다 다 바뀌어야한다. 결국 결합도가 높은것이다.

ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("ioc.xml");

3단계 Spring IOC Container를 실행해서 프로그램을 구동한다.

IOC/DI 제어 방식


일꾼이 몇명이든 상관없이 고정 인터페이스로 work()만 호출하면 DI로 인해 가져올 수 있다.

0개의 댓글

관련 채용 정보