JAVA/Spring

Spring 의존성 주입: 생성자 주입과 수정자 주입의 동작 원리

min민 2024. 12. 21.

Spring 의존성 주입: 생성자 주입과 수정자 주입의 동작 원리

Spring을 사용하다 보면 의존성 주입(Dependency Injection)이라는 개념을 반드시 접하게 된다. 이는 객체 간의 의존성을 관리하고 설정하는 강력한 기능으로, 코드의 유연성과 테스트 가능성을 크게 향상시킨다. Spring에서는 의존성을 주입하는 방식으로 생성자 주입(Constructor Injection), 수정자 주입(Setter Injection), 그리고 **필드 주입(Field Injection)**을 제공한다. 이번 글에서는 생성자 주입수정자 주입이 함께 사용될 경우의 동작 원리와 각 주입 방식의 특징을 설명한다.

 

 

 

 

의존성 주입 방식의 종류

디테일한 공부를 원하면 아래 링크도 참고하면 좋다!

https://mininkorea.tistory.com/76

 

DI(의존관계 주입, Dependency Injection)란 무엇인가?

DI(의존관계 주입, Dependency Injection)란 무엇인가? 의존관계 주입(Dependency Injection, DI)은 객체 간의 의존성을 외부에서 주입받는 설계 방식을 말한다.이 방식은 객체를 직접 생성하거나 내부에서 의

mininkorea.tistory.com

 

1. 생성자 주입(Constructor Injection)

생성자 주입은 객체의 생성자를 통해 의존성을 전달받는 방식이다. 주입이 필수적인 의존성일 때 가장 적합하다. Spring 컨테이너는 객체를 생성할 때 생성자를 호출하며, 이 과정에서 의존성을 주입한다.

생성자 주입의 가장 큰 장점은 객체 생성 시 필수 의존성을 보장할 수 있다는 점이다. 또한, 주입된 의존성을 변경할 수 없기 때문에 불변 객체(Immutable Object)를 만들기에도 적합하다.

 

 

 

 

2. 수정자 주입(Setter Injection)

수정자 주입은 setter 메서드를 통해 의존성을 주입하는 방식이다. 선택적인 의존성이 필요한 경우나 객체 생성 후 추가적으로 설정해야 할 작업이 있을 때 주로 사용된다. Spring 컨테이너는 객체를 생성한 후, setter 메서드를 호출하여 의존성을 주입한다.

 

 

 

 

3. 필드 주입(Field Injection)

필드 주입은 클래스의 필드에 직접 의존성을 주입하는 방식이다. @Autowired 또는 @Inject를 필드에 붙여 간단히 사용할 수 있다. 그러나 테스트와 유지보수성이 떨어지고, 주입된 의존성을 명확히 확인하기 어렵기 때문에 권장되지 않는 방식이다.

 

 

 

 

생성자 주입과 수정자 주입의 동작 순서

Spring에서 생성자 주입수정자 주입을 함께 사용할 경우, 다음과 같은 순서로 동작한다:

  1. Spring 컨테이너가 객체를 생성한다.
    • 이때 생성자가 호출되며, 생성자 주입이 적용된다. 필수적인 의존성은 이 단계에서 초기화된다.
  2. Spring 컨테이너가 수정자 주입을 적용한다.
    • 객체 생성 후, setter 메서드를 호출하여 추가적인 의존성을 주입한다.

즉, 생성자 주입이 먼저 실행되고, 그 이후에 수정자 주입이 실행된다.

 

 

코드 예제

다음은 생성자 주입과 수정자 주입을 함께 사용하는 간단한 예제이다.

MyService 클래스

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyService {

    private final DependencyA dependencyA; // 생성자 주입
    private DependencyB dependencyB;       // 수정자 주입

    // 생성자 주입
    @Autowired
    public MyService(DependencyA dependencyA) {
        this.dependencyA = dependencyA;
        System.out.println("생성자 주입: DependencyA가 주입되었습니다.");
    }

    // 수정자 주입
    @Autowired
    public void setDependencyB(DependencyB dependencyB) {
        this.dependencyB = dependencyB;
        System.out.println("수정자 주입: DependencyB가 주입되었습니다.");
    }

    public void doSomething() {
        System.out.println("DependencyA: " + dependencyA.getName());
        System.out.println("DependencyB: " + dependencyB.getName());
    }
}

 

의존성 클래스 정의

import org.springframework.stereotype.Component;

@Component
public class DependencyA {
    public String getName() {
        return "DependencyA";
    }
}

@Component
public class DependencyB {
    public String getName() {
        return "DependencyB";
    }
}

 

 

동작 과정

Spring 컨테이너가 MyService를 초기화할 때, 다음과 같은 순서로 동작한다.

 

1. 생성자 주입이 실행된다. DependencyA가 생성자를 통해 주입된다.

생성자 주입: DependencyA가 주입되었습니다.

 

 

2. 수정자 주입이 실행된다. DependencyB가 setter 메서드를 통해 주입된다.

수정자 주입: DependencyB가 주입되었습니다.

 

3. 의존성 주입이 완료된 후, doSomething() 메서드를 실행하면 다음과 같은 결과를 얻을 수 있다.

DependencyA: DependencyA
DependencyB: DependencyB

 

 

 

 

 

생성자 주입과 수정자 주입의 차이점

구분 생성자 주입 수정자 주입
적합한 경우 필수 의존성 주입 시 사용 선택적 의존성 주입 시 사용
주입 시점 객체 생성 시 의존성 주입 객체 생성 후 setter를 통해 주입
장점 - 필수 의존성 보장
- 불변 객체 생성 가능
- 유연한 의존성 주입
- 선택적 의존성 설정 가능
의존성이 많아지면 생성자의 파라미터가 많아질 수 있음 객체가 완전히 초기화되기 전 의존성 누락 가능성

 

 

 

 

 

 

 

생성자 주입이 먼저 실행되고 수정자 주입이 나중에 실행되는 이유

Spring이 생성자 주입을 먼저 처리하고 수정자 주입을 나중에 적용하는 이유는 다음과 같다.

  1. 필수 의존성 보장
    • 생성자 주입은 객체 생성 시 필수적인 의존성을 보장한다. 만약 필요한 의존성이 없으면 객체 생성이 실패하므로, 잘못된 구성을 즉시 확인할 수 있다.
  2. 추가적인 설정 작업
    • 수정자 주입은 선택적 의존성이나 객체 생성 후 필요한 추가 설정 작업을 처리하기 위해 사용된다. 객체를 생성한 후, 필요한 부분만 유연하게 설정할 수 있다.

 

 

 

 

총 정리

Spring에서 의존성 주입은 객체의 필수 의존성과 선택적 의존성을 명확히 구분하고, 이를 효율적으로 관리할 수 있는 방법을 제공한다. 생성자 주입은 필수 의존성을 안전하게 보장하며 불변성을 유지하는 데 적합하다. 반면에 수정자 주입은 객체 생성 후 추가적인 설정이 필요한 경우 유용하다.

Spring의 의존성 주입 메커니즘을 이해하고 올바르게 사용하는 것은, 견고하고 유지보수하기 쉬운 코드를 작성하는 데 필수적이다. 특히, 생성자 주입과 수정자 주입의 동작 순서를 명확히 이해하면 보다 안정적인 애플리케이션을 설계할 수 있다.

댓글