반응형

마이크로서비스 아키텍처(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대 장점
- 테스트 용이성: Mock 객체를 이용한 단위 테스트 간소화
- 코드 재사용: 컴포넌트의 독립적 활용 가능
- 유지보수성: 구현체 변경 시 영향 범위 최소화
- 설계 유연성: DIP(의존 역전 원칙) 준수를 통한 확장성 향상
결론: MSA에서 DI는 생명선
의존성 주입은 마이크로서비스의 독립성과 탄력성을 보장하는 핵심 메커니즘입니다.
- 생성자 주입을 기본으로 한 명시적 의존성 관리
- 인터페이스 추상화를 통한 결합도 최소화
- 순환 참조 문제 사전 방지 설계
이 원칙들을 준수하면 복잡한 MSA 환경에서도 견고한 서비스 아키텍처를 구축할 수 있습니다.
[MSA] 객체 관리와 설계 의존성 주입
마이크로서비스 아키텍처(MSA)에서 의존성 주입(Dependency Injection, DI)은 객체 간의 결합도를 ...
blog.naver.com
[MSA] 스테레오타입 어노테이션을 활용한 스프링 빈 설정
마이크로서비스 아키텍처(MSA)에서는 각 서비스의 모듈화와 관심사 분리가 핵심입니다.스프링 프레임워크의 스테레오타입 어노테이션은 클래스의 역할을 명시적으로 정의하고,의존성 주입(DI)
hoosfa.tistory.com
반응형
'IT기술 > MSA (with. springboot)' 카테고리의 다른 글
| Spring Bean Scope 완벽 가이드: MSA 환경에서의 객체 생명주기 관리 (0) | 2025.07.04 |
|---|---|
| Spring Framework ApplicationContext 완벽 가이드: MSA 환경에서의 핵심 컨테이너 활용법 (0) | 2025.07.04 |
| [MSA] 스테레오타입 어노테이션을 활용한 스프링 빈 설정 (0) | 2025.04.29 |
| [MSA] 스프링 빈 자바(JAVA) 설정 – @Configuration, @ComponentScan, @Import 완벽 이해 (2) | 2025.04.28 |
| [MSA] 스프링 빈 사용: 설정, 관리, 모범 사례 (2) | 2025.04.27 |