본문 바로가기
공부이야기/Spring

[Spring] Bean? DI? 이제는 친해지자!

by coderoom 2022. 9. 24.

 

"Spring"이라 했을 때 많이 나오는 키워드 중 하나는 바로 DI, 즉 의존성 주입이다.

도대체 이게 왜 Spring의 키워드일까? 그 이유는 바로 Spring이 이 DI 과정을 알아서 해 주기 때문이다.

최근에 Spring 공부를 다시 시작하게 되었는데 아주 간단하게 DI에 대해 알아보자!

 


 

먼저, DI란 뭘까?

DI (Dependency Injection): 의존성 주입

 

고객 관리 서비스를 개발할 때 고객을 관리하는 Service Class가 있으면 고객의 데이터를 다루는 Dao Class가 있을 것이다. 이 경우 아래와 같이 두 Class간의 의존성이 생기게 된다.

class MemberService {
	private MemberDao memberDao = new MemberDao();
}

MemberService memberService = new MemberService();

 

위와 같이 직접 생성하는 방식은 꽤 쉽다! 하지만 이 방법은 유지보수 관점에서 아래와 같은 어려움이 있을 수 있다.

  • MemberDao를 상속받는 CachedMemberDao를 사용하려면 각 코드를 모두 변경해 주어야 한다.

 

 

위 코드는 아래와 같이 외부에서 의존성을 주입하는 방식으로 변경할 수 있다. 이렇게 변경할 경우 CachedMemberDao를 사용하더라도 Service Class를 사용하는 곳에서만 변경하면 되며 앞서 의존 객체를 직접 생성했던 방식에 비해 변경할 코드가 한 곳으로 집중되는 것을 알 수 있다.

  • 주입 방식으로는 1) 생성자 주입 방식, 2) Setter 주입 방식이 있다.
class MemberService {
	private MemberDao memberDao;
    
    MemberService(MemberDao memberDao) {
    	this.memberDao = memberDao;
    }
}

MemberService memberService = new MemberService(new CachedMemberDao());

 

 

이러한 객체들을 Spring에서는 Bean이라 부르며 사용자가 특정 객체를 Bean으로 등록하면 이후 이 객체에 대한 생성 및 소멸에 대한 과정을 Spring Bean Container에서 대신 처리한다. 이 현상을 IoC(Inversion of Control: 제어의 역전)이라고 한다. 말 그대로 객체의 제어를 개발자가 아닌 Spring이 맡았다는 의미이다. (처음엔 이 단어가 너무 낯설고 이해가 안됐다 ㅠ)

 

 

 

아주 간단한 코드로 사용 방식을 살펴보자!

// @Configuration: 스프링 설정 클래스를 의미한다.
@Configuration
class AppCtx {
    // @Bean: Bean으로 등록할 객체를 의미한다.
    // Spring은 @Bean이 붙은 메서드에 대해 하나의 객체만 생성. 객체가 사용될 때 마다 생성 X. 
    @Bean
    public MemberDao memberDao() {
    	return new MemberDao();
    }
    
    @Bean
    public MemberService memberService() {
    	return new MemberService(memberDao());
    }
}
class Main {

    private static ApplicationContext ctx = null;
    // AnnotationConfigApplicationContext 를 사용해서 스프링 컨테이너를 생성한다.
    public static void main(String[] args) {
    	ctx = new AnnotationConfigApplicationContext(AppCtx.class);
        
        // 설정 파일(AppCtx 클래스)로부터 생성할 객체와 의존 주입 대상을 정한다.
        MemberService memberService = ctx.getBean("memberServce", MemberService.class);
    }
}

 

 

 

두 개의 config를 사용할 경우엔 어떻게 사용할까? 아래 코드로 간단하게 알아보자. 이 때 사용된 @AutoWired는 Spring Bean에 의존하는 다른 Bean을 자동으로 주입하고자 할 경우 사용된다.

@Configuration
class AppCtx1 {
    @Bean
    public MemberDao memberDao() {
    	return new MemberDao();
    }
}
@Configuration
class AppCtx2 {
    @AutoWired
    MemberDao memberDao;
}
class Main {

    private static ApplicatonContext ctx = null;
    
    public void main(String args[]) {
    	ctx = new AnnotationConfigApplicationContext(AppCtx1.class, AppCtx2.class);
    }
}

 

 

이렇게 Spring DI에 대해 알아보았다. 물론, 주입할 객체를 모두 Bean으로 등록할 필요는 없지만 보통은 등록해서 사용한다.

Spring과 좀 친해진 생각이 들었길 바라며! :)

 

 

 

 

출처

댓글