2 분 소요

이 글은 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 커리큘럼에 맞춰서 작성된 글입니다😀

스프링 빈을 등록하는 방법은 2가지가 있다.

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

근데 모르는 용어가 하나 둘씩 등장한다😯
스프링 빈은 뭐고 스프링 컨테이너는 뭘까?
간단하게 설명하면 스프링 빈은 스프링에서 활용하는 객체고,
스프링 컨테이너는 빈이 활동할 수 있는 환경이다. 빈의 생명주기를 관리한다고 보면 된다.
검색해보면 자세한 설명글이 많은데 GilLog님의 글이 이해가 잘됐다!
물론 강의에서도 잘 설명해주신다😄

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

hello/hellospringcontroller라는 리포지토리를 생성 후 MemberController.java를 만들어주자.
그리고 코드를 다음과 같이 적어주자.

일단 확인해야할 점이 3가지가 있다.

첫 번째로, 필드로 선언된 memberService를 new를 통해 인스턴스 생성을 하지 않은 점이다.
new를 통해 만들어서 쓸 수는 있으나 memberSerivce에 구현된 내용은 딱히 여러 인스턴스를 관리하면서
별도로 운용될 필요가 없기 때문에 1개만 스프링 컨테이너에 등록해놓고 사용해도 문제가 없다!
따라서 new가 아닌 위의 코드처럼 생성자를 활용해 받아와서 등록하는 방식을 취한다.

두 번째로, 위 코드는 Run 했을 때 스프링에서 인식하지 못한다.
어노테이션이 달려있는 것들만 빈으로 만들어서 스프링 컨테이너에서 관리하게 되는데
MemberController는 지금 어노테이션이 등록되지 않은 상태여서 그렇다.
이 때 Run을 하면 memberService가 스프링 빈으로 등록되어 있지 않다는 에러가 뜨게 된다.
그니까 @ControllerMemberController위에 써주면 해결된다!
같은 맥락으로 MemberService에는 @Service를, MemoryMemberRepository에는 @Repository를 써줘야 한다.

마지막으로, MemberController에서 MemberService를 활용하고 있음을 확인할 수 있다.
비슷하게 MemberService에서는 MemberRepository를 활용하고 있다.
(MemberController -> MemberService -> MemberRepository)
이렇게 활용하고 있는 관계를 의존관계라고 하는데, 이 때 @Autowired를 꼭 써줘야 한다!
때문에 MemberControllerMemberSerivce의 생성자에 @Autowired라는 어노테이션을 달아주자.
최종적인 MemberController의 코드는 다음과 같다.

@Controller, @Service, @Repository 모두 @Component에 속하는 케이스이며
이렇게 컴포넌트로 명시된 것들을 스프링이 찾아 빈으로 만들어 컨테이너에 등록하기 때문에
이를 컴포넌트 스캔이라고 한다.

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

위에서 MemberServiceMemoryMemberRepository에 등록한 어노테이션인
@Service, @Repository, @Autowired를 없애주자. (MemberController는 건드리지 않는다)
그러면 MemberController에서 생성자의 인자로 들어오는 MemberService가 스프링 빈으로 등록되지 않아서
에러가 발생하게 된다. 때문에 스프링 빈으로 등록해주는 작업이 필요하다.

hello/hellospring/serviceSpringConfig라는 클래스를 만들고 다음과 같이 써주자.
MemberServiceMemberRepository를 스프링 빈으로 등록해기 위해 @Bean을 반드시 붙여야 한다!
참고로 MemberSerice의 생성자의 인자로 MemberRepository가 들어오기 때문에
리턴 시 return new MemberService(memberRepository())로 써줘야 한다!

컴포넌트 스캔도 그렇고 스프링 빈 등록에서도 그렇고 생성자 주입 방식을 따랐는데,
의존성 주입(Dependency Injection: DI)을 하는 방법은 3가지 방법이 있다고 한다.

  • 필드 주입 : 필드 앞에 @Autowired를 붙여서 연결하는 방식
  • setter 주입 : setter를 활용해 연결하는 방식
  • 생성자 주입 : 생성자의 특성을 활용해 연결하는 방식

어차피 Runtime에서 변경될 이유나 해당 사항이 없기 때문에 안정적인 생성자 주입을 추천한다고 한다.

컴포넌트 스캔 방식과 스프링 빈으로 등록하는 방식 중 어떤 것을 써야할까?
컴포넌트 스캔 방식은 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드에서 사용하고
스프링 빈 등록 방식은 구현 클래스를 변경해야하는 상황일 때 사용한다고 한다.
이전글에서 데이터 저장소가 등록되지 않은 상황을 가정하자고 했었다.
그러니까 MemberRepository라는 인터페이스를 만들고 그 구현체인 MemoryMemberRepository를 사용했는데
상황에 따라 MemberRepository를 구현하지만 MemoryMemberRepository가 아닌 다른 구현체를 활용해야 할 때
SpringConfig에서 MemberRepository에 리턴하는 내용을 다른 구현체로 바꿔치기해주면 된다!
컴포넌트 스캔 방식일 때는 이것저것 건드려줘야 하는데 반해 간단하게 수정할 수 있는 장점이 있다!

카테고리:

업데이트:

댓글남기기