본문 바로가기
Server/Spring

스프링 빈 등록하기 - 1. 컴포넌트 스캔과 자동 의존관계 설정

by print_soo 2024. 8. 25.
private final MemberRepository memberRepository = new MemoryMemberRepository();

기존에 필요한 객체가 있다면 위의 코드와 같이 직접 객체를 만들어와서 사용해왔다.

 

 

다만, 이렇게 할 경우 아래의 단점 들이 생기게 된다. 

1. 높은 결합도: 클래스들이 서로 강하게 연결되어, 변경이 어려워집니다.
2. 유연성 부족: 다른 구현체(클래스)로 쉽게 교체하기 어렵습니다.
3. 테스트 어려움: 테스트할 때 실제 객체를 사용해야 하므로 느려지고 복잡해집니다.
4. 가독성 및 유지보수성 저하: 코드에서 의존성을 파악하기 어렵고, 관리가 힘들어집니다.
5. 재사용성 저하: 특정 상황에 맞게 유연하게 재사용하기 어렵습니다.

 

 

따라서 우리는 @Component와 @Autowired를 통해서 각자 필요한 객체를 서로 연결해주는 의존성 주입(DI)를 해보려고 한다.

 

우선 알아보기 전에 용어 정리부터 해보자.

 

스프링 컨테이너

  • 스프링 컨테이너는 빈을 담아주는 상자이다. 
  • 스프링이 실행되면 스프링 컨테이너는 우리가 정의한 빈들을 만들어 담아두고 필요할 때마다 꺼내서 사용하도록 해준다. 
  • 어플리케이션에서 어떤 객체들이필요하고, 그 객체들이 어떻게 연결되는지(의존성 주입)를 컨테이너가 알아서 관리해준다.

 

  • 스프링이 관리하는 객체를 의미한다.
  • 쉽게 말해, 스프링이 필요할 때 꺼대 쓸 수 있도록 만들어 놓은 도구
  • A라는 클래스가 있다면, 스프링이 A 객체를 빈으로 등록하고 관리한다. B라는 클래스에서 A객체가 필요하면 스프링에서 자동으로 꺼내서 제공해준다.

 


 

1. 빈 등록하기 (땅 만들기)

 

빈과 그 연결을 땅과 다리라고 가정하고 설명을 해보겠다.

 

우선 우리는 땅(빈)을 만들고 등록해보자. 

이전에 우리가 만들어본 Service, Controller, repository를 빈에 등록하면 @Component를 사용하면 된다. 아래와 같이 클래스 위에 작성해주면 된다.

 

@Service
public class MemberService {
    ...
}

@Controller
public class MemberController {
    ...
}

@Repository
public class MemoryMemberRepository implements MemberRepository {
    ...
}

 

 

왜 @Component 사용하지 않고 @Service, @Controller, @Repository를 사용한걸까?

-> 우선 @Service, @Controller, @Repository 내부에 @Component가 있기때문에 해당 어노테이션을 해도 무방하다. 또한 나눠서 어노테이션을 하는 이유는 역할에 따라 더 명확하게 구분하고 특정 기능을 부여하기 위해서 이다.

 

 

2. 의존성 주입(다리 만들기)

빈을 등록했으니 해당 빈이 필요한 곳에 사용할 수 있도록 의존성 주입을 해보자.ㅇ 

 

의존성을 주입 하기 위해서는 @Autowired가 필요하다. 이 어노테이션을 사용하면 자동으로 해당 타입의 빈을 찾아서 주입해준다.

또한 주입 받은 빈을 활용해야하기 때문에 생산자도 있어야한다.

 

//[Controller]
private final MemberService memberService;

@Autowired //필요한 것들을 직접 생성하지말고 외부에서 가져다줘! 라는 의미이다.
// 즉, Memeber service는 Member Repository가 필요하므로 스프링 컨테이너에서 repository 빈을 가져다주라는 말이다.
public MemberController(MemberService memberService) {
    this.memberService = memberService;
}



//[Service]
private final MemberRepository memberRepository;

@Autowired //필요한 것들을 직접 생성하지말고 외부에서 가져다줘! 라는 의미이다.
// 즉, Memeber service는 Member Repository가 필요하므로 스프링 컨테이너에서 repository 빈을 가져다주라는 말이다.
public MemberService(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
}

 

 

이렇게 컨트롤러는 서비스가 필요하고 서비스는 레포지토리가 필요하기 때문에 서로 연결해주면 필요할 때 의존성 주입이 된다. (즉 땅을 다리로 연결 했으니 필요할 때마다 필요한 자원을 B에서 A로, C에서 B로 전달이 가능하다. 

 

이게 바로 의존성 주입이다.