Good Morning

Spring Framework 핵심 기능 탐구: 컴포넌트 스캔, 의존성 주입, 그리고 ApplicationContext 본문

Back-End/Spring

Spring Framework 핵심 기능 탐구: 컴포넌트 스캔, 의존성 주입, 그리고 ApplicationContext

욘쥰 2024. 8. 6. 18:26

Spring의 핵심 기능인 컴포넌트 스캔, 의존성 주입, 빈 스코프, 그리고 ApplicationContext의 사용법을 실제 코드 예제를 통해 자세히 살펴보겠습니다.

2. 주요 개념 설명

2.1 컴포넌트 스캔

컴포넌트 스캔은 Spring이 자동으로 애플리케이션의 컴포넌트를 검색하고 Spring 컨테이너에 빈으로 등록하는 메커니즘입니다.

  • @Component 어노테이션: 클래스를 Spring 빈으로 표시합니다.
  • XML 설정: <context:component-scan> 태그를 사용하여 컴포넌트 스캔을 활성화합니다.

2.2 의존성 주입 (Dependency Injection)

의존성 주입은 객체 간의 의존 관계를 외부에서 설정하는 디자인 패턴입니다.

  • @Autowired: Spring이 자동으로 의존성을 주입합니다.
  • @Value: 프로퍼티 값을 주입할 때 사용합니다.

2.3 빈 스코프

빈 스코프는 빈의 생명주기와 가시성을 정의합니다.

  • 싱글톤: 기본 스코프로, 애플리케이션 당 하나의 인스턴스만 생성됩니다.
  • 프로토타입: 요청할 때마다 새로운 인스턴스가 생성됩니다.
  • @Scope 어노테이션: 빈의 스코프를 지정합니다.

2.4 설정 관리

Spring은 다양한 방법으로 애플리케이션 설정을 관리할 수 있습니다.

  • @PropertySource: 외부 프로퍼티 파일을 로드합니다.
  • 시스템 프로퍼티와 환경 변수: 런타임 환경 설정을 활용합니다.

3. 코드 예제 분석

3.1 기본 컴포넌트 정의

@Component
class Door {}

@Component class Engine {}
@Component class TurboEngine extends Engine {}
@Component class SuperEngine extends Engine {}

@Component
@Scope("prototype")
class Door {}

 

이 코드는 여러 컴포넌트를 정의하고 있습니다. @Component 어노테이션은 이 클래스들을 Spring 빈으로 등록합니다. Door 클래스는 프로토타입 스코프로 정의되어 있어, 매번 새로운 인스턴스가 생성됩니다.

3.2 Car 클래스 분석

@Component
class Car {
    @Value("red") String color;
    @Value("100") int oil;
    @Autowired Engine engine;
    @Autowired Door[] doors;

    @Override
    public String toString() {
        return "Car{" +
                "color='" + color + '\'' +
                ", oil=" + oil +
                ", engine=" + engine +
                ", doors=" + Arrays.toString(doors) +
                '}';
    }
}


Car 클래스는 다양한 Spring 기능을 보여줍니다:

  • @Value를 사용하여 기본값을 주입합니다.
  • @Autowired를 사용하여 EngineDoor 배열을 자동으로 주입받습니다.
  • toString() 메서드로 객체의 상태를 쉽게 확인할 수 있습니다.

3.3 SysInfo 클래스 분석

@Component
@PropertySource("setting.properties")
class SysInfo {
    @Value("#{systemProperties['user.timezone'] ?: T(java.util.TimeZone).getDefault().getID()}")
    String timeZone;

    @Value("#{systemEnvironment['PWD']}")
    String currDir;

    @Value("${autosaveDir}")
    String autosaveDir;

    @Value("${autosaveInterval}")
    int autosaveInterval;

    @Value("${autosave}")
    boolean autosave;

    // toString() 메서드 생략
}


SysInfo 클래스는 다양한 소스에서 설정 값을 가져오는 방법을 보여줍니다:

  • @PropertySource로 외부 프로퍼티 파일을 로드합니다.
  • 시스템 프로퍼티, 환경 변수, 그리고 프로퍼티 파일에서 값을 가져옵니다.
  • SpEL(Spring Expression Language)을 사용하여 복잡한 표현식을 평가합니다.

4. ApplicationContext 활용

ApplicationContextTest 클래스에서 Spring의 ApplicationContext를 사용하는 다양한 방법을 볼 수 있습니다:

public class ApplicationContextTest {
    public static void main(String[] args) {
        ApplicationContext ac = new GenericXmlApplicationContext("config.xml");

        // 빈 조회
        Car car = ac.getBean("car", Car.class);
        System.out.println("car = " + car);

        // 빈 정의 정보 확인
        System.out.println("ac.getBeanDefinitionNames() = " + 
                            Arrays.toString(ac.getBeanDefinitionNames()));
        System.out.println("ac.getBeanDefinitionCount() = " + 
                            ac.getBeanDefinitionCount());

        // 빈 존재 확인
        System.out.println("ac.containsBeanDefinition(\"car\") = " + 
                            ac.containsBeanDefinition("car"));
        System.out.println("ac.containsBean(\"car\") = " + 
                            ac.containsBean("car"));

        // 빈 타입 확인
        System.out.println("ac.getType(\"car\") = " + ac.getType("car"));

        // 빈 스코프 확인
        System.out.println("ac.isSingleton(\"car\") = " + ac.isSingleton("car"));
        System.out.println("ac.isPrototype(\"door\") = " + ac.isPrototype("door"));

        // 어노테이션 검색
        System.out.println("ac.findAnnotationOnBean(\"car\", Component.class) = " + 
                            ac.findAnnotationOnBean("car", Component.class));

        // 특정 타입의 모든 빈 이름 가져오기
        System.out.println("ac.getBeanNamesForType(Engine.class) = " + 
                            Arrays.toString(ac.getBeanNamesForType(Engine.class)));
    }
}


이 코드는 ApplicationContext의 다양한 메서드를 사용하여 빈을 조회하고, 빈의 정보를 확인하는 방법을 보여줍니다.

5. 실행 결과 분석

실행 결과를 통해 우리는 다음과 같은 사실을 확인할 수 있습니다:

  1. Car 빈이 성공적으로 생성되고 의존성이 주입되었습니다.
  2. 여러 개의 빈이 정의되어 있으며, 그 중 일부는 Spring 내부 빈입니다.
  3. car와 같은 특정 빈의 존재와 타입을 확인할 수 있습니다.
  4. car는 싱글톤 스코프이고, door는 프로토타입 스코프입니다.
  5. @Component 어노테이션이 붙은 빈들을 확인할 수 있습니다.
  6. Engine 타입의 빈으로 engine, superEngine, turboEngine이 존재합니다.

6. 결론 및 정리

이 예제를 통해 우리는 Spring Framework의 강력함과 유연성을 확인할 수 있었습니다:

  1. 컴포넌트 스캔을 통한 자동 빈 등록
  2. 어노테이션 기반의 의존성 주입
  3. 다양한 소스에서의 설정 값 주입
  4. 빈 스코프 관리
  5. ApplicationContext를 통한 풍부한 빈 관리 기능