본문 바로가기

Spring

Java Spring 에서의 Bean 이란?

안녕하세요! 즐거운 주말이 되어 오늘도 포스팅합니다! 오늘의 주제는 저의 지난 포스팅이나 다른 Spring 관련된 내용에서 늘 등장하는 Bean 이란 어떤것인지에 대해 알아보려고 합니다! 

 

Bean 은 우리 모두가 알고있듯 '콩' 이란 의미이죠? 또한 Java 를 보면 항상 나오는 커피잔 로고를 보신 적 있을 겁니다. 별로 이론적인 내용과는 상관없긴 하지만 자바가 커피한잔을 의미한다고 치면 Bean 은 아마도 '커피콩'의 '콩'을 의미하는 것 같습니다.

 

이제 좀 더 이론적인 내용으로 들어가보겠습니다.

 


Spring 에서 Bean 이란 무엇인가요?

"Spring 에서 Bean 이 뭔가요?" 라는 질문은 초보자뿐 아니라 중급 개발자에게도 한 번쯤 다시 짚고 넘어갈 필요가 있는 중요한 주제입니다. Spring 을 제대로 이해하고 활용하려면 "Bean 이란 무엇인가?"를 먼저 정확히 이해하는 것이 매우 중요하죠.

 

✅ Bean 이라는 이름은 왜 붙였을까?

"Bean" 이라는 단어는 Java 진영에서 오래전부터 사용된 개념입니다. JavaBean 이라는 개념이 그 뿌리라고 할 수 있습니다.

  • JavaBean 은 기본 생성자와 Getter/Setter 를 가진 단순한 자바 객체(POJO)를 말합니다.
  • 주로 데이터 전달 객체(DTO)처럼 사용되었고, 재사용 가능한 컴포넌트로 취급되었습니다.

 

Spring 은 이런 JavaBean 에서 재사용 가능하고 독립적인 구성 요소(Component)라는 개념을 가져와서, Spring 컨테이너가 직접 관리하는 객체들을 Spring Bean 이라고 부르게 되었습니다.

 

즉, Bean 은 Spring 이 관리하는 재사용 가능한 자바 객체라는 의미라고 볼 수 있습니다.

 

이런 설명이 이해가 어려우시면 위에서 말했던 커피와 커피콩을 연상하면서 포스팅을 읽다보면 좀 더 자연스럽게 이해되실 수도 있습니다!!

 


🥔 Bean 은 어떤 역할을 하나요?

간단히 말해, Bean 은 Spring 이 생성하고, 관리하고, 주입하는 객체입니다.

 

Spring 에서 애플리케이션을 구성하는 핵심 구성 요소들은 모두 Bean 으로 관리되며, Spring 컨테이너가 이 Bean 들을 생성하고, 필요한 곳에 자동으로 주입(DI)합니다.

 

앞선 포스팅에서 Spring Framework 란 어떤 것인지에 대해 말할 때 언급했던 내용입니다.

Spring Framework 의 대표적인 특징으로 IoC(제어의 역전), DI(의존성 주입), AOP(관점 지향 프로그래밍) 에서 IoC와 DI 에 대한 내용을 설명할 때 Bean 이라는 용어가 언급되었었죠.

 

애플리케이션을 실행시키면, `ApplicationContext` 라는 스프링 IoC 컨테이너가 프로그램을 스캔하기 시작하고 Bean 들을 찾아 핵심 구성 요소들로 등록하고 관리해줍니다. 

우리가 개발을 할때 사용하는 @Component 라는 어노테이션이나, @Service, @Controller 등의 어노테이션을 타고 들어가다 보면 Bean 인터페이스와 연결되어 있는 것을 발견할 수 있을거에요.

 

이런 애플리케이션이 동작하는데 필요한 핵심 요소들을 ApplicationContext 라는 스프링 컨테이너가 Bean 으로 등록하여, 필요에 따라 Repository 는 Service 에 주입하고, Service 는 Controller 에 주입하는 등 생성과 주입을 개발자대신 Spring 이 직접 하며 IoC(제어의 역전)을 이뤄내게 되고, DI 도 할 수 있게됩니다. (앞선 포스팅과 이어서 읽으면 훨씬 이해하기 쉬울거에요!)

 

✅ Spring 에서 Bean 의 역할 요약

역할 설명
객체 생성 개발자가 new 로 생성하지 않아도 스프링이 대신 생성
의존성 주입 필요한 Bean 을 찾아서 자동으로 주입
생명주기 관리 초기화, 소멸 등 생명주기를 컨테이너가 책임짐
싱글톤 유지 기본적으로 애플리케이션 내에 하나의 인스턴스만 유지(Singleton Scope)

 

이 역할들 중에서 싱글톤에 대한 개념도 추후에 디자인패턴을 다루는 글에서 만나보실 수 있습니다!


⚙️ Bean 은 어떻게 등록되나요?

Spring 에서는 다음과 같은 방식으로 Bean 을 등록할 수 있습니다.

 

1. 자동 등록 (컴포넌트 스캔)

@Component
public class UserService {}

 

`@Component`, `@Service`, `@Repository`, `@Controller` 등은 모두 자동 등록을 위한 어노테이션입니다. Spring 이 클래스패스를 스캔하면서 해당 어노테이션이 붙은 클래스들을 자동으로 Bean 으로 등록합니다.

 

2. 수동 등록 (@Bean)

@Configuration
public class AppConfig {

    @Bean
    public UserService userService() {
        return new UserService();
    }
}

 

`AppConfig` 와 같은 자바 설정 클래스를 통해 명시적으로 Bean 을 등록할 수 있습니다.

 

⛔ 동일한 이름 or 동일한 타입의 Bean 이 두 개 이상인 경우

