Spring

[Spring 완전 정복 시리즈] 9편 - 스프링으로 전환하고 의존관계 주입 자동화하기

dev-nadan 2025. 7. 26. 22:43

앞서 AppConfig를 활용해 객체 생성과 의존관계를 분리해보았다.
이번에는 이 설정 클래스를 스프링 방식으로 전환해보고,
스프링 컨테이너가 어떻게 의존관계를 자동으로 주입해주는지 확인해본다.


AppConfig를 스프링 설정으로 전환

먼저 @Configuration 과 @Bean 어노테이션을 활용해 AppConfig를 스프링 설정 클래스로 변경한다.

@Configuration
public class AppConfig {

    @Bean
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public OrderService orderService() {
        return new OrderServiceImpl(
            memberRepository(),
            discountPolicy()
        );
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

    @Bean
    public DiscountPolicy discountPolicy() {
        return new RateDiscountPolicy(); // 정률 할인 정책으로 변경
    }
}

@Bean이 붙은 메서드들은 모두 스프링 빈으로 등록된다.
이 객체들은 스프링 컨테이너가 대신 생성하고 관리한다.


스프링 컨테이너로 객체 생성 및 주입

AppConfig를 통해 등록한 빈들을 사용하려면,
ApplicationContext를 이용해 컨테이너를 생성하고 필요한 빈을 꺼내 쓰면 된다.

public class MemberApp {
    public static void main(String[] args) {
        ApplicationContext applicationContext = 
            new AnnotationConfigApplicationContext(AppConfig.class);

        MemberService memberService = 
            applicationContext.getBean("memberService", MemberService.class);

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

        Member findMember = memberService.findMember(1L);
        System.out.println("new member = " + member.getName());
        System.out.println("find member = " + findMember.getName());
    }
}

스프링 컨테이너의 역할

  • 객체 생성과 관리: 싱글톤 스코프로 한 번만 생성해서 재사용
  • 의존관계 주입(DI): 필요한 의존 객체를 자동으로 주입
  • 설정 정보 중심의 구성이 가능: AppConfig에서 구성 변경만으로 전체 흐름 제어 가능

이렇게 IoC 컨테이너는 객체 제어 권한을 직접 코드가 아닌 외부(AppConfig or 스프링)가 가지게 된다.
이를 제어의 역전(Inversion of Control, IoC) 이라고 한다.

 


좋은 객체 지향 설계를 위한 전환

이번 구조 전환을 통해 다음과 같은 장점이 생겼다:

  • SRP (단일 책임 원칙): 설정(AppConfig)과 기능(Service)의 책임을 분리
  • DIP (의존 역전 원칙): 인터페이스에만 의존하고, 실제 구현은 외부에서 주입
  • OCP (개방-폐쇄 원칙): 새로운 구현체가 생겨도 AppConfig만 수정하면 됨
  • IoC/DI 컨테이너를 통해 관리와 생성을 위임함으로써 구조를 더욱 유연하게 관리 가능

정리

스프링을 도입함으로써 객체 생성, 의존관계 관리, 설정 책임 등을 컨테이너가 대신하게 되었다.
이제 개발자는 기능 구현에만 집중하면 되고, 설정 변경이나 구현체 교체는 AppConfig만 수정하면 된다.

스프링이 왜 복잡한 구조에서도 유지보수와 확장이 쉬운지를 직접 느낄 수 있는 구조였다.

다음 편에서는 스프링이 관리하는 객체들, 즉 스프링 빈의 생명주기싱글톤 컨테이너에 대해 깊이 다뤄볼 예정이다.