의존 주입

2024. 2. 25. 18:01SPRING

MemberService 에서 MemberRepository 를 사용하기 위해서는

1. MemberService 의 인스턴스를 생성한다.

2. MemberRepository 의 인스턴스를 생성한다.

3. MemberService 에서 MemberRepository를 참조하여 접근. 사용한다.

 

의 과정을 거쳐야 한다.

그런데 말입니다.

Service와 Repository가 밀접한 연관을 가지고 있고,

Service가 Repository를 자주 사용한다고 할 때,

Repository를 매번 생성하게 되면 무슨 일이 벌어지게 될까요?

 

이전 테스트 글에서 학습했던 것처럼 테스트의 결과가 다 따로 놀게 될 것입니다.

Sevice를 동작시킬 때 마다 계속해서 새로운 MemberRepository를 생성하기 때문입니다.

private final MemverService memberService = new MemberService();
private final MemberRepository memberRepository = new MemorymemberRepository();

 

이러한 현상을 막고, 항상 동일한 결과를 도출하도록 하기 위해선 어떻게 하면 좋을까요?

답은 단순합니다.

하나의 Repository만 생성해서, 그걸 계속 참조하게 하면 됩니다.

 

그렇다면 그렇게 할 수 있는 방법은?

아래의 예시를 봅시다.

@Controller
public class MemberController {

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

 

MemberController class 를 작성

멤버 변수로 MemberService 를 갖게 합니다.

이 때, private final 키워드를 사용한 이유는 단순합니다.

1. MemberService는 MemberController에서만 사용할 것입니다.

2. Controller는 프로그램을 동작시킬 때 만들고, 더 이상 내용이 변하지 않습니다. (변해도 안 됩니다)

 

그리고, MemberController를 초기화해주는 MemberController() 생성자에 paramater 로 MemberService 를 받게 합니다.

외부에서 생성된 MemberService를 멤버변수로 두기 위함입니다.

 

위에서 말했듯, MemberService는 MemberService에서 사용합니다.

그리고, 내용도 변하지 않을 것입니다.

내용이 변하지 않는다? = 하나의 인스턴스만 계~속해서 참조하겠다는 의미이기도 합니다.

 

이를 통해 MemberController는 단 하나의 MemberService를 참조하게 되었습니다.

 

자. 그럼 그건 알겠고,

어떻게 해야 MemberController에 MemberService의 주소값이 전달될까요?

답은, MemberController 의 생성자 위에 붙인 @AutoWired 에 있습니다.

 

Spring framework 는 프로그램 실행 시,

정해진 범위에서 '스프링 빈' 이라는 것을 탐색합니다.

Class 범위든, Method 범위든 특별한 표식이 있다면 모두 인스턴스화하여 Spring Framework 의 컨테이너에 저장합니다.

 

이후,

Autowired 등의 방식으로 개발자가 해당 클래스에서 필요한 인스턴스의 주입을 맡겼을 때,

Spring이 해당 내용에 맞는 인스턴스를 할당 해주는 것입니다.

이를, 의존 주입(Dependency Injection) 이라 합니다.

 

여기서 주의사항이 있습니다.

스프링에게 의존주입을 위탁하기 위해서는, 너무나 당연하게도

"의존 주입 대상과 의존 주입이 필요한 주체를 스프링이 알아야 합니다."

 

따라서, 개발자는 DI 현상을 발생시킬 클래스들에 표식을 남겨 스프링의 컨테이너에 객체를 등록해야 합니다.

스프링 컨테이너에 등록되는 객체를 '스프링 빈' 이라 합니다.

 

자 이제 여기까진 알겠고,

스프링 컨테이너에 인스턴스를 등록하기 위해선 어떤 표식을 남겨야 할깡?

 

기존에 작성했던 코드 중 MemberController를 봅시다.

@Controller
public class MemberController {

    private final MemberService memberService;

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

@Contorller 애노테이션이 있고,

@Service
public class MemberService {...}

@Service 애노테이션이 있네요.

 

이러한 애노테이션을 통해, 개발자는 Spring framework 에 '스프링 빈'으로 등록할 인스턴스를 알릴 수 있습니다.

이를 토대로 spring framework 는 해당 '스프링 빈' 들을 관리.

서로 의존주입할 수 있도록 해줍니다.

 

MemberController 클래스의 생성자 메서드에 붙은 @Autowired 를 통해 파라미터에 '컨테이너에 등록된 스프링 빈 객체의 주소값을 넣어 줍니다.

 

지금까지 학습했던 내용을 다시 복기 해봅시다.

1. 스프링 프레임워크가 특별한표식( 애노테이션 )을 읽어 '스프링 빈' 객체를 생성한다.

2. 생성된 '스프링 빈' 을 '스프링 컨테이너'에 넣고 관리한다.

3. 특별한 표식(@Autowired 등)을 읽어들여 해당 위치에 필요한 '스프링 빈'객체의 주소값을 할당한다.

 

또, 스프링 빈 객체는 프로그램을 시작할 때 1회 생성되며, 스프링 컨테이너 내에서 중복값을 허용하지 않습니다.

 

따라서, 스프링 컨테이너에는 하나의 클래스, 메서드에서 뽑아낸 '스프링 빈' 객체에 대해 유일성을 보장합니다.

하나의 객체를 계속해서 사용할 수 있게 됩니다.

 

그 결과, 스프링 프레임워크가 대행 해주는 의존주입(Dependency Injection) 을 통해, 동일한 결과를 낼 수 있게 되었습니다. 짞짞짞.

 

==========================

스프링 빈은 중복을 허용하지 않는다고 위에서 언급한 바 있다.

그러나, 실제로는 주입할 때마다 새로운 객체를 넣는 방법도 있다.

하지만 쓸 일이 많지 않다는 모양으로, 꼭 필요하게 되면 그 때 학습 해보도록 하자.

'SPRING' 카테고리의 다른 글

테스트_@Transactional  (0) 2024.02.27
스프링 빈 등록 방법  (0) 2024.02.25
테스트 코드 작성 시의 에로사항  (0) 2024.02.24
웹 개발 방식_API  (0) 2024.02.21
@RequestParam  (0) 2024.02.21