Spring 에서 Bean 을 등록할 때는 내부적으로 Bean 이름(또는 ID) 를 키로 하여 Map 형태로 저장합니다.그래서 같은 이름의 Bean 이 중복되면 충돌(Confilct)이 발생하게 됩니다

 

1. 같은 이름의 Bean 이 두 번 수동 등록된 경우

@Bean("myService")
public MyService service1() {
    return new MyService();
}

@Bean("myService")  // 같은 이름으로 또 등록
public MyService service2() {
    return new MyService();
}

 

이 경우에 애플리케이션 실행 시 예외가 발생합니다 (중복 등록 오류)

` org.springframework.beans.factory.support.BeanDefinitionOverrideException`

 

기본적으로 Spring 은 동일한 이름의 Bean 을 덮어쓰기 하는 것을 허용하지 않습니다.

 

하지만 이런 경우 아래와 같이 설정하면 중복 등록 시 뒤에 있는 Bean 이 앞을 덮어쓰게 할 수 있습니다. 하지만 추천하지는 않는 방식입니다.

spring.main.allow-bean-definition-overriding=true

 

 

2. 같은 타입의 Bean 이 여러 개인 경우

@Bean
public MyService service1() {
    return new MyServiceImpl1();
}

@Bean
public MyService service2() {
    return new MyServiceImpl2();
}

 

위의 경우에는 Bean 이름은 다르지만, 타입(`MyService`)이 같기 때문에 `@Autowired` 로 주입할 때 어떤 Bean 을 주입할지 모호하기 때문에 에러가 발생합니다.

No qualifying bean of type 'MyService' available: expected single matching bean but found 2

 

✅ 수동 빈 등록 및 중복될 시, 해결 방법은?

방법 1. `@Primary` 사용 - 우선순위 지정

@Bean
@Primary
public MyService service1() {
    return new MyServiceImpl1();
}

@Bean
public MyService service2() {
    return new MyServiceImpl2();
}

 

`@Primary`가 붙은 Bean 이 자동 주입 시 우선 선택됩니다. 단, `@Qualifier` 가 있으면 무시됩니다.

 

 

방법 2. `@Qualifier` 로 명시적 지정

@Autowired
@Qualifier("service2")
private MyService myService;

 

위와 같은 방식대로 작성하면, 어떤 Bean 을 주입할지 이름으로 명확하게 지정할 수 있습니다. 이 방법이 가장 안전하고 명시적인 방법입니다.

 

 

방법 3. List<타입> 또는 Map<String, 타입>으로 여러 Bean 주입

@Autowired
private List<MyService> services;

@Autowired
private Map<String, MyService> serviceMap;


Spring 컨테이너에 등록된 `MyService` 타입의 모든 Bean 들을 모아서 주입해줍니다. `List` 는 순서대로 Bean 을 나열하고, `Map`은 Bean 이름(Key) - Bean 객체(Valeu) 형식으로 전달해 줍니다.

@Bean
public MyService serviceA() {
    return new ServiceA();
}

@Bean
public MyService serviceB() {
    return new ServiceB();
}

 

위처럼 두 개의 `MySercie` Bean 이 등록되어 있다면,

@Autowired
private List<MyService> services;  // [serviceA, serviceB]

@Autowired
private Map<String, MyService> serviceMap;  // {serviceA=ServiceA, serviceB=ServiceB}

 

Spring 이 자동으로 둘 다 넣어줍니다.

이 방식은 플러그인처럼 여러 기능을 순차적으로 실행해야 할 때나, Bean 이름을 기준으로 동적으로 실행할 로직이 있을 때 등 유용하게 활용할 수 있습니다.

public void process(String type) {
    MyService service = serviceMap.get(type);  // "serviceA" 또는 "serviceB"
    service.execute();
}

 

위와같은 예시로, 사용자가 "serviceA" 를 선택하면 해당 Bean 을 꺼내서 실행하는 식으로 사용 가능합니다.


🚫Bean 이 없다면 어떻게 될까?

Spring 없이 일반 자바 코드에서는 모든 객체를 직접 생성하고, 직접 연결해줘야 했습니다.

UserService userService = new UserService(); // 직접
OrderService orderService = new OrderService(userService); // 생성

 

이 방식은 코드가 많아지고, 유연성이 떨어지며, 테스트하기도 어려워집니다. 그래서 Spring 에서는 Bean 으로 객체를 대신 관리하고, 필요한 객체를 자동으로 연결해주기 때문에 코드가 훨씬 단순하고 유연해집니다.


정리: Spring Bean 이란?

Bean 은 Spring IoC 컨테이너(ApplicationContext) 에 의해 생성되고, 관리되며, 주입되는 객체를 말합니다. 즉, 개발자가 직접 관리하지 않고, Spring 이 대신 객체를 조립하고 운용합니다.

 

Spring 에서 Bean 은 단순한 객체가 아니라, IoC 와 DI 원칙에 따라 애플리케이션 전체를 구성하는 핵심 구성 요소입니다. Spring 을 이해하고 제대로 활용하려면, Bean 이란 무엇인지 단순하게 외우기 보다는, "0왜 필요한가", "어떻게 동작하는가" 를 함께 이해하면서 개발을 하시면 좋을 것 같습니다.

 

읽어주셔서 감사합니다!

728x90
반응형

'Spring' 카테고리의 다른 글

JPA 와 N+1 문제  (2) 2025.04.19
Spring - JPA  (0) 2025.04.05
Spring Framework 와 Spring Boot (2)  (0) 2025.04.05
Spring Framework 와 Spring Boot (1)  (0) 2025.03.30
Spring - Redis의 Pub/Sub 및 WebSocket 구현하기  (4) 2024.12.17