스프링이해 5 - 차이는?

좋습니다 👍
이건 **Spring Framework 내부 구조에서 가장 유명한 질문입니다.

> Spring은 순환참조(Circular Dependency)를 어떻게 해결하는가?



핵심은

3단계 캐시 (3-level cache)

입니다.


---

1️⃣ 순환참조란 무엇인가

예를 들어 이런 구조입니다.

@Service
class AService {

    private final BService b;

    public AService(BService b) {
        this.b = b;
    }
}

@Service
class BService {

    private final AService a;

    public BService(AService a) {
        this.a = a;
    }
}

구조

A → B
↑ ↓
└───┘

문제

A 생성하려면 B 필요
B 생성하려면 A 필요

그래서 일반 DI 컨테이너는

무한 루프

또는

BeanCurrentlyInCreationException

이 발생합니다.


---

2️⃣ Spring 해결 방법

Spring Framework는

3개의 캐시

를 사용합니다.

1️⃣ singletonObjects
2️⃣ earlySingletonObjects
3️⃣ singletonFactories


---

3️⃣ 1단계 캐시

singletonObjects

완전히 생성된 Bean 저장


AService (완성)
BService (완성)

일반 Bean 조회는 여기서 합니다.


---

4️⃣ 2단계 캐시

earlySingletonObjects

초기 생성 Bean


아직 초기화 안 끝난 Bean


---

5️⃣ 3단계 캐시 (핵심)

singletonFactories

여기에는

ObjectFactory

가 들어 있습니다.


Bean을 만들어 줄 팩토리

입니다.

이게 중요한 이유는

> AOP 프록시 생성 때문



입니다.


@Transactional

@Async


같은 Spring AOP 기능 때문입니다.


---

6️⃣ 실제 순환참조 해결 과정


A → B → A


---

① A 생성 시작

create A

A는 아직 완성 안 됨

그래서

singletonFactories

에 등록

A factory 저장


---

② B 생성

A가 B 필요

그래서

create B


---

③ B가 A 필요

이제 문제 발생

B → A 필요

하지만 A는 아직 생성 중

그래서 Spring이

singletonFactories

확인


---

④ early reference 생성

Spring이

ObjectFactory


A early object

만듭니다.

그리고

earlySingletonObjects

에 저장


---

⑤ B 생성 완료

B 완성


---

⑥ A 생성 완료

이제

A → B 주입

완료


---

7️⃣ 그림으로 보면

create A
  ↓
singletonFactories 저장
  ↓
create B
  ↓
B → A 필요
  ↓
earlySingletonObjects에서 A 제공
  ↓
B 완성
  ↓
A 완성
  ↓
singletonObjects 이동


---

8️⃣ 중요한 제한

이 방법은

Setter / Field Injection

에서는 가능하지만

Constructor Injection

에서는 불가능합니다.

왜냐하면

생성 전에 의존성 필요

하기 때문입니다.

그래서

constructor circular dependency

는 에러 납니다.


---

9️⃣ Spring Boot 2.6 변화

**Spring Boot 2.6부터

순환참조 기본 금지

되었습니다.

에러

circular reference detected

필요하면

spring.main.allow-circular-references=true

설정해야 합니다.


---

🔥 핵심 요약

Spring Circular Dependency 해결
      │
      ▼
3-level cache

캐시 역할

singletonObjects 완성 Bean
earlySingletonObjects 초기 Bean
singletonFactories Bean factory



---

💡 진짜 핵심

이 구조가 필요한 이유는

AOP 프록시 때문

입니다.

그래서

Spring Framework의 Bean 생성 로직은

AbstractAutowireCapableBeanFactory

안에 구현되어 있습니다.


---

원하시면 다음도 설명해 드릴게요.
이건 Spring 내부 이해 끝판왕 3개입니다.

1️⃣ DispatcherServlet 동작 원리 (Spring MVC 90% 구조)
2️⃣ Spring AOP 프록시 생성 과정
3️⃣ Spring Boot 자동설정 직접 만드는 방법 (@Conditional)

특히 1번 DispatcherServlet 이해하면
Spring MVC 구조가 완전히 정리됩니다.

댓글

가장 많이 본 글