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

Sujung Shin·2023년 1월 15일
0
post-thumbnail

❤️ 스프링 빈(Bean)

스프링 컨테이너가 관리하는 자바 객체(POJO)를 빈(Bean)이라고 한다.
자바에서는 객체를 생성할 때 주로 new()를 통해 생성하는데, 이 객체를 의미하는 것이 아니라 컨테이너에서 스스로 생성하고 관리하는 객체를 의미한다.
컨테이너에서의 관리를 통해 객체를 여러 번 생성할 필요가 없고, 공용으로 사용할 수 있다.

❤️ 스프링 컨테이너

스프링 컨테이너는 스프링 빈의 생명 주기를 관리하며, 생성된 스프링 빈들에게 추가적인 기능을 제공하는 역할을 한다.
스프링의 3대 핵심원리인 IoC(제어의 역전), DI(의존성 주입)의 원리가 스프링 컨테이너에게 적용된다.
개발자는 new 연산자, 인터페이스 호출, 팩토리 호출 방식으로 객체를 생성하고 소멸하지만, 스프링 컨테이너는 이를 대신 해준다.
즉, 제어의 흐름을 외부에서 관리하게 된다.(IoC)
또한, 객체들과의 의존관계를 스프링 컨테이너에서 알아서 만들어준다.(DI)

스프링 빈을 등록하는 방식에는 크게 2가지가 있다.

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

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

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

☝️ Component Scan

컴포넌트 스캔은 @Component 어노테이션을 명시하여 빈을 추가하는 방법이다. 클래스 위에 @Component를 붙여서 스프링 컨테이너에 빈을 등록한다.
@Controller 컨트롤러가 스프링 빈으로 자동 등록된 이유도 컴포넌트 스캔 덕분이다.

@Component를 포함하는 다음 어노테이션도 스프링 빈으로 자동 등록된다.

  • @Controller
    : 스프링 MVC 컨트롤러로 인식된다.
  • @Service
    : 특별한 처리는 하지 않으나, 개발자들이 핵심 비즈니스 계층을 인식하는 데 도움을 준다.
  • @Repository
    : 스프링 데이터 접근 계층으로 인식하고 해당 계층에서 발생하는 예외는 모두 DataAccessException으로 처리한다.
  • @Configuration
    : 스프링 설정 정보로 인식하고 스프링 빈이 싱글톤을 유지하도록 추가 처리를 한다.

💻 회원 컨트롤러에 의존관계 추가

hello-spring/src/main/java/hello/hellospring/controller/MemberController.java

package hello.hellospring.controller;
 
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
 
@Controller
public class MemberController {
 
	private final MemberService memberService;
 
	@Autowired
	public MemberController(MemberService memberService) {
		this.memberService = memberService;
	}
}

💻 회원 서비스 스프링 빈 등록

@Service
public class MemberService {
	
    private final MemberRepository memberRepository;
    
    @Autowired
    public MemberService(MemberRepository memberReopsitory) {
    	this.memberRepository = memberRepository;
    }
}
  • 생성자에 @Autowired를 사용하면 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입한다. 생성자가 1개만 있으면 @Autowired는 생략할 수 있다.

  • controller와 service 연결

    : MemberController 생성될 때 스프링 빈에 등록되어있는 MemberService 객체를 가져다 넣어준다.
    : DI(Dependecny Injection: 의존성 주입)

  • service 전체 흐름도
    : MemberService는 MemberRepository가 필요하다. 스프링은 MemberService를 호출할 때 @Service 보고 스프링 컨테이너에 MemberService 등록하며 생성자를 호출한다.
    이때 @Autowired가 있으면 MemberRepository가 필요하다고 판단한다.
    MemberRepository 스프링 컨테이너에는 구현체로 MemoryMemberRepository가 있으므로 MemoryMemberRepository가 서비스에 주입된다.

💻 회원 리포지토리 스프링 빈 등록

@Reopsitory
public class MemoryRepository implements MemberRepository {}



✔️ 자동 의존관계 설정

  • @Autowired 는 관계를 연결해준다.
  • MemberController가 MemberService를 쓸 수 있게 해주고, MemberService가 MemberRepository를 쓸 수 있게 된다.
  • @Component 어노테이션이 있으면 스프링 빈으로 자동 등록된다.
  • @SpringBootApplication 부터 시작해, 패키지를 포함한 하위 패키지들은 스프링이 어노테이션을 찾아 스프링 빈으로 등록한다.

  • 하위 패키지가 Application 패키지와 동일하거나 하위 패키지가 아닌 경우 컴포넌트 스캔을 하지 않는다.

  • 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본적으로 싱글톤으로 등록한다.(유일하게 하나만 등록해서 공유한다) 따라서 같은 스프링 빈이면 모두 같은 인스턴스이다. 설정으로 싱글톤이 아니게 설정할 수 있지만, 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.
    (ex helloController 1개, memberService 1개, memberRepository 1개)


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

  • Dependency Injection (DI)에는 필드 주입, setter 주입, 생성자 주입이 있다.
    의존관계가 실행 중에 동적으로 변하는 경우는 거의 없으므로 생성자 주입을 권장한다.
    실무에서는 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드에 컴포넌트 스캔을 사용한다.
  • 정형화되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록한다.
  • 본 강의에서는 메모리 리포지토리를 다른 리포지토리로 변경할 예정이기 때문에 자바 코드로 직접 스프링 빈을 등록하기로 한다.
  • @Autowired를 통한 DI는 스프링이 관리하는 객체(helloController, memberService)에서만 동작한다. 사용자가 직접 생성한 객체에서는 동작하지 않는다.

💻 SpringConfig 파일 만들기

hello-spring/src/main/java/hello/hellospring/SpringConfig.java

package hello.hellospring;
 
import hello.hellospring.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class SpringConfig {
	
	@Bean
	public MemberService memberService() {
		return new MemberService();
	}
    
    @Bean
	public MemberRepository memberRepository() {
		return new MemoryMemberRepository();
	}
}

스프링이 뜰때, @Configuration 을 읽고, @Bean 쓰여진 memberService 로직을 호출해 스프링 빈에 등록한다.
memberService는 생성자에서 memberRepository 를 넣어줘야 하는데, 인터페이스이므로 이의 구현체인 MemorymemberRepository를 리턴하여 넣어준다.

profile
백문이불여일타

0개의 댓글

관련 채용 정보