[Spring] Spring Container

노유성·2023년 7월 12일
0
post-thumbnail

IoC(제어의 역전)

기존의 프로그램에서는 client객체가 피룡한 구체를 생성하고 연결하는 것이 당연하고 자연스러운 흐름이었다. 하지만 AppConfig가 등장한 이후에 구현 객체는 자신의 로직을 실행하는데에만 집중한다. 즉, 프로그래므이 제어 흐름에 대한 권한은 모두 AppConfig가 갖고 있는 셈이다.

예를 들어, OrderService는 MemberRepsitory interface에 의존하고 있다면 그에 대해서 어떤 구체가 들어올 지는 AppConfig가 결정한다. 이렇게 프로그래므이 제어 흐름이 직접 제어되는 것이 아니라 외부에서 관리가 되는 것을 두고 IoC, 제어의 역전이라고 한다.

의존관계 주입(DI)

의존관계는 정적인 클래스 의존 관계와, 실행 시점에 결정되는 동적인 의존관계를 분리해서 생각해야한다.

<정적인 클래스 다이어그램>

<동적인 객체 다이어그램>

App 실행 시점에 외부에서 구체를 생성해서 클라이언트에 전달해 의존 관계가 연결되는 것을 두고 의존관계 주입이라 한다. 의존관계 주입을 사용하면 클라이언트 코드를 변경하지 않고 클라이언트가 호출하는 타입의 instance를 변경할 수 있다. 또, 정적인 클래스 의존관계를 변경하지 않고 동적인 객체 인스턴스 의존관계를 변경할 수 있다.

이렇게 AppConfig처럼 객체를 생성하고 관리하며 의존관계를 연결해주는 것은 DI 컨테이너라고 한다.

Spring 전환

AppConfig

@Configuration
public class AppConfig {
    @Bean
    // 생성자를 통해서 주입한다.
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }
    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
    @Bean
    public OrderService orderService()  {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }
    @Bean
    public DiscountPolicy discountPolicy() {
        return new RateDiscountPolicy();
    }

메소드에 @Bean을, class에 @Configuration 이라는 annotatino을 붙힌다. 그러면 자연스럽게 class들은 Spring bean으로 등록이 되고 Spring에서 관리를 한다.

적용 예시

public class OrderApp {
    public static void main(String[] args) {
//        AppConfig appConfig = new AppConfig();
//        MemberService memberService = appConfig.memberService();
//        OrderService orderService = appConfig.orderService();

        ApplicationContext ac 
        	= new AnnotationConfigApplicationContext(AppConfig.class);

        MemberService memberService = ac.getBean("memberService", MemberService.class);
        OrderService orderService = ac.getBean("orderService", OrderService.class);

        Long memberId = 1L;
        Member member = new Member(memberId, "memberA", Grade.VIP);
        memberService.join(member);

        Order order = orderService.createOrder(memberId, "itemA", 10000);

        System.out.println("order = " + order.toString());
    }
}

주석 처리된 부분은 기존에 Spring 없이 DI 컨테이너를 이용한 코드이고 그 뒤부터는 Springㅇ르 이용한 코드이다. Spring을 이용할 경우에는 AppConfig class을 직접 생성해서 사용하는 것이 아니라

ApplicationContext ac
= new AnnotationConfigApplicationContext(AppConfig.class);

위와 같이 AppConfig를 등록해서 사용한다.

스프링 컨테이너는 @Configuration이 붙은 AppConfig를 설정 정보로 사용하고 @Bean이라 적힌 메소드를 모두 호출해서 반환된 객체를 컨테이너에 등록한다. Spring Bean은 메소드 명을 bean의 이름으로 사용한다. 에전에는 필요한 객체를 AppConfig에서 찾았지만 이제는 Container을 통해서 찾는다.

profile
풀스택개발자가되고싶습니다:)

0개의 댓글