Spring 프레임워크에서 Bean을 조립하는 방법은 크게 세 가지가 있다: 애노테이션 기반 자동 구성, JavaConfig 구성, XML 구성. 이 중 JavaConfig는 XML 구성完全可以 대체할 수 있다.
구성 전략 권장 사항
애노테이션 기반 구성과 JavaConfig를 결합하여 사용하는 것이 바람직하다. 구체적인 원칙은 다음과 같다:
- 전역 구성은 JavaConfig 사용 (데이터베이스 연결, MVC 구성 등)
- 업무 Bean은 애노테이션 활용 (@Controller, @Service, @Repository, @Component, @Autowired, @ComponentScan)
실제 동작하는 Maven 프로젝트로 테스트해보자. Eclipse에서 Maven Java 프로젝트를 생성하고 Spring 의존성을 추가해야 한다.
핵심 원리
Spring은 두 가지 메커니즘으로 Bean 자동 조립을 수행한다:
- 컴포넌트 스캔: 애플리케이션 컨텍스트에서 생성된 Bean을 자동 탐지
- 자동 의존성 주입: Bean 간의 의존 관계를 자동으로 해결
1. 컴포넌트 스캔 — Spring이 인식할 수 있는 Bean 생성
@Component, @Service, @Repository, @Controller 중 하나를 사용하여 클래스를 Bean으로 등록할 수 있다. 이 애노테이션들은 해당 클래스가 컴포넌트 클래스임을 나타내며, Spring이 Bean을 생성하도록 지시한다.
import org.springframework.stereotype.Component;
@Component
public class MusicTrack {
private String performer = "밴드A";
private String title = "아침감기";
public void play() {
System.out.println("재생 중: " + title + " - " + performer);
}
}
2. 자동 의존성 주입 — @Autowired 활용
자동 의존성 주입은 Spring이 Bean 생성 시 해당 Bean이 필요한 다른 Bean을 자동으로 연결하는 방식이다. 예를 들어, MusicPlayer Bean이 MusicTrack Bean에 의존한다면 @Autowired를 사용하여 주입할 수 있다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MusicPlayer {
@Autowired
private MusicTrack track;
public void playMusic() {
track.play();
}
}
3. 컴포넌트 스캔 활성화 — JavaConfig 기반
컴포넌트 스캔을 활성화하는 방법은 JavaConfig와 XML 두 가지가 있다.
@Configuration이 적용된 클래스는 구성 파일 역할을 한다. @ComponentScan은 지정된 패키지 내에서 @Component, @Service, @Repository, @Controller 애노테이션이 적용된 클래스를 모두 Bean으로 등록한다.
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class PlayerConfig {
}
XML 기반 설정은 생략한다.
4. 자동 조립 테스트
SpringJUnit4ClassRunner를 사용하여 테스트 실행 시 자동으로 Spring 애플리케이션 컨텍스트를 생성한다. @ContextConfiguration은 구성 클래스 위치를 지정한다.
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = PlayerConfig.class)
public class MusicPlayerTest {
@Autowired
private MusicPlayer player;
@Autowired
private MusicTrack track;
@Test
public void testPlayback() {
track.play();
player.playMusic();
}
}
testPlayback 메서드를 실행하면 콘솔에 두 줄이 출력된다: "재생 중: 아침감기 - 밴드A"
5. Bean ID 지정
Spring 애플리케이션 컨텍스트의 각 Bean은 고유한 ID를 가진다. 명시하지 않으면 Spring은 클래스명의 첫 글자를 소문자로 변환하여 ID로 사용한다. @Component("id") 형태로 특정 ID를 지정할 수 있지만, 자동 주입 시 변수명에는 영향을 주지 않는다.
@Component("customTrack")
public class Album {
private String performer = "밴드A";
private String title = "저녁바람";
public void play() {
System.out.println("재생: " + title + " 연주자: " + performer);
}
}
6. 스캔 기준 패키지 설정
기본적으로 구성 클래스가 있는 패키지와 its 하위 패키지를 스캔한다. basePackages 속성을 사용하면 여러 패키지를 지정할 수 있다.
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {"com.music.player", "com.video.player"})
public class PlayerConfig {
}
또는 basePackageClasses 속성을 사용하여 특정 클래스가 속한 패키지를 기준으로도 설정 가능하다.
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackageClasses = Album.class)
public class PlayerConfig {
}
Spring은 애플리케이션 컨텍스트를 생성할 때 해당 Bean들을 인스턴스화하고 의존 관계를 주입한다. 이 과정이 자동화되어 개발자는 명시적인 구성 코드를 줄일 수 있다.