앞서 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만 수정하면 된다.
스프링이 왜 복잡한 구조에서도 유지보수와 확장이 쉬운지를 직접 느낄 수 있는 구조였다.
다음 편에서는 스프링이 관리하는 객체들, 즉 스프링 빈의 생명주기와 싱글톤 컨테이너에 대해 깊이 다뤄볼 예정이다.
'Spring' 카테고리의 다른 글
[Spring 완전 정복 시리즈] 11편 - 스프링 빈 조회와 ApplicationContext의 역할 (1) | 2025.07.27 |
---|---|
[Spring 완전 정복 시리즈] 10편 - 스프링 컨테이너의 시작과 빈 등록 (1) | 2025.07.27 |
[Spring 완전 정복 시리즈] 8편 - AppConfig로 객체 지향 설계 완성하기 (0) | 2025.07.26 |
[Spring 완전 정복 시리즈] 7편 - DIP/OCP 위반 구조의 문제점 (1) | 2025.07.26 |
[Spring 완전 정복 시리즈] 6편 - 예제 만들기: 역할과 구현 분리의 시작 (1) | 2025.07.26 |