YoungSoo

순환 참조에 의한 종속성 문제 발생 본문

프로젝트

순환 참조에 의한 종속성 문제 발생

YoungSooSoo 2023. 5. 30. 00:50

문제 원인 파악

현재 Spring Boot 프로젝트에서 순환 참조에 의한 종속성 문제가 발생했습니다. Spring Cloud Gateway에서 Spring Security를 적용하는 과정에서 발생했습니다. Gateway와 Security를 관리하기 위해 GatewaySecurityConfig 클래스를 만들어 코드를 작성하던 중 JwtAuthenticationFilter 빈을 생성자를 통해 주입받았습니다. 동시에 JwtAuthenticationFilter 클래스에서 GatewaySecurityConfig 클래스를 주입받아 사용되었습니다. 이로 인해 두 클래스 간에 서로를 참조하는 순환 참조 문제가 발생했습니다.

 

순환 참조에 의한 종속성 문제란

순환 참조 문제에 대해 간단하게 알고 가려고 합니다. 순환 참조란 서로를 참조하는 빈들 간에 종속성이 발생하는 상황을 말합니다. 이 경우 스프링은 어떤 빈을 먼저 생성해야 할지 결정할 수 없어서 오류가 발생합니다. Spring Framework에서는 기본적으로 순환 참조를 허용하지 않습니다. 이는 의도하지 않은 동작, 무한 루프, 메모리 누수 등과 같은 문제를 발생시킬 수 있기 때문입니다. 따라서 스프링은 순환 참조를 감지하고 이를 방지하기 위해 의존성을 관리하고 있습니다.

 

해결 방안 모색

1. @Component 어노테이션을 사용하여 클래스를 빈으로 등록하는 방법

  • JwtAuthenticationFilter 클래스에 @Component 어노테이션을 추가하여 컴포넌트 스캔 대상으로 등록합니다. 이렇게 하면 스프링이 해당 클래스를 빈으로 인스턴스화할 수 있었습니다.
  • 장점
    • 간편하고 빠르게 클래스를 빈으로 등록할 수 있습니다.
    • 자동으로 컴포넌트 스캔에 의해 찾아지기 때문에 추가 구성이 필요하지 않습니다.
  • 단점
    • 외부 클래스나 라이브러리의 경우에는 @Component 어노테이션을 직접 추가할 수 없으므로, 수정할 수 없는 클래스의 경우에는 사용할 수 없습니다.
    • 명시적으로 빈의 이름을 지정하기 어렵기 때문에 충돌이 발생할 수 있습니다.
    • 빈의 생성과 구성에 대한 제어가 제한적일 수 있습니다.

2. @Bean 메서드를 사용하여 클래스를 빈으로 등록하는 방법

  • 아래 사진과 같이 @Bean을 사용한다면 이름을 지정할 수도 있고 제어가 가능했고 순환 참조 문제를 해결할 수 있었습니다.
  •  장점
    • 외부 클래스나 라이브러리의 객체를 빈으로 등록할 수 있습니다.
    • 빈의 생성 및 구성에 대한 제어가 가능합니다.
    • 명시적으로 빈의 이름을 지정할 수 있어 충돌을 방지할 수 있습니다.
  • 단점
    • 수동으로 메서드를 작성해야 하므로 번거로울 수 있습니다.
    • 일부 클래스의 경우에는 생성자 인자를 전달받을 수 없어서 의존성 주입이 어려울 수 있습니다.

3. @Lazy를 통해 순환 참조를 끊을 수 있습니다.

 

Core Features

Spring Boot uses Commons Logging for all internal logging but leaves the underlying log implementation open. Default configurations are provided for Java Util Logging, Log4j2, and Logback. In each case, loggers are pre-configured to use console output with

docs.spring.io

 

결과적으로

저는 @Component 어노테이션을 사용해 해결해주는 방법과 @Bean을 직접 생성해주는 방식을 고민하였고 명시적으로 빈의 이름을 지정해줄 수 있고 순환 참조 문제를 해결해줄 수 있는 @Bean을 통해 해결해주었습니다.

 

하지만 제일 좋은 방법은 역시 순환 참조가 일어나지 않도록 코드를 작성하지 않는 거 같습니다. ㅎㅎ