IT개발및프로그래밍/웹서버프로젝트

스프링 컨텍스트에 빈 추가하는 3가지 방법: 예제와 함께 배우기

devgodmj 2024. 10. 21. 14:34

1. 스프링 컨테스트란?

스프링에서 빈(Bean)은 스프링이 직접 관리하는 객체를 의미합니다. 스프링은 컨텍스트(Context)라고 부르는 공간에서 이 객체들을 관리합니다. 즉, 애플리케이션에서 필요한 객체들을 만들고, 그 객체들이 서로 의존하는 것들을 자동으로 연결해줍니다. 이렇게 관리되는 객체들을 빈이라고 부르고, 스프링 컨텍스트가 이 빈들을 보관하고 필요한 곳에 꺼내서 사용하게 합니다.

 

쉽게 말하면, 스프링 컨텍스트는 스프링이 관리하는 객체의 저장소이고, 우리는 그 안에 새로운 객체(빈)를 추가할 수 있습니다.

 


 

2. 스프링에서 빈을 추가하는 방법

  • @Bean 애너테이션으로 빈 추가하기
  • 스테레오타입 애너테이션으로 빈 추가하기
  • 프로그래밍 방식으로 빈 추가하기
방법 장점 단점
@Bean -명시적 설정
-복잡한 로직 처리 가능
-외부 클래스 등록 가능
-추가 코드 작성 필요
-직접 객체 관리
스테레오타입 -자동 등록
-역할이 명확함
-간결한 코드
-제한된 제어
-패키지 스캔 필요
-외부 클래스 적용 불가
프로그래밍(registerBean) -동적 등록
-높은 유연성
-외부 클래스 등록 가능
-직관성부족(빈관리복잡)
-추가 코드 필요

@Bean 애너테이션으로 빈 추가하기

 

가장 기본적인 방법 중 하나는 @Bean 애너테이션을 사용하는 것입니다.

이 방법은 우리가 직접 객체를 만들고, 그 객체를 스프링에 등록할 수 있습니다.

 

1) 빈으로 등록할 객체를 만든다.

public class MyService {
    public String serve() {
        return "MyService가 동작 중입니다!";
    }
}

 

 

 

2) MyService 클래스를 스프링 컨텍스트에 빈으로 등록한다.

@Configuration
public class AppConfig {

    @Bean
    public MyService myService() {
        return new MyService(); // 이 객체가 스프링에 의해 관리됩니다.
    }
}

 

  • @Configuration: 이 클래스가 스프링 설정 파일이라는 걸 나타내는 애너테이션
  • @Bean: 이 애너테이션이 붙은 메서드는 스프링 컨텍스트에 빈으로 등록됨

 

3) 빈 사용하기

이제 MyService라는 객체는 스프링 컨텍스트에서 관리되기 때문에 다른 곳에서 바로 꺼내 쓸 수 있습니다. 

public class Application {
    public static void main(String[] args) {
        // 스프링 컨텍스트 생성
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        // MyService 빈을 컨텍스트에서 가져오기
        MyService myService = context.getBean(MyService.class);
        System.out.println(myService.serve()); // 출력: "MyService가 동작 중입니다!"
    }
}

 


스테레오타입 애너테이션으로 빈 추가하기

 

스테레오타입 애너테이션은 스프링에서 특정 클래스를 빈(bean)으로 자동 등록하기 위해 사용하는 애너테이션들을 말합니다.

이 애너테이션들은 그 클래스의 역할을 명확히 구분하고, 스프링이 해당 클래스를 자동으로 관리하는 빈으로 만들어줍니다. 

 

스프링에서 제공하는 대표적인 스테레오타입 애너테이션

 

  • @Component: 가장 기본적인 스테레오타입 애너테이션으로, 특별한 역할을 지정하지 않고 그냥 일반적인 빈을 등록할 때 사용
    즉, 스프링 컨텍스트에 자동으로 빈을 등록해주는 기본적인 애너테이션
  • @Service: 비즈니스 로직을 담당하는 클래스에 주로 사용하는 애너테이션
    이 애너테이션을 붙이면 스프링은 해당 클래스를 서비스 역할로 인식하고 빈으로 등록
  • @Repository: 데이터 접근 계층(예: 데이터베이스와의 상호작용)을 담당하는 클래스에 사용
    주로 데이터베이스와 상호작용하는 클래스에 붙이며, 데이터 액세스 관련 예외 처리를 자동으로 관리해주는 기능을 포함
  • @Controller: 웹 요청을 처리하는 컨트롤러 클래스에 사용
    주로 MVC(Model-View-Controller) 패턴에서 컨트롤러 역할을 하는 클래스에 붙이며, 클라이언트로부터 오는 HTTP 요청을 처리하고 응답을 반환하는 역할

