스프링 컨테이너와 빈

랏 뜨·2024년 12월 19일

🔎 Overview

  예전부터 필자가 정말 중요하게 생각하는 부분은 기초이다.
이 기초를 탄탄히 다지지 못해서 많이 넘어져도 봤고, 넘어지는 사람들도 많이 보았다.

  최근 스프링에 대해 공부하며, 나는 내 생각보다 더 스프링을 잘 모른다는 느낌이 들었다.
그렇게 중요시하던 기초적인 부분도, 원리도, 그냥 이런 식으로 되는구나~ 하고 넘겨왔던 것 같다.

  그러다보니 스프링을 더욱 공부해나갈수록, 기초적인 부분에서 발목이 잡히기 시작했다.
왜 이렇게 동작하는지도 확실하게 알지 못하는데, 점점 그 앞을 나아갈 수 있을 리 없다.

그렇기에 초심으로 돌아가서, 당분간 스프링의 핵심 요소들 및 헷갈리거나 중요한 요소들을 차근차근 공부하고 정리할 예정이다.

금일은 스프링 컨테이너에 대해서 학습해보자.


1️⃣ 스프링 컨테이너

  • 스프링 빈 객체를 관리하는 핵심 부분
  • 빈 객체의 생성, 소멸 등의 생명주기를 관리
  • DI (의존성 주입) 담당
  • 프로젝트의 설정 파일(XML, Java Config ...), 어노테이션 등을 기반으로 구성


✔️ 컨테이너의 종류

  • ApplicationContext
    • 스프링에서 가장 많이 사용되는 컨테이너
    • 애플리케이션 전반에 걸쳐 을 관리
  • BeanFactory
    • 스프링의 기본 컨테이너
    • 지연 로딩 방식

2️⃣ 스프링 빈

  • 스프링 컨테이너에서 관리하는 객체
  • 개발자가 객체를 으로 등록하면, 스프링 컨테이너에서 해당 객체를 담당
  • DI 에 필요한 요소
    • 개발자가 new 를 통해 객체를 직접 생성하지 않을 수 있게 해줌
  • 일반적으로 Controller, Service, Repository 등의 역할을 수행 (@Component)


📋 @Bean

  • 개발자가 직접 메서드을 정의
  • @Bean 어노테이션은 오직 메서드만 지정 가능
    • 필드, 클래스 등에는 지정 불가능
  • 일반적으로 @Configuration 내부에서 사용
  • 메서드의 이름
    • 빈의 이름은 기본적으로 메서드 이름으로 스프링 컨테이너에 등록
    • name 옵션으로 빈의 이름을 변경할 수 있음
  • 메서드의 반환값
    • 빈이 호출될 때 객체에 리턴값을 주입


✔️ 빈 등록 방법

1) @Configuration 지정 방식

  • 스프링의 설정 클래스를 정의할 때 사용
  • 애플리케이션의 전체적인 설정 담당
  • 의 생성과 의존성을 명시적으로 관리할 때 사용
  • XML 기반 설정을 대체하여 Java Config을 제공
  • 지정 방법
    • 클래스에 @Configuration 어노테이션 지정
    • 으로 등록을 원하는 메서드를 @Bean 어노테이션으로 지정
@Configuration
public class AppConfig {
	@Bean
    public UserService userService() {
    	return new UserService(userRepository);
    }
    
    @Bean
    public UserRepository userRepository() {
    	return new UserRepository();
    }
}
  • 메서드의 이름을 이름으로 지정하여 스프링 컨테이너에 등록
  • 여기서는 userServiceuserRepository 가 등록

2) @Component 지정 방식

  • 일반적인 빈 객체를 정의하는 클래스에 사용
  • 클래스 자체스프링 컨테이너에 의해 관리되도록 지정
  • Controller, Service, Repository 클래스 등을 으로 등록할 때 사용
  • 주로 비즈니스 로직이나 데이터 처리를 담당하는 객체에 사용
  • @Controller , @Service , Repository 의 기본형
@Component
public class UserService {
	public String sendUser() {
    	return "User";
    }
}
  • 클래스명userService으로 등록

🛑 1)과 2)의 코드를 같이 사용하면 userService를 동일한 이름으로 가진 이 2개 발생한다.
기본적으로 빈의 이름은 고유해야 하기 때문에, 이 경우 충돌이 발생한다.



🤔 동일한 이름의 여러 빈을 어떻게 처리하면 좋을까?

@Configuration
public class AppConfig {
    @Bean
    public User user {
        return new User();
    }

    @Bean
    public User user {
        return new User();
    }
}

1) name 옵션 및 @Qualifier 사용

@Bean(name = "newName")
public User user {
	return new User();
}

public class UserService {
	@AutoWired
    @Qualifier("newName")
    private User user;
}
  • 하나의 메서드에 name 옵션을 지정
  • 메서드명은 아직 User 로 동일하기 때문에, 스프링 컨테이너 에는 user 빈이 2개 등록
  • 2개의 user 빈 중 어떤 것을 선택할 지 @Qualifier 어노테이션으로 지정
  • 빈을 선택하는 것으로 충돌을 피할 수 있음


2) @Primary

@Bean(name = "newName")
@Primary
public User user {
	return new User();
}
  • 하나의 메서드에 @Primary 지정
  • 지정된 메서드가 user 빈 중 기본 빈으로 스프링 컨테이너에 등록
  • 빈이 호출되면 기본 빈을 주입하는 것으로 충돌을 피할 수 있음

참고) OpenAI. (2024).ChatGPT(4o)[Large language model].https://chatgpt.com/

profile
기록

0개의 댓글