본문 바로가기
IT개발/Spring Framework

스프링 DI(Dependency Injection)

by 시간기억자 2025. 3. 27.
반응형

스프링을 사용하면 객체 간의 의존성을 관리하는 방식이 기존의 Java 코드와 다르다.
특히, **의존성 주입(DI, Dependency Injection)**은 스프링의 핵심 개념 중 하나이며, 이를 통해 객체 간의 결합도를 낮추고 유지보수를 쉽게 만들 수 있다.


✅ 의존성(Dependency)이란?

객체 A가 객체 B를 사용해야 할 때, A는 B에 **의존(Dependency)**한다고 말할 수 있다.
예를 들어, MemberService 클래스에서 MemberRepository 클래스를 사용한다고 가정해 보자.

public class MemberService {
    private MemberRepository memberRepository = new MemberRepository();
}

 

위 코드에서는 MemberService가 MemberRepository를 직접 생성하고 있다.
이 방식은 클래스 간의 결합도가 높아지기 때문에, MemberRepository의 변경이 필요할 경우 MemberService도 함께 수정해야 한다.

이러한 문제를 해결하기 위해 DI(Dependency Injection) 개념이 등장했다.


✅ DI(의존성 주입)이란?

DI는 객체를 직접 생성하는 것이 아니라 외부에서 주입받는 방식을 의미한다.
즉, 클래스가 필요로 하는 객체를 직접 생성하는 것이 아니라, 스프링 컨테이너가 대신 생성하고 주입해 준다.

@Service
public class MemberService {
    private final MemberRepository memberRepository;

    @Autowired  // 의존성 자동 주입
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
}

 

위 코드에서 MemberRepository 객체는 new 키워드로 직접 생성되지 않는다.
대신, @Autowired 어노테이션을 통해 스프링 컨테이너가 자동으로 주입해 준다.
이렇게 하면 MemberService는 MemberRepository의 변경에 영향을 받지 않고 독립적으로 동작할 수 있다.

 


✅ DI의 주요 장점

1️⃣ 결합도 감소 → 클래스 간의 의존성을 줄여 유지보수가 쉬워진다.
2️⃣ 객체 관리 자동화 → 스프링이 객체를 자동으로 생성하고 주입해 준다.
3️⃣ 테스트 용이 → Mock 객체를 활용하여 단위 테스트가 쉬워진다.
4️⃣ 유연한 설정 가능 → XML, Java Config, 어노테이션 방식 등 다양한 설정 방법을 지원한다.


✅ DI(의존성 주입)의 종류

DI에는 크게 생성자 주입, 필드 주입, 세터 주입 3가지 방식이 있다.

1️⃣ 생성자 주입 (Constructor Injection) - 가장 권장되는 방식

생성자를 통해 필요한 객체를 주입하는 방식이다.

@Service
public class MemberService {
    private final MemberRepository memberRepository;

    @Autowired
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
}

 

📌 장점
✅ 객체가 반드시 주입되도록 보장할 수 있다.
✅ final 키워드를 사용할 수 있어 불변성을 유지할 수 있다.
✅ 테스트 시 Mock 객체를 쉽게 주입할 수 있다.


2️⃣ 필드 주입 (Field Injection) - 권장되지 않음

필드에 직접 @Autowired 어노테이션을 붙여 의존성을 주입하는 방식이다.

@Service
public class MemberService {
    @Autowired
    private MemberRepository memberRepository;
}

 

📌 단점
❌ 테스트 시 Mock 객체를 주입하기 어렵다.
❌ 순환 참조 문제가 발생해도 실행 전에는 알기 어렵다.
❌ 객체 변경이 불가능하다.

👉 필드 주입 방식은 사용을 지양하는 것이 좋다.


3️⃣ 세터 주입 (Setter Injection) - 선택적 의존성 주입 가능

Setter 메서드를 통해 의존성을 주입하는 방식이다.

@Service
public class MemberService {
    private MemberRepository memberRepository;

    @Autowired
    public void setMemberRepository(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
}

 

📌 장점
✅ 의존성을 선택적으로 변경할 수 있다.
✅ 순환 참조 문제를 피할 수 있다.

 

📌 단점
❌ 불필요한 setter 메서드가 추가될 가능성이 있다.
❌ 변경이 많지 않은 객체라면 불필요한 코드가 될 수 있다.


✅ DI와 함께 알아두면 좋은 개념

개념 설명
IoC (Inversion of Control)
제어의 역전. 객체 생성을 개발자가 아닌 스프링 컨테이너가 관리
Bean
스프링이 관리하는 객체. @Component, @Service, @Repository 등을 사용해 등록
ApplicationContext
스프링 컨테이너의 핵심 인터페이스
@Autowired
자동 의존성 주입을 위한 어노테이션
@Qualifier
동일한 타입의 여러 빈이 있을 때, 특정 빈을 선택할 때 사용

 


스프링 DI(Dependency Injection)는 스프링 프레임워크의 가장 중요한 개념 중 하나다.
의존성 주입을 활용하면 객체 간의 결합도를 줄이고, 유지보수성을 높이며, 테스트가 쉬워진다.
특히, 생성자 주입 방식이 가장 권장되며, 필드 주입은 지양하는 것이 좋다.

 

 

 

반응형

댓글