IT기술/MSA (with. springboot)

MSA 환경에서 스프링 의존성 주입(DI)의 핵심 전략

후스파 2025. 4. 30. 17:17
반응형

msa service springboot

마이크로서비스 아키텍처(MSA)에서는 서비스 간 낮은 결합도높은 유연성이 필수적입니다.
의존성 주입(Dependency Injection, DI)은 이를 실현하는 핵심 기술로,
객체 생성·관리 책임을 외부 컨테이너에 위임함으로써 테스트 용이성과 유지보수성을 극대화합니다.

 


 

1. 의존성 주입의 3대 구현 방식

 

1.1 생성자 주입 (권장)

@Service  
public class OrderService {  
    private final PaymentClient paymentClient;  

    // @Autowired 생략 가능 (Spring 4.3+)  
    public OrderService(PaymentClient paymentClient) {  
        this.paymentClient = paymentClient;  
    }  
}  
  • 장점:
    • 객체 불변성 보장 (final 키워드 사용 가능)
    • 순환 의존성 문제 조기 발견 (컴파일 타임 에러)
    • 테스트 시 Mock 객체 주입 용이

 

1.2 Setter 주입

@Service  
public class InventoryService {  
    private ProductRepository productRepository;  

    @Autowired  
    public void setProductRepository(ProductRepository productRepository) {  
        this.productRepository = productRepository;  
    }  
}  
  • 사용 시나리오:
    • 선택적 의존성
    • 런타임 시 동적 교체 필요 시

 

1.3 필드 주입

@Service  
public class NotificationService {  
    @Autowired  
    private EmailSender emailSender;  
}  
  • 주의점:
    • 테스트 시 Reflection API 필요
    • 순환 참조 문제 늦게 발견 (런타임 에러)

 


 

2. MSA 환경에서의 DI 활용 전략

 

2.1 인터페이스 기반 추상화

public interface PaymentGateway {  
    void process(PaymentRequest request);  
}  

@Service  
public class StripePayment implements PaymentGateway { ... }  

@Service  
public class OrderService {  
    private final PaymentGateway paymentGateway;  
}  
  • 장점: 결제 시스템 교체 시 OrderService 코드 변경 불필요

 

2.2 @Qualifier를 이용한 다중 빈 관리

# application.yml  
payment:  
  default-provider: paypal  
@Bean  
@Qualifier("stripe")  
public PaymentGateway stripePayment() { ... }  

@Bean  
@Qualifier("paypal")  
public PaymentGateway paypalPayment() { ... }  

 

2.3 Configuration 클래스에서 명시적 주입

@Configuration  
public class ServiceConfig {  
    @Bean  
    public OrderService orderService(  
        @Qualifier("circuitBreaker") PaymentGateway paymentGateway  
    ) {  
        return new OrderService(paymentGateway);  
    }  
}  

 


 

3. 순환 의존성(Circular Dependency) 문제 해결

 

3.1 문제 발생 시나리오

@Service  
public class ServiceA {  
    private final ServiceB serviceB;  
    public ServiceA(ServiceB serviceB) { ... }  
}  

@Service  
public class ServiceB {  
    private final ServiceA serviceA;  
    public ServiceB(ServiceA serviceA) { ... }  
}  

BeanCurrentlyInCreationException 발생

 

3.2 해결 방법 3가지

  • @Lazy 어노테이션 활용
@Service  
public class ServiceB {  
    private final ServiceA serviceA;  
    public ServiceB(@Lazy ServiceA serviceA) { ... }  
}
  • 인터페이스 계층 분리
public interface CommonService { ... }  

@Service  
public class ServiceA implements CommonService {  
    private final CommonService commonService;  
}
  • 설계 재검토
    • 공통 기능을 제3의 서비스(예: EventPublisher)로 분리
    • CQRS 패턴 적용: Command/Query 책임 분리

 


 

4. MSA 환경에서의 DI 최적화

 

4.1 모듈별 독립적 빈 관리

@SpringBootApplication  
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})  
public class OrderServiceApplication { ... }

 

4.2 조건부 빈 등록

@Bean  
@ConditionalOnProperty(name = "cache.enabled", havingValue = "true")  
public CacheManager redisCache() { ... }  

 

4.3 프로파일별 구성

@Profile("dev")  
@Configuration  
public class DevConfig { ... }  

 

 


 

5. 의존성 주입의 4대 장점

  1. 테스트 용이성: Mock 객체를 이용한 단위 테스트 간소화
  2. 코드 재사용: 컴포넌트의 독립적 활용 가능
  3. 유지보수성: 구현체 변경 시 영향 범위 최소화
  4. 설계 유연성: DIP(의존 역전 원칙) 준수를 통한 확장성 향상

 


 

결론: MSA에서 DI는 생명선

의존성 주입은 마이크로서비스의 독립성탄력성을 보장하는 핵심 메커니즘입니다.

  • 생성자 주입을 기본으로 한 명시적 의존성 관리
  • 인터페이스 추상화를 통한 결합도 최소화
  • 순환 참조 문제 사전 방지 설계

이 원칙들을 준수하면 복잡한 MSA 환경에서도 견고한 서비스 아키텍처를 구축할 수 있습니다.

 

 

[MSA] 객체 관리와 설계 의존성 주입

마이크로서비스 아키텍처(MSA)에서 의존성 주입(Dependency Injection, DI)은 객체 간의 결합도를 ...

blog.naver.com

 

 

[MSA] 스테레오타입 어노테이션을 활용한 스프링 빈 설정

마이크로서비스 아키텍처(MSA)에서는 각 서비스의 모듈화와 관심사 분리가 핵심입니다.스프링 프레임워크의 스테레오타입 어노테이션은 클래스의 역할을 명시적으로 정의하고,의존성 주입(DI)

hoosfa.tistory.com

 

반응형