짱아의 개발 기록장

5강. Inversion of Control 본문

반응형

Inversion of Control은 말 그대로 제어가 역전된 것을 의미한다.

일반적인 (의존에 대한) 제어권 : "내가 사용할 의존성은 내가 만든다."

1
2
3
class OwnerController{
    private OwnerRepository repository = new OnwerRepository();
}
cs

IoC(Inversion of Control) : "내가 사용할 의존성을 누군가 알아서 해주겠지.."

-> 내가 사용할 의존성의 타입(또는 인터페이스)만 맞으면 어떤거든 상관없다.

-> 그래야 내 코드 테스트 하기도 편하지...

 

1
2
3
4
5
6
7
8
class OwnerController{
    private OwnerRepository repo;
    
    public OwnerController(OwnerRepository repo){
        this.repo = repo;
    }
 
}
cs

 

생성자를 통해 외부에서 Dependency를 받아온다. (스스로 생성x)

그래서, 의존성을 만드는 일은 더 이상 OwnerController의 일이 아니다.

누군가가 밖에서 해주는 것이다.(->Dependency Injection)

결국 제어권이 역전된 것을 말한다.

 

Project코드로 살펴보기

관련 코드1(OwnerController.java)
관련 코드2(OwnerController.java)

OwnerController.java파일에서는 다음과 같이 IoC가 일어나고 있다.

OwnerController생성자(인스턴스)는 OwnerRepository없이는 실행되지 않고

OwnerRepository를 통해서 owners(레퍼지토리)가 만들어지기 때문에(선언만 해놓은...)

그 뒤에서 사용되는 수많은 this.owners.save(...)와 같은 코드가 NullPtr exception없이 실행될 수 있는 것이다!

 

관련 코드3(OwnerControllerTests.java)

관련코드3를 보면, @MockBean annotation은 생성된 객체를 Spring Container에서 bean이라는 이름으로 관리되도록 해준다.

따라서, 관련 코드1에서와 같이 OwnerController에 의존성을 주입할때 Spring에서 OwnerRepository, VisitRepository Type에 해당되는 객체(bean)을 찾아서 주입시켜준다. (=> 정확히, 말하자면 Spring의 IoC컨테이너에서 의존성 주입을 해준다.)

 

여기서 잠깐! @MockBean의 구체적 사용 목적은?

일반적으로, Application의 main문 혹은 .jar파일을 Run함으로써 프로젝트를 실행시키면

당연히 API로 접근하게 되고 front controller역할을 하는 Dispatcher Servlet이 관련 로직을 처리해줄 controller에게 위임하게 된다.

하지만, 간단하게 unit단위로 test를 할 때에는 이러한 역할을 해주는 것이 없기 때문에,,,,

test할때는 xml파일을 돌릴 수없기 때문에? 혹은 unit단위로 test를 하기 때문에 필요한 객체만 bean으로 등록하기 위해? (이건...잘 모르겠다...ㅜ)

@MockBean으로 Spring Container에서 객체를 bean으로 관리하도록 한다.(즉, bean객체 생성)

 

@MockBean 어노테이션을 사용해서 이름 그대로 Mock 객체를 빈으로써 등록할 수 있다. 그렇기 때문에 만일 @MockBean으로 선언된 빈을 주입받는다면(@Autowired 같은 어노테이션 등을 통해서) Spring의 ApplicationContext는 Mock 객체를 주입해준다.

 

그러면! bean을 등록하는 방법은?

1) xml설정파일에 직접 등록 (프로젝트 run할때 돌아간다)

2) @MockBean 어노테이션 이용 (일반적으로, test할때 사용)

3) @Bean 어노테이션 이용

등등 여러가지 방법이 있다!

그러면! DI(Dependency Injection)을 하는 방법은?

1) Constructor Injection(✅권고)

생성자를 통한 주입

2) Method(setter) Injection

setter를 통한 주입

3) Field Injection

Field를 통한 주입(대표적으로, @Autowired 어노테이션으로 빈을 주입한다.)

반응형
Comments