스프링 부트/스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

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

sungw00 2023. 3. 11. 13:09
728x90

스프링 빈을 등록하는 방법

@Controller, @Service, @Repository를 사용하는 방법을 컴포넌트 스캔이라고 한다.

이유: @Controller, @Service, @Repository 애노테이션들 속에는 @Component 애노테이션이 등록되어 있기 때문에 스프링이 실행될 때 컴포넌트 관련 애노테이션이 있으면 스프링이 객체를 생성해서 스프링 컨테이너에 모두 등록한다. 

(@Controller 컨트롤러가 스프링 빈으로 자동 등록된 이유도 컴포넌트 스캔 때문)

 

컴포넌트 스캔의 범위

hello.hellospring 패키지의 HelloSpringApplication.java 파일의 내용을 보면 패키지의 이름이 적혀져 있는데,

HelloSpringApplication의 메인 메서드가 실행이 될 때 hello.hellospring 패키지 하위의 파일들의 내용을 전부 읽어 스프링 빈으로 등록을 하지만, hello.hellospring 패키지의 하위 파일이 아닌 것들은 스캔하지 않는다.

@SpringBootApplication 애너테이션의 내용을 보면 @ComponentScan 애노테이션이 있기 때문에 스프링이 찾아서 스프링 컨테이너에 등록되는 것이다.

 

@Autowired는 MemberController가 MemberService를 쓸 수 있도록, MemberService가 MemberRepository를 쓸 수 있도록 연결해준다. 

스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록한다(유일하게 하나만 등록해서 공유) 따라서 같은 스프링 빈이면 모두 같은 인스턴스다.

 

컴포넌트 스캔

스프링 컨테이너가 @Controller 애너테이션을 보고 MemberController 객체를 생성해서 넣어둔다.(스프링 빈이 관리된다)

그렇기때문에 컨트롤러 관련 기능들이 동작하는 것.

 

MemberController 코드를 작성해보자.

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;
    }
}

new로 객체를 생성하는 것보다 하나만 생성해놓고 공용으로 쓰는 것이 적합할 때: 스프링 컨테이너에 등록하면 하나만 등록이 된다.

 

@Autowired: 스프링 컨테이너에 있는 MemberService를 가져와서 연결을 시켜줌

스프링 빈으로 대부분의 것들을 다 스프링 빈으로 등록해서 사용해야 얻는 이점이 많다.

 

이 상태에서 프로젝트를 실행하면 MemberService를 찾을 수 없다는 오류가 발생한다.

이유는 helloController는 스프링 컨테이너에 등록이 되지만, MemberService에는 스프링이 Service임을 알 수 있는 코드가 존재하지 않아서 @Service 애너테이션을 추가해주면 된다.

 

또한 Repository에도 @Repository 애너테이션을 추가함으로써 리포지토리라는 것을 스프링 컨테이너가 알 수 있게 해준다.

 

컨트롤러에서 외부 요청을 받고, 서비스에서 비즈니스 로직을 만들고, 리포지토리에서 저장소에 저장을 하는 것은 이미 정형화 된 방법으로 많이 사용하고 있다.

 

생성자에 @Autowired 가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어준다. 이렇게
객체 의존관계를 외부에서 넣어주는 것을 DI (Dependency Injection), 의존성 주입이라 한다.

이와같이 컨트롤러, 서비스, 리포지토리가 연결이 되는 과정을 거치고 나면 성공적으로 실행이 잘 되는 것을 볼 수 있다.

 

728x90