WEB

스프링 의존성 주입에 관하여

쥬쥬코드 2024. 10. 27. 16:18

스프링의존성 주입에 대해 알아보기 전에,

먼저 계층 구조에 대해 다시 확인하고 가보자.

보통 스프링에서 개발을 진행할 때, Controller, Service, Repository 이렇게 계층을 나누어 개발한다.

Controller가 Service를, Service가 Repository를 관여하는 방식이다.

 

각각의 계층을 작성시 코드위에 @Controller, @Service, @Repository 어노테이션을 달아주는데, 이때 어노테이션의 역할은 해당 파일을 스프링 빈으로 등록하겠다는 의미이다.

@Controller	// 아래 코드를 컨트롤러로 스프링 컨테이너에 등록하겠다는 의미
public class MemberController {

    private final MemberService memberService;

    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}

 

스프링에는 스프링 컨테이너라고 스프링을 관리해주는 친구가 있는데, 

스프링 동작 방식

간단하게 보자면 위 그림처럼 스프링 부트 안에 스프링 컨테이너가 존재하고 초록색 동그라미(?)들이 들어있다

저 초록색 동그라미가 스프링 빈으로 등록한 친구들이다.

 

위 코드의 경우 현재 MemberController를 스프링 빈으로 등록했다.

마찬가지로 서비스와 레포지토리 둘다 등록해야한다.

 

이걸 왜 등록 하느냐?

여러 컨트롤러에서 하나의 서비스 파일을 사용할 경우, 객체를 계속 새로 생성해서 사용한다면, 비효율적이기 때문에, 스프링 컨테이너에 하나의 빈으로 등록하여 필요할때마다 꺼내서 쓰는 방식으로 사용하기 위해서이다.

 

어노테이션을 통해 등록을 하게되면 저 스프링 컨테이너에 빈으로 올라가게 되고,

필요할때마다 꺼내서 외부에서 연결을 해줘야한다. 

이렇게 객체 의존관계를 외부에서 넣어주는 것이 바로 의존성 주입 (dependency Injection)이다.

 @Autowired
 public MemberController(MemberService memberService) {
 	this.memberService = memberService;
 }

이 코드는 아까 위의 코드 내부에 있던 membercontroller 생성자인데, service를 외부에서 받아 등록하고 있다.

이때 위에 @Autowired를 작성해주면 스프링이 연관된 객체(여기선 memberservice)를 스프링 컨테이너에서 찾아서 넣어준다.(DI)

 

@Autowired로 연결을 해줄 때에는 해당 객체가 스프링 빈에 등록되어있어야한다.

 

 

스프링 빈을 설정하는 방식에는 크게 두가지가 있다.

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

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

 

1번 방식이 여태까지 알아본 @Controller, @Service, @Repository 와 같이 어노테이션을 이용하여 자동으로 스프링 빈 설정 방식이다.

 

컴포넌트 스캔 원리

@Component 어노테이션이 있으면 스프링 빈으로 자동 등록 되는데, @Controller, @Service, @Repository 이 어노테이션들에는 @Component 어노테이션이 포함되어있기 때문이다.

 

그렇다면 2번은 어떻게 하는걸까?

@Service, @Repository를 모두 제거하고, 해당 파일의 @Autowired도 제거한 다음, 따로 config 파일을 만들어서, 거기에서 service와 repository 파일을 빈으로 등록해준다.

@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository(){
        return new MemoryMemberRepository();
    }
}

 

참고로 컨트롤러는 config 파일에 등록 X, @Controller 어노테이션으로 등록한다.

멤버 서비스에서 멤버 리포지토리로 연결을 해주어야하므로 애초에 빈을 생성할때 멤버 리포지토리를 꽂아서 생성해준다. -> 따라서 Service에서는 AutoWired가 필요 없음

 

참고로 DI에는 세가지 방식이 있다.

1. 필드 주입,

2. setter 주입,

3. 생성자 주입

 

보통 3번 방식으로 많이 한다.

생성자 주입은 private으로 막아둬서 처음에 주입하고 바꿀 일이 없지만, 1,2번 방식은 다른 누군가가 쉽게 바꿔버릴수 있기 때문이다. 의존관계가 실행중에 동적으로 변하는 경우는 거의 없으므로 3번 방식으로 한다.

 

아까 스프링 빈 설정 방식에는 두가지가 있다고 했는데 실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 첫번째 방식(컨포넌트 스캔)을 사용한다고 한다.

그리고 정형화 되지 않거나, 

예를 들어 DB가 아직 정해지지 않은 상황 등 상황에 따라 구현 클래스를 변경해야 하면,

2번째 방법(설정을 통해)으로 스프링 빈으로 등록한다.

 

 

 

'WEB' 카테고리의 다른 글

스프링 객체지향과 다형성  (0) 2024.11.25
서블릿(Servlet)  (0) 2024.11.15
[Tomcat] Web Server와 WAS, Apache Tomcat  (8) 2024.11.10
[pandas] csv 데이터 api 연동, 처리  (2) 2024.11.03
[JWT]쿠키/세션/JWT 비교, jwt 구현 (nodejs)  (0) 2024.10.29