Back-End/Spring

Spring) IoC & Container

아. 이렇게 하면 될거 같은데.. 2024. 4. 15. 22:10
728x90



IoC (Inversion of Control, 제어의 역행)

IoC는 제어 흐름의 개념을 바꾸는 것을 의미한다. 일반적으로 프로그램이 자신의 제어 흐름을 관리하는 것에서 벗어나고, 외부 컴포넌트나 프레임워크에 의해 제어되도록 한다.

예를 들어, 일반적인 프로그램의 제어 흐름은 메소드 호출에 의해 이루어진다. 그러나 IoC에서는 프레임워크나 컨테이너가 애플리케이션의 실행 흐름을 관리하며, 애플리케이션 코드는 이러한 프레임워크나 컨테이너에 의해 호출되어 실행된다.

 

IoC의 구현 방법중 하나가 DI(의존성 주입) 이다

 


Container

컨테이너란 객체의 생성, 사용, 소멸에 해당하는 라이프사이클을 담당하여 관리하며 라이프 사이클을 기본으로 애플리케이션 사용에 필요한 주요 기능을 제공한다

 

Container의 기능

  • 라이프 사이클 관리
  • Dependency 객체 제공
  • Thread 관리
  • 기타 애플리케이션 실행에 필요한 환경

Container의 필요성

  • 비즈니스 로직 외에 부가적인 기능들에 대해서는 독립적으로 관리되도록 하기 위함
  • 서비스 look up 이나 Configuration에 대한 일관성을 갖기 위함
  • 서비스 객체를 사용하기 위해 각각 Factory 또는 Singleton 패턴을 직접 구현하지 않아도 됨
"서비스 Look up"은 주로 다른 컴포넌트나 객체에 대한 참조를 가져오는 과정을 가리킨다.

 


IoC Container

오브젝트의 생성과 관계설정, 사용, 제거 등의 작업을 애플리케이션 코드 대신 독립된 컨테이너가 담당한다. 이로써 컨테이너가 코드 대신 오브젝트에 대한 제어권을 가지고 있어 IoC라고 부른다.

이런 이유로 스프링 컨테이너를 IoC 컨테이너라고 부르기도 한다.

스프링에서 IoC를 담당하는 컨테이너에는 BeanFactory, ApplicationContext가 있음

 

 

BeanFactory

Bean을 등록, 생성, 조회, 반환 관리

일반적으로 BeanFactory보다는 이를 확장한 ApplicationContext를 사용

getBean() method가 정의되어 있음

ApplicationContext

Bean을 등록, 생성, 조회, 반환 관리기능은 Beanfactory와 같음

Spring의 각종 부가 서비스를 추가로 제공.

Spring이 제공하는 ApplicationContext 구현 클래스는 여러가지 종류가 있다.

 

AnnotationConfigApplicationContext, ClassPathXmlApplicationcontext, FileSystemXmlApplicationContext, WebApplicationContext, GenericApplicationContext 등등

 

bean 객체를 찾거나 가져오기 위해 사용되는 메서드 들이다

 


IoC 개념

객체 제어 방식

  • 기존에 필요한 위치에서 개발자가 필요한 객체 생성 로직을 구현하였다면 IoC를 사용하면 객체 생성을 Container에게 위임하여 처리한다.

IoC 사용에 따른 장점

  • 객체 간의 결합도를 떨어 뜨릴 수 있다.
객체 간의 결합도가 높으면 해당 클래스가 유지보수 될 때 그 클래스와 결합된 다른 클래스도 같이 유지보수 되어야 할 가능성이 높아서 유지보수 비용이 증가한다.

 


객체의 강한 결합

클래스 호출 방식

클래스 내에 선언과 구현이 모두 되어 있기 때문에 다양한 형태로 변화가 불가능

Class의 세부사항이 변경되면 다른 Class도 변경 해야 함 (의존 관계 높음)

 

 

< 강한 결합 예시 >

public class HelloWorld {
	
    public static void main(String[] args) {
    	HelloMessage hello = new HelloMessage();
    	String world = hello.helloKor("홍길동");
        
        System.out.println(world);
	}
}

public class HelloMessage {
	
    public static helloKor(String str){
    	
        return "안녕하세요, " + str + "!";
    }
    
}

 

 

객체 간의 강한 결합을 Assembler를 통해 결합도를 낮춤

각 Service(객체)의 Life-Cycle을 관리하는 Assembler를 사용

Spring Container가 외부조립기(Assembler) 역할을 함

 

< Spring의 빈으로 등록하기 위한 XML 설정 파일 >

<!-- applicationContext.xml -->
<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">

    <!-- HelloWorld 클래스를 빈으로 등록 -->
    <bean id="helloWorld" class="com.example.HelloWorld"/>

    <!-- HelloMessage 클래스를 빈으로 등록 -->
    <bean id="helloMessage" class="com.example.HelloMessage"/>
</beans>

 

< 자바 코드에서 의존성 주입 ( DI ) >

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        // XML 설정 파일을 사용하여 ApplicationContext 생성
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        // HelloWorld 빈 객체를 가져옴
        HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");
        
        // 의존성 주입을 통해 HelloMessage 객체를 설정
        helloWorld.setHelloMessage((HelloMessage) context.getBean("helloMessage"));
        
        // 메시지 출력
        helloWorld.printMessage();
    }
}


public class HelloWorld {
    // 의존성 주입을 위한 HelloMessage 필드
    private HelloMessage helloMessage;
    
    // setter 메서드를 통해 의존성 주입
    public void setHelloMessage(HelloMessage helloMessage) {
        this.helloMessage = helloMessage;
    }
    
    public void printMessage() {
        // HelloMessage에게 작업을 위임하여 결과를 받음
        String world = helloMessage.helloKor("안녕");
        System.out.println(world);
    }
}

 


 

728x90
반응형