일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 1차원 DP
- 2차원 dp
- 99클럽
- @Builder
- @GeneratedValue
- @GenericGenerator
- @NoargsConstructor
- @Transactional
- Actions
- Amazon EFS
- amazon fsx
- Android Studio
- ANSI SQL
- ApplicationEvent
- assertThat
- async/await
- AVG
- AWS
- Azure
- bind
- builder
- button
- c++
- c++ builder
- c03
- Callback
- case when
- CCW
- chat GPT
- CICD
- Today
- Total
기록
[bug] SpringBoot/The dependencies of some of the beans in the application context form a cycle 본문
[bug] SpringBoot/The dependencies of some of the beans in the application context form a cycle
youngyin 2023. 12. 13. 05:581. 문제 정의:
서비스 간 순환참조로 인해 스프링 부트 애플리케이션 실행 시 빈 초기화에서 순환 의존성 문제 발생.
The dependencies of some of the beans in the application context form a cycle
┌─────┐
| challengeService defined in file
↑ ↓
| couponService defined in file
└─────┘
도메인 서비스 A와 B 간에 의존성이 존재하며, A는 B를 참조하고 B는 A를 참조하면서 순환참조 문제가 발생. 서비스 A는 ChallengeService를, 서비스 B는 CouponService를 참조하고 있음.
2. 고려사항
서비스 간 의존성 그래프를 분석하여 순환참조를 발생시키는 의존성 구조를 확인. 서비스 간의 의존성을 최소화하면서 문제를 해결할 방법을 고려.
// ChallengeService에서 CouponService를 직접 참조하고 있음
class ChallengeService {
private val couponService: CouponService // 순환참조 문제 발생
// ...
}
// CouponService에서 ChallengeService를 직접 참조하고 있음
class CouponService {
private val challengeService: ChallengeService // 순환참조 문제 발생
// ...
}
3. 고려한 해결방법
3.1. 서비스 분리:
CouponService와 ChallengeService를 더 작은 서비스로 분리하여 각각 독립적으로 동작하도록 설계. 이를 통해 순환참조를 방지하고 서비스 간의 명확한 경계를 설정.
3.2. 이벤트 기반 아키텍처 도입:
이벤트를 통해 서비스 간 통신하도록 아키텍처를 변경. ChallengeService에서 발생한 이벤트를 CouponService에서 수신하고 필요한 작업 수행.
// ChallengeService
class ChallengeService {
private val eventBus: EventBus // 이벤트 버스를 통한 통신
fun processChallengeCompletedEvent(challengeId: String) {
// Challenge 완료 이벤트 발행
eventBus.publish(Event(ChallengeCompletedEvent(challengeId)))
}
}
// CouponService
class CouponService {
fun onChallengeCompletedEvent(event: ChallengeCompletedEvent) {
// Challenge 완료 이벤트 수신 및 처리 로직
issueCoupon(event.challengeId)
}
}
4. 해결방법
서비스 분리 방법 선택. ChallengeService와 CouponService를 별도의 마이크로서비스로 분리하여 순환참조 문제를 해결.
4.1 ChallengeReviewService 도입 후의 ChallengeService
@Service
class ChallengeService(
private val converter : ChallengeConverter,
private val repository: ChallengeRepository,
) : BaseService<ChallengeReq, ChallengeResp, Challenge, String> {
fun findAll(searchDto : ChallengeSearchDto, pageable: Pageable): Page<ChallengeResp> {
// 이전 구현 내용과 동일
}
override fun findById(id: String): ChallengeResp {
// 이전 구현 내용과 동일
}
}
4.2 ChallengeReviewService
@Service
class ChallengeReviewService(
private val repository: ChallengeRepository,
private val couponService: CouponService,
) {
fun review(request: ChallengeReviewReq){
// 도전 내역 리뷰 로직
// ...
// 쿠폰 서비스 호출
couponService.save(CouponReq(/*...*/))
}
}
5. 효과와 결과:
서비스 간의 명확한 분리로 순환참조 문제가 사라지고 애플리케이션 초기화 과정에서 발생한 에러가 해결.
6. 기타 고려 사항:
작은 규모의 프로젝트나 단순한 비즈니스 로직을 가진 프로젝트라서, 이벤트 기반 아키텍처를 도입할 필요성이 낮음.
작은 규모의 시스템에서는 단일 모놀리식 아키텍처나 간단한 마이크로서비스 아키텍처가 충분.
'Web > Spring' 카테고리의 다른 글
이미지 처리 및 저장 방법 : 로컬 저장소 업로드/조회/삭제 (0) | 2024.02.05 |
---|---|
API/이미지 처리 및 저장 방법 (0) | 2024.01.29 |
[Spring] Kotlin/Bean Validation 오류 (0) | 2023.11.05 |
Spring Boot와 JPA를 활용한 커스텀 아이디 생성 전략 구현 (0) | 2023.10.31 |
Spring/트랜잭션 제어/@Transactional (0) | 2023.08.27 |