티스토리 뷰

스프링

DI(Dependency Injection) - 의존주입

김쓰로그 2022. 8. 17. 14:34

스프링 책을 보거나 또는 인터넷 검색을 했을 때 가장 많이 나오는 키워드, 중요한 키워드가

 DI(Dependency Injection)이다.

 

나는 DI 개념이 처음에 굉장히 어려웠다. 이걸 왜 하는 걸까? 하면 어떠한 효과를 보기에 DI라는 것이 대단하다고 불리는 걸까?

 

예제로 다음과 같이 간단히 코드를 작성해 보았다.

 

<Member>

public class Member {

    private String id;
    private String password;

    public Member(String id, String password) {
        this.id = id;
        this.password = password;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

<MemoryMemberRepository> - 내장 메모리 사용 Map자료구조를 이용

public class MemoryMemberRepository implements MemberRepository{

    private Map<String, Member> store = new HashMap<>();

    @Override
    public void save(Member member) {
        store.put(member.getId(), member);
    }

    @Override
    public Member findById(String memberId) {
        return store.get(memberId);
    }
}

<MemberServiceImpl>

public class MemberServiceImpl implements MemberService {

    private MemoryMemberRepository memberRepository = new MemoryMemberRepository();

    public MemberServiceImpl(MemoryMemberRepository memoryMemberRepository) {
        this.memberRepository = memoryMemberRepository;
    }

    @Override
    public void join(Member member) {
        memberRepository.save(member);
    }

    @Override
    public Member findMember(String memberId) {
        return memberRepository.findById(memberId);
    }
}

위의 코드에서 중요하게 볼 부분은 MemberServiceImpl 클래스이다. 

해당 클래스는 MemoryMemberRepository에 의존하고 있다. 만약 repository 객체가 바뀐다면 코드를 수정해줘야하는데 당장에는 간단해 보이지만 코드가 길어지고 repository 객체를 이용하는 클래스가 많아진다면 수정하기 굉장히 힘들어진다.

 

내가 앞서 작성한 글에서 다형성에 대해 작성한 부분이 있는데 역할과 구현을 분리하여 코드를 작성해야 한다고 하였다. 즉, 역할에는 의존하되 구현에는 의존받지 않아야한다.

 

그래서 아래와 같이 변경할 수 있는데 하지만 인터페이스뿐만 아니라 구현 클래스에도 의존하고 있다.

private MemberRepository memberRepository = new MemoryMemberRepository();

다른 저장방식을 사용하고 싶어 클래스를 바꾸고자 한다면 MemberRepositoryImpl 코드를 변경해야 한다. 그래서 결국은 인터페이스만 의존하도록 변경해야 한다.

private MemberRepository memberRepository;

 

위 코드와 같이 변경하면 인터페이스에만 의존하는 것이다.

 

그럼 저렇게 고친 클래스는 구현체도 없는데 어떻게 쓸까?

그때 사용하는 것이 DI 의존주입이다. 즉, 외부에서 사용할 객체를 넣어주는 것이다.

private MemberRepository memberRepository;

public MemberServiceImpl(MemoryMemberRepository memoryMemberRepository) {
    this.memberRepository = memoryMemberRepository;
}

위의 코드와 같이 생성자를 통해 외부에서 전달한 객체를 내부 변수에 넣어주는 것이다.

그럼 어디서 구현 객체르르 생성하고, 연결을 할까? 이에 대한 책임을 가지는 별도의 설정 클래스를 생성하면 된다.

 

public class Appconfig {

    public MemberService memberService(){
        return new MemberServiceImpl(new MemoryMemberRepository());
    }
    
}

이렇게 해주면 MemberServiceImpl 입장에서는 자기가 가지고 있는 변수에 어떠한 객체가 들어올지 모른다. 

어떠한 객체가 들어올지는 오직 AppConfig 클래스에서 결정한다. 

 

결국 이러한 의존관계는 외부 맞기고 자기자신은 실행에만 집중할 수 있게 된다.

 

이렇듯 MemberServiceImpl의 입장에서 보면 의존관계를 외부에서 주입해주는 것 같다고 해서 의존주입(Denpendency Injection), DI라고 부르는 것이다.

 

스프링에서는 이러한 작업을 Annotation과 스프링 컨테이너를 활요하여 정말 쉽게 할 수 있게 만들어준다. 

위의 코드는 스프링의 기능을 단 하나도 사용하지않고 의존주입을 사용한 코드이다.

 

오늘은 의존주입이 어떤 것이고 왜 해야하는지 간단하게 정리했다. 다음에는 스프링에서 어떠한 방식으로 의존주입을 하는지 정리해야겠다.

 

 

- 저의 공부했던 내용을 정리하는 블로그입니다. 틀린 부분이 있다면 강력한 피드백 부탁드립니다. -

'스프링' 카테고리의 다른 글

@RequestBody 데이터 검증하기  (0) 2022.11.04
Spring Controller에서 사용하는 여러 어노테이션  (0) 2022.08.23
JSP와 MVC패턴??  (0) 2022.08.21
Servlet HTTP 요청데이터와 응답데이터  (0) 2022.08.19
스프링(Spring)?  (0) 2022.08.16
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함