그동안 김영한님의 스프링 고급편까지 달려오면서 점점 기초적인 Bean에 대한 정의가 흔들리기 시작했다.
그래서 결국 Bean이란 무엇인가?
스프링을 오래 사용하면서 이 단어에 익숙해졌지만 혼자 명확히 제대로 짚어보기는 너무 미뤘던 것 같다.
이 게시글에서는 Bean에 대한 정의 및 의존성 주입에 대해 다시 한번 짚어보고자 한다.
Spring이라는 프레임워크에서 빈은 스프링이 관리하는 객체라고 한다.
별로 와닿지 않는다.
코드가 객체를 어떻게 관리하지?
그럼 자바 인스턴스와 빈은 같은건가? 뭐가 다른거지?
둘은 다르지 않다.
빈은 자바 인스턴스의 종류 중에 하나일 뿐이다.
스프링 빈 등록에 대한 대략적인 그림 흐름은 이렇다.
그렇다면 그냥 객체와 인스턴스 개념 외에 빈이라는 개념이 필요한 이유는 뭘까?
이는 스프링의 근본적인 장점과 직결된다.
의존성 주입이다.
의존성 주입이라는 말도 처음에는 와닿지 않았는데 의외로 간단했다.
스프링이 관리하는 빈이 있지 않는가.
회사가 사원을 관리하면 보통 사번 체계가 있다.
사번으로 사원을 특정해 사원을 호출할 수도, 일을 시킬수도 있다.
그 사번을 사용하던 사람이 퇴사하고 다른 새로운 사람이 그 사번을 쓸 수도 있다.
스프링, 빈과 의존성 주입도 비슷한 개념이다.
스프링은 회사, 빈은 사번, 의존성 주입은 발령으로 볼 수 있을 것 같다.
챗지피티가 짜준 Bean 설정 코드이다.
// 빈으로 사용될 클래스 정의
public class MyBean {
// 클래스 내용 생략
}
// 스프링 설정 클래스
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
// 컴포넌트 스캔을 통해 MyBean 클래스를 빈으로 등록
@Bean
public MyBean myBean() {
return new MyBean();
}
}
// 애플리케이션 실행
public class MainApp {
public static void main(String[] args) {
// 스프링 컨텍스트 생성
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 빈 호출
MyBean myBean = context.getBean(MyBean.class);
// 빈 사용
// ...
}
}
여기서 다음 코드로 넘어갈 때의 차이는 @Component로 Bean을 등록하게 해달라고 했다.
@Component를 클래스 위에 달게 되면 따로 Configuration 클래스에 @Bean을 등록하지 않아도 자동으로 해당 클래스가 빈으로 등록이 된다.
// 빈으로 사용될 클래스 정의
@Component
public class MyBean {
// 클래스 내용 생략
}
// 스프링 설정 클래스에서 컴포넌트 스캔을 통해 빈을 찾도록 설정
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
// AppConfig 클래스에 따로 빈 설정 메서드를 작성할 필요가 없음
}
// 애플리케이션 실행
public class MainApp {
public static void main(String[] args) {
// 스프링 컨텍스트 생성
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 빈 호출
MyBean myBean = context.getBean(MyBean.class);
// 빈 사용
// ...
}
}
이 다음은 @Autowired 어노테이션의 편의성이다.
// 빈으로 사용될 클래스 정의
@Component
public class MyBean {
// 클래스 내용 생략
}
// 다른 클래스에서 MyBean을 주입받아 사용
@Service
public class MyService {
private final MyBean myBean;
// 생성자 주입을 통해 MyBean을 주입받음
@Autowired
public MyService(MyBean myBean) {
this.myBean = myBean;
}
// MyBean 사용
public void doSomething() {
// myBean 사용
// ...
}
}
// 애플리케이션 실행
public class MainApp {
public static void main(String[] args) {
// 스프링 컨텍스트 생성
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// MyService 빈 가져오기
MyService myService = context.getBean(MyService.class);
// MyService에서 MyBean 사용
myService.doSomething();
}
}
빈 컨테이너에는 사번과 직원에 대한 리스트가 있다.
@Autowired 어노테이션을 생성자에 붙여 생성자 주입을 하게 되면
해당 사번을 가진 직원을 그 자리에 자동으로 발령을 내준다.
이게 빈과 의존성 주입이다.
매번 new 인스턴스를 생성할 필요없이 스프링에 등록된 빈 객체를 발령받아 사용하는 것이다.
A라는 일을 하는 사원이 하나면 됐지, A라는 일을 할 때마다 사람을 뽑는건 비효율적이지 않는가.
'Spring > 이론' 카테고리의 다른 글
[AOP] @Aspect 프록시, 포인트컷, 어드바이스 (0) | 2024.01.30 |
---|---|
[스프링 고급] 빈 후처리기 (0) | 2024.01.23 |
[AOP 기반] 프록시 팩토리, 포인트컷, 어드바이스, 어드바이저란? (0) | 2024.01.17 |
프록시 형태 별 차이 (인터페이스 VS 클래스) (0) | 2024.01.04 |
[JPA] 응답 값으로 DTO를 전달해야 하는 이유 (0) | 2023.10.04 |