1) MyService라는 클래스를 @Component 애너테이션으로 등록한다.

@Component 애너테이션을 붙이면 스프링이 자동으로 이 클래스를 빈으로 등록합니다. 이렇게 하면 설정 파일에 따로 등록할 필요 없이 간단하게 빈을 추가 할 수 있다. 

@Component
public class MyService {
    public String serve() {
        return "MyService가 동작 중입니다!";
    }
}

 

2) 빈 자동 스캔 설정하기

스프링이 특정 패키지 안의 @Component, @Service 애너테이션을 붙인 클래스를 자동으로 찾아서 빈으로 등록하도록 설정합니다.

@Configuration
@ComponentScan(basePackages = "com.example") // com.example 패키지에서 빈을 자동으로 스캔
public class AppConfig {
}

 

 


프로그래밍 방식으로 빈 추가하기

 

스프링 5부터는 registerBean( ) 이라는 메서드를 사용하여 프로그래밍 방식으로 빈을 추가할 수 있습니다.

이 방식은 상황에 따라 유연하게 빈을 추가할 수 있다는 장점이 있습니다.

registerBean( ) 메서드는 스프링 컨텍스트에서 동적으로 빈을 등록하는데 사용되는데, 애플리케이션 실행 중 또는 특정 조건에서만 빈을 등록해야 할 경우 유용하게 사용될 수 있습니다.

public class Application {
    public static void main(String[] args) {
        // 스프링 컨텍스트 생성
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

        // MyService 빈을 직접 등록
        context.registerBean(MyService.class);
        context.refresh(); // 컨텍스트를 새로고침하여 빈을 활성화

        // MyService 빈 사용
        MyService myService = context.getBean(MyService.class);
        System.out.println(myService.serve()); // 출력: "MyService가 동작 중입니다!"
    }
}

 

위 코드에서 registerBean(MyService.class)를 사용해 MyService 클래스의 빈을 동적으로 등록해. 이 방법을 통해 애플리케이션 실행 중에도 빈을 추가할 수 있고, 미리 설정 파일에 정의하지 않아도 빈을 등록하고 사용할 수 있어.


3. 빈 간의 관계 설정하기

스프링의 가장 큰 장점 중 하나는 빈들 간의 의존성을 스프링이 자동으로 관리해준다는 것입니다. 

즉, 한 빈이 다른 빈을 필요로 할 때, 스프링이 알아서 그 관계를 설정해줍니다. 

 

@Controller
public class MyController {

    private final MyService myService;

    // @Autowired를 사용해 MyService 빈을 자동으로 주입받습니다.
    @Autowired
    public MyController(MyService myService) {
        this.myService = myService;
    }

    public String handleRequest() {
        return myService.serve();
    }
}

 


4. 빈 등록 시 주의할 점

 

  • 순환 의존성: 두 빈이 서로를 의존하게 만들면 순환 참조 문제가 발생할 수 있습니다. 스프링은 기본적으로 이런 경우를 막아줍니다.
순환 의존성(Circular Dependency)이란 두 개 이상의 객체(또는 빈)가 서로를 의존하는 상황을 말합니다. 
예를 들어, 클래스 A가 클래스 B를 필요로 하고, 동시에 클래스 B도 클래스 A를 필요로 하는 경우를 순환 의존성이라고 합니다. 
  • @Primary와 @Qualifier: 같은 타입의 빈이 여러 개 있을 때는 스프링이 어떤 빈을 사용할지 헷갈릴 수 있습니다. 이때는 @Primary 애너테이션을 사용해 기본값을 설정하거나, @Qualifier를 사용해 구체적으로 어떤 빈을 사용할지 지정할 수 있습니다.