카테고리 없음

스프링 프레임워크 "다양한 빈 등록 방법"

KayEsQuo 2025. 7. 4. 07:38

 

개요

이번 글에서는 김영한 스프링 핵심원리의 다음 강의에 대한글을 작성하려합니다.  "다양한 설정 형식 지원 - 자바 코드, XML"

 

입사 초기  스프링 기반 시스템을 분석해야 할 일이 있었는데, 톰캣이 처음 실행될 때 어떤 설정을 참고하고, 스프링이 어떻게 초기화되는지가 가장 궁금했었습니다. 이를 분석하고자 설정파일을 찾아봤지만, 다양한 .xml, .class 파일들이 설정에 사용되는 모습을 보면서 혼란스러웠습니다.

 

 

 

그러던 중 강의 수강하며 스프링은 단일 방식이 아닌, 다양한 설정 형식을 유연하게 지원한다는 사실을 알게 되었고, 특히 아래 그림처럼 ApplicationContext가 어떤 설정 파일을 읽어들이는지에 따라 컨테이너가 달라진다는 점이 흥미로웠습니다.

 

BeanFactory를 기반으로 다양한 ApplicationContext 구현체가 존재하며, 자바 클래스, XML, 기타 포맷을 통해 설정 정보를 읽어들인다.

이 글에서는 스프링 컨테이너가 설정 정보를 어떻게 인식하는지, 그리고 자바 기반 설정과 XML 설정 방식에 대해 간단하게 정리해보려고 합니다. 본문에서는 class파일과 .xml파일을 중심으로 다룹니다.

 

 

본론

 

 

A. Class 설정 파일 등록

 

1. 자바 설정 클래스 (AppConfig.class)

@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.class에 정의된 메서드들이 스프링 컨테이너 내에 실제 빈으로 등록됩니다.


✅ 2. 컨테이너에 등록된 모든 빈 출력

다음은 AnnotationConfigApplicationContext를 사용하여 자바 설정 클래스를 기반으로 컨테이너를 생성하고, 등록된 모든 빈을 출력하는 코드입니다.

class ApplicationContextInfoTest {

    AnnotationConfigApplicationContext ac =
        new AnnotationConfigApplicationContext(AppConfig.class);

    @Test
    @DisplayName("모든 빈 출력하기")
    void findAllBean() {
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            Object bean = ac.getBean(beanDefinitionName);
            System.out.println("name = " + beanDefinitionName + " object = " + bean);
        }
    }
}

 


✅ 3. 실행 결과 (출력 로그 예시)

name = org.springframework.context.annotation.internalConfigurationAnnotationProcessor object = ...
name = org.springframework.context.annotation.internalAutowiredAnnotationProcessor object = ...
name = org.springframework.context.annotation.internalRequiredAnnotationProcessor object = ...
name = org.springframework.context.annotation.internalCommonAnnotationProcessor object = ...
name = appConfig object = hello.core.AppConfig$$EnhancerBySpringCGLIB
name = memberService object = hello.core.member.MemberServiceImpl@8f4ea7c
name = orderService object = hello.core.order.OrderServiceImpl@63a65a25
name = memberRepository object = hello.core.member.MemoryMemberRepository@37052337
name = discountPolicy object = hello.core.discount.RateDiscountPolicy@2f666ebb

위 결과에서 볼 수 있듯, AppConfig.class에서 등록한 빈들도 모두 컨테이너에 등록되어 있는 것을 확인할 수 있습니다.

 

 

 

 

B. xml 설정 파일 등록

1. XML 설정 파일 (appConfig.xml)

먼저 resources 폴더에 appConfig.xml 파일을 생성하고 다음과 같이 빈을 등록합니다:

<bean id="memberService" class="hello.core.member.MemberServiceImpl">
    <constructor-arg name="memberRepository" ref="memberRepository"/>
</bean>

<bean id="memberRepository" class="hello.core.member.MemoryMemberRepository"/>

<bean id="orderService" class="hello.core.order.OrderServiceImpl">
    <constructor-arg name="memberRepository" ref="memberRepository"/>
    <constructor-arg name="discountPolicy" ref="discountPolicy"/>
</bean>

<bean id="discountPolicy" class="hello.core.discount.RateDiscountPolicy"/>

2. 테스트 코드에서 컨테이너 생성 및 빈 조회

이제 GenericXmlApplicationContext를 사용해 XML 설정 파일을 읽고, 등록된 빈을 조회합니다.

java
@Test
void xmlAppContext() {
    ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
    MemberService memberService = ac.getBean("memberService", MemberService.class);
    assertThat(memberService).isInstanceOf(MemberService.class);
}​
 
 

위 코드에서 보듯, GenericXmlApplicationContext는 XML 설정 파일을 기반으로 컨테이너를 초기화합니다.
그 후 getBean() 메서드를 통해 필요한 빈을 가져올 수 있습니다.


3. 실행 결과 로그

실행 시 콘솔에는 다음과 같이 각 빈이 생성되는 로그가 출력됩니다.

Loaded 4 bean definitions from class path resource [appConfig.xml]
Creating shared instance of singleton bean 'memberService'
Creating shared instance of singleton bean 'memberRepository'
Creating shared instance of singleton bean 'orderService'
Creating shared instance of singleton bean 'discountPolicy'

스프링이 appConfig.xml에서 정의된 총 4개의 빈을 모두 로딩하고, 싱글톤으로 등록한 것을 확인할 수 있습니다.

 

 

결론

 

이번 글에서는 스프링 컨테이너가 설정 정보를 읽어들이는 방식에 대해 두 가지 관점에서 정리해보았습니다.

  1. 자바 클래스 기반 설정
    @Configuration과 @Bean을 활용하여 코드로 직접 설정을 정의하고, AnnotationConfigApplicationContext를 통해 컨테이너를 구성
  2. XML 기반 설정
    appConfig.xml 파일을 작성하고, GenericXmlApplicationContext를 통해 설정 정보를 읽어 빈을 등록

두 방식 모두 컨테이너가 설정 파일의 정보를 기반으로 내부에 Bean 객체를 등록하고 관리한다는 공통된 구조를 가지고 있습니다.
프로젝트마다 설정 방식은 다를 수 있지만, 핵심은 스프링이 설정 정보를 기반으로 빈을 등록해 컨테이너를 구성한다는 원리를 이해하는 것이었습니다.