
서로 다른 클래스가 각자의 Bean을 생성하기 위해 서로를 참조하다가
결국 어느 Bean도 생성하지 못하는 문제이다.
(빈 생성 충돌)
그래서 적용 된
기존의 내 서비스 코드는
+---------------------------+
| EduCardService |
|---------------------------|
| - Redis 캐싱 로직 |
| - 크롤링 로직 |
| - RDS 데이터 저장 요청 | <----+
+---------------------------+ |
| |
v |
+---------------------------+ |
| EduCardTransactionalService |
|---------------------------| |
| - RDS 데이터 저장 | |
| - RDS 데이터 조회 | |
| - 크롤링 요청 처리 | ------+
+---------------------------+
이렇게 서로를 참조하는 형태가 되었다.
Redis 캐싱 체크하고, -> 없으면 RDS를 조회해 캐싱에 가져다 놓고..
RDS에 없으면 -> 크롤링 로직 돌리고 -> RDS에 저장하고..
@Service
@RequiredArgsConstructor
public class EduCardService {
private final EduCardTransactionalService transactionalService;
public List<EduCardDto> fetchEduCardContentsWithCache() {
// Redis → RDS → Crawling
return transactionalService.handleCrawlingAndSave();
}
}
@Service
@RequiredArgsConstructor
public class EduCardTransactionalService {
private final EduCardService eduCardService;
public List<EduCardDto> handleCrawlingAndSave() {
return eduCardService.crawlEduCardContents(); //크롤링 요청 to EduCardService
}
}
위 코드보면 알 수 있듯이 왔다갔다.. 그러다보니 순환 참조 문제가 발생하게 되었다.
빈 생성이 온전히 이뤄지도록 하기 위해서 순환 참조를 제거해주어야 하고,
클래스의 책임을 명확히 분리해야 한다.
EduCardService
-캐싱 및 크롤링만 담당
-데이터베이스 관련 작업은 하지 않음
EduCardTransactionalService
-데이터베이스 관련 작업만 담당
-크롤링 로직은 호출하지 않음
이렇게 클래스의 역할을 완전히 분리하려고 한다.
서로를 참조하는 형태에서, 하나를 완전히 모듈화하여 단방향 호출하도록 바꿔준다.
@Service
@RequiredArgsConstructor
public class EduCardService {
private final EduCardTransactionalService transactionalService;
public List<EduCardDto> fetchEduCardContentsWithCache() {
// Redis → RDS → Crawling
transactionalService.saveCrawledData(crawlEduCardContents());
}
}
@Service
@RequiredArgsConstructor
public class EduCardTransactionalService {
// 데이터 저장 및 조회만 담당
public void saveCrawledData(List<EduCardDto> crawledData) {
// 크롤링 된 데이터를 RDS에 저장
}
}