Programming/SpringBoot

Spring DI / IoC

MJHmong 2023. 2. 27. 21:20

 

의존성 주입 ( DI / Dependency Injection )

 

DI ( Dependency Injection ) 란 스프링의 핵심 기능으로써 객체를 직접 생성하지 않고, 외부에서 생성한 객체를 주입해주는 방식이다.

 

IoC ( Inversion Of Control ) 이란 직역하면 "제어의 역전" 이라는 의미로, 스프링에서는 객체를 개발자가 아닌 스프링 컨테이너를 통해 관리한다.

 

DI / IoC 를 통해 객체 간 결합도를 낮추고 유연성을 높힐 수 있다.

 

바로 예제로 알아보자.

 

 

Class Diagram

위와 같은 구조에서 아래 테스트 코드를 기반으로 DI /IoC 의 유연성을 느껴보자

 

아래 코드에서 사용하는 showDbmsName() 메서드는 각 DbmsService의 name을 출력하는 메소드이다.

package springboot.diioc.sample;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import springboot.diioc.sample.service.DbmsService;

@SpringBootTest
class SampleApplicationTests {

	@Autowired
	DbmsService dbmsService;

	@Test
	void showNameTest() {
		dbmsService.showDbmsName();
	}

}

위 showNameTest 코드를 통해 어떤 메소드가 호출될까 ?

 

정답은 DbmsService를 구현한 ADbmsService 혹은 BDbmsService 클래스 중 Spring Container에 등록된 객체의 showDbmsName() 메서드가 호출된다.

 

만약 ADbmsService의 showDbmsName() 메서드가 호출되었다면, 아래와 같이 코드를 확인할 수 있다.

// AdbmsService
package springboot.diioc.sample.service.impl;

import org.springframework.stereotype.Service;
import springboot.diioc.sample.service.DbmsService;


@Service // Spring Container에 등록
public class ADbmsService implements DbmsService {
    private String name = "ADbmsService";
    @Override
    public void showDbmsName() {
        System.out.println(name);
    }
}


// BDbmsService
package springboot.diioc.sample.service.impl;

import springboot.diioc.sample.service.DbmsService;

public class BDbmsService implements DbmsService {

    private String name = "BDbmsService";

    @Override
    public void showDbmsName() {
        System.out.println(name);
    }
}

만약 반대로 BDbmsService의 showDbmsName() 메소드를 호출하고 싶은 경우 다음과 같이 @Service 어노테이션을 BDbmsService로 수정하면 된다.

 

// AdbmsService
package springboot.diioc.sample.service.impl;

import org.springframework.stereotype.Service;
import springboot.diioc.sample.service.DbmsService;



public class ADbmsService implements DbmsService {
    private String name = "ADbmsService";
    @Override
    public void showDbmsName() {
        System.out.println(name);
    }
}


// BDbmsService
package springboot.diioc.sample.service.impl;

import springboot.diioc.sample.service.DbmsService;

@Service // Spring Container에 등록
public class BDbmsService implements DbmsService {

    private String name = "BDbmsService";

    @Override
    public void showDbmsName() {
        System.out.println(name);
    }
}

 

즉 Spring의 의존성 주입(DI) / 제어의 역전 ( IoC )를 통해 실제 작동하는 코드의 변경 없이 실제 의존하는 객체를 변경할 수 있으며, 이를 통해 코드의 결합도를 낮추며 동시에 유연성을 높힐 수 있다.