스프링 입문 - 섹션4 스프링 빈과 의존관계
CS/김영한 스프링 강의

스프링 입문 - 섹션4 스프링 빈과 의존관계

일단 의존관계가 뭐고 왜 나오는지 부터 생각하자.

 

public class MemberService {

    MemberService memberService = new MemberService();
    MemoryMemberRepository memberRepository = new MemoryMemberRepository();

    // ...
}

서비스에서 레퍼지토리 객체를 직접 만드는 식으로 하면, 다른 서비스에서도 새로 만들면 서로 다른 데이터베이스(레퍼지토리)를 볼 수 있는 일이 생긴다. 그래서 꼬일 수 있으니 하나만 보게 하기 위함. 또 어차피 같은 일을 하니 하나만 만들어서 계속 쓰는 의미도 있음. 이를 싱글톤이라고 함.

 

 

의존관계는 해당 기능을 원하는 클래스가 그 클래스의 인스턴스를 주입 받아서 사용하는 것으로 설계됨. 이래야 다른 서비스에도 그 클래스의 하나의 인스턴스를 받아서 같은 인스턴스 가지고 할 수 있도록 조절할 수 있으니까. 처음 실행해서 만들어진 뒤에 변경이 일어나지 않게끔(변수 없애기) 생성자에서 받도록 만드는게 보통이다. 생성자 말고도 세터로 등록하는 방법, 변수에서 @Autowired로 등록하는 방법이 있는데, 다른곳에서 변형시킬 수 있고, 내가 원하는대로 못 바꿔서 거의 안사용함.

public class MemberService {

    MemberService memberService = new MemberService();

    private final MemoryMemberRepository memberRepository;
    public MemberService() {
        memberRepository = new MemoryMemberRepository();
    }

    // ...
}

 

이렇게 이어받는걸 다음과 같이 다이어그램으로 그릴 수 있음(이래서 4학년때 배운다.).

 

이 의존관계 주입을 @Autowired를 사용하면 스프링이 알아서 해주는 것. 그럼 스프링 컨테이너 안에 Bean으로 등록된 객체를 찾아 스프링이 알아서 넣어준다. 넣는다는 것은 스프링 컨테이너 안에 넣어준다는 것이고, 스프링 빈으로 등록한다고 함.

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

 

내가 원하는 객체를 스프링 컨테이너 안에 넣는 방법 즉, 빈으로 등록하는 방법은 2가지가 있는데, 컴포넌트 스캔과 자동 의존관계 설정, 자바 코드로 직접 등록하는 방법임. 둘 다 @SpringBootApplication가 포함되어 있는 패키지에 포함되어야 함.

 

컴포넌트 스캔은 저 @SpringBootApplication가 포함되어 있는 클래스들을 다 돌면서 annotation으로 @Component가 등록되어 있는지 보는거다. @Controller, @Service, @Repository는 @Component들이 이미 정의가 되어있는 특이 케이스들.

직접 등록은 @SpringBootApplication가 포함되어 있는 패키지 위치 아무데나 config 클래스를 만들어 @Bean으로 원하는 클래스를 직접 넣어주면 된다. 직접 등록하면 나중에 독립적으로 수정하기 쉽다는 장점이 있음.

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