[스프링 입문] Section05. 스프링 빈과 의존관계

Euiyeon Park·2025년 6월 13일
0

갓영한 스프링🍀

목록 보기
4/12
post-thumbnail

🫛 스프링 빈(Bean)이란?

  • 스프링 프레임워크에서 스프링 컨테이너가 관리하는 객체, 인스턴스
  • 스프링이 생성하고, 의존성을 주입하고, 생명 주기를 관리하는 객체
  • 일반 자바 객체는 new 키워드로 생성하는 반면,
    스프링에서는 스프링 컨테이너(Application Context)가 대신 객체 생성 및 관리
  • 어노테이션에 따라 스프링 빈의 대상이 됨 - 해당 클래스의 인스턴스는 빈으로 등록
  • @Component, @Service, @Repository, @Controller, @Configuration + @Bean

스프링 빈을 등록하는 2가지 방법

  1. 컴포넌트 스캔과 자동 의존관계 설정
  2. 자바 코드로 직접 스프링 빈 등록

15. 컴포넌트 스캔과 자동 의존 관계 설정

  • ControllerServiceRepository를 사용할 수 있도록 의존 관계를 준비

  • 스프링이 처음에 뜰 때 스프링 컨테이너가 생성되는데,
    MemberController.java 파일에 @Controller 를 붙여두면
    컨트롤러 객체를 생성해서 스프링 컨테이너에 넣어두고 관리한다.

  • 즉, 스프링 컨테이너에서 스프링 빈이 관리된다.

의존 관계의 DI - new를 지양한다

@Controller
public class MemberController {

	private final MemberService memberService = new MemberService();
    
    ...
}
@Controller
public class MemberController {

	private final MemberService memberService;
    
    @AutoWired
    public MemberController(MemberService memberService) {
    	this.memberService = memberService;
    
    }
    ...
}
  • ControllerService 의존관계를 맺는 과정에서
    첫 번째 코드처럼 new를 사용하는건 스프링답지 않다.
    • 스프링의 의존성 주입이 안됨
    • AOP, 트랜잭션 등 스프링의 기능이 적용되지 않음
    • 테스트나 유지보수가 불편
  • 스프링답게 사용하기 위해서는 스프링 컨테이너에 빈으로 등록하고,
    스프링 컨테이너에서 받아서(주입받아서) 사용할 수 있어야 한다.
  • 🌿 따라서 @Autowired를 사용해 의존관계를 주입한다.

컴포넌트 스캔 - @Component, 스프링이 관리할 객체(빈)를 자동 등록

  • @Component는 해당 클래스를 스프링 컨테이너가 관리할 수 있도록 등록하는 어노테이션
  • 위에서 언급한 대로 @Controller, @Servcie, @Repository 등의 어노테이션은
    내부적으로 @Component를 포함하고 있어,
    스프링이 실행될 때 자동으로 객체를 만들어 관리(스프링 컨테이너에 빈 등록)
  • ⚠️ 단, @ComponentScan이 설정된 패키지 안에 있어야 감지됨!

참고 - 스프링의 기본 빈 생성 방식, Singleton

  • 스프링 컨테이너에 빈을 등록할 때 기본적으로 싱글톤으로 등록
  • 오직 하나의 객체(인스턴스)를 생성해 애플리케이션 전체에서 공유하는 방식
  • 모든 빈을 싱글톤으로 생성해 필요할 때마다 같은 객체를 주입
  • 메모리 효율, 공통된 설정 및 데이터 공유 가능, 애플리케이션 전반에서 동일한 동작 유지

자동 의존관계 설정 -@Autowired, 자동으로 필요한 객체를 주입

  • @Autowired는 스프링 컨테이너 안에 있는 필요한 객체(빈)을 자동으로 주입하는 어노테이션

  • ControllerService를 사용하고, ServiceRepository를 사용할 수 있도록
    @Autowired연관관계(의존관계)를 자동으로 맵핑(주입)해줌

  • 생성자, 필드, setter() 등에 사용 가능

    • 생성자에 @Autowired를 사용하면 객체 생성 시점에
      스프링 컨테이너에서 스프링 빈을 찾아서 주입
  • ⚠️ 단, @Autowired를 통한 DI는 스프링이 관리하는 객체에서만 동작
    (스프링 빈으로 등록하지 않거나, 개발자가 직접 생성한 객체에서는 동작❌)

정리하자면,

  • @Component를 통해 스프링 빈으로 등록하고,
  • @Autowired를 통해 빈들 간의 의존관계를 자동으로 맺는다.
  • 🌿 스프링 컨테이너가 객체를 만들고, 필요한 곳에 자동으로 연결해주는 것이 DI의 핵심

16. 자바 코드로 직접 스프링 빈 등록하기

@Service, @Repository, @Autowired를 제거하면?

@Controller
public class MemberController {

    private final MemberService memberService;
	
    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
  • Controller에서 사용하는 Service가 스프링 빈으로 등록되지 않는 경우,
    Component Scan을 사용하지 않고 직접 등록해서 사용 가능
  • Config 파일에서 수동으로 Bean으롤 정의한 ServiceController에 DI해줌

@Configuration

  • 해당 클래스가 스프링 설정 클래스임을 명시
  • 스프링은 이 클래스를 빈 구성정보로 사용하여 애플리케이션의 객체(빈) 관리를 수행
  • @Bean 어노테이션을 사용해 메서드에서 정의한 빈들을 스프링 컨테이너에 등록
  • 스프링은 이 클래스를 읽고, 내부의 빈 정의를 스캔해 스프링 컨테이너에 빈을 등록

@Bean

  • 메서드에서 반환하는 객체를 스프링 빈으로 등록
  • 빈으로 등록된 객체는 싱글톤으로 관리, 필요할 때 의존성 주입을 통해 사용

📂SpringConfig.java

@Configuration
public class SpringConfig {
	
    @Bean
    public MemberService memberService(){
    	return new MemberService(memberRepository());
    }
	
    @Bean
    public MemberRepository memberRepository(){
    	return new MemoryMemberRepsoitory();
    }
}

기타 참고사항

  • DI의 세 가지 방식(생성자 주입, 필드 주입, setter 주입) 중,
    의존관계가 실행 중에 동적으로 변경되는 경우는 ㄴ거의 없으므로 생성자 주입을 권장
  • 실무에서 정형화된 Controller, Service, Repsotitory 는 컴포넌트 스캔을 사용
  • 정형화되지 않거나, 상황에 따라 구현 클래스를 변경해야 되는 경우,
    설정을 통해 스프링 빈으로 등록
    - @Configuration + @Bean
profile
"개발자는 해결사이자 발견자이다✨" - Michael C. Feathers

0개의 댓글