개발/Spring

Spring @Primary와 @Qualifier 어노테이션 쉽게 이해하기

피터JK 2025. 2. 11. 11:41
728x90

Spring에서는 하나의 인터페이스를 여러 개의 구현체가 가질 수 있습니다.
이때, 특정 구현체를 선택해서 사용할 수 있도록 도와주는 것이 @Primary와 @Qualifier 어노테이션입니다.
이번 글에서는 두 어노테이션의 차이와 사용법을 쉽게 설명하겠습니다.


1. @Primary 어노테이션

@Primary는 동일한 타입의 빈이 여러 개 존재할 때, 우선적으로 선택할 빈을 지정하는 어노테이션입니다.

✅ 예제 코드

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

interface Printer {
    void print();
}

@Component
@Primary // 기본적으로 선택될 빈 지정
class LaserPrinter implements Printer {
    @Override
    public void print() {
        System.out.println("레이저 프린터 출력");
    }
}

@Component
class InkjetPrinter implements Printer {
    @Override
    public void print() {
        System.out.println("잉크젯 프린터 출력");
    }
}

✅ @Primary 적용 시 동작

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

@Component
class PrintService {
    private final Printer printer;

    @Autowired
    public PrintService(Printer printer) {
        this.printer = printer;
    }

    public void doPrint() {
        printer.print();
    }
}

위 코드에서 PrintService는 Printer 타입의 빈을 자동 주입받습니다. LaserPrinter가 @Primary로 지정되었으므로 자동으로 선택됩니다.

✅ 실행 결과

레이저 프린터 출력

2. @Qualifier 어노테이션

@Qualifier는 특정한 빈을 명시적으로 선택할 때 사용합니다. @Primary가 설정되어 있어도 @Qualifier를 사용하면 지정된 빈이 우선됩니다.

✅ @Qualifier 적용 예제

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

@Component
class QualifierPrintService {
    private final Printer printer;

    @Autowired
    public QualifierPrintService(@Qualifier("inkjetPrinter") Printer printer) {
        this.printer = printer;
    }

    public void doPrint() {
        printer.print();
    }
}

✅ 실행 결과

잉크젯 프린터 출력

3. @Primary vs @Qualifier 차이점

어노테이션  동작 방식
@Primary 기본적으로 선택될 빈을 지정할 때 사용
@Qualifier 특정한 빈을 명시적으로 지정할 때 사용
  • @Primary는 우선 순위를 부여하는 방식, @Qualifier는 명확하게 지정하는 방식입니다.
  • @Qualifier가 사용되면 @Primary는 무시됩니다.

4. @Primary와 @Qualifier 함께 사용하기

@Primary는 기본 선택 빈을 정할 때 유용하지만, 특정 상황에서 다른 빈을 선택하고 싶을 수도 있습니다. 그럴 때 @Qualifier를 함께 사용하면 더욱 유연한 설정이 가능합니다.

✅ 예제 코드

@Component
@Primary
class DefaultPrinter implements Printer {
    @Override
    public void print() {
        System.out.println("기본 프린터 출력");
    }
}

@Component("fastPrinter")
class FastPrinter implements Printer {
    @Override
    public void print() {
        System.out.println("빠른 프린터 출력");
    }
}

@Component
class MixedPrintService {
    private final Printer printer;

    @Autowired
    public MixedPrintService(@Qualifier("fastPrinter") Printer printer) {
        this.printer = printer;
    }

    public void doPrint() {
        printer.print();
    }
}

✅ 실행 결과

빠른 프린터 출력

@Primary가 설정된 DefaultPrinter가 있음에도 불구하고, @Qualifier("fastPrinter")를 사용했기 때문에 FastPrinter가 주입되었습니다.


5. 정리

🎯 언제 @Primary를 사용해야 할까?

  • 특정 타입의 빈이 여러 개 있을 때 기본적으로 사용할 빈을 설정할 때.
  • 같은 인터페이스의 여러 구현체 중 가장 많이 사용하는 빈을 지정할 때.

🎯 언제 @Qualifier를 사용해야 할까?

  • 특정한 구현체를 명확하게 지정해야 할 때.
  • @Primary가 설정된 빈이 있지만 다른 빈을 선택해야 할 때.
  • 동일한 인터페이스의 여러 개의 구현체를 상황에 따라 다르게 주입해야 할 때.

6. 마무리

@Primary와 @Qualifier는 Spring에서 의존성 주입 시 특정 빈을 선택하는 방법입니다. 기본적으로 @Primary를 활용하고, 특정한 빈을 선택해야 할 경우 @Qualifier를 사용하면 됩니다. 상황에 맞게 두 어노테이션을 적절히 조합하여 사용하면, 더욱 유연한 Spring 애플리케이션을 만들 수 있습니다. 😊

728x90