Home OpenFeign으로 인한 순환참조 에러
Post
Cancel

OpenFeign으로 인한 순환참조 에러

직장동료가 테스트 코드를 작성하려 하니 OpenFeign(내가 작성한 코드)에서 순환참조가 일어나 테스트 코드가 제대로 돌아가지 않는다고 한다. 어서 해결해보자.


환경: spring boot + GraphQL

OpenFeign 코드

1
2
3
4
5
6
7
8
9
10
11
@Service  
@RequiredArgsConstructor  
public class OpenFeignServiceImpl implements OpenFeignService {  
	
	private final OpenFeign sendOpenFeign;  // 아래의 OpenFeign interface를 참조
  
	@Override  
	public Response getResponse(final Input input) {  
		return sendOpenFeign.getResponse(input);  
	}  
}
1
2
3
4
5
6
7
@FeignClient(name = "Client", url = "${client.url}", configuration = OpenFeignConfig.class)  
public interface OpenFeign {  
  
	@GetMapping(value = "/api/v1/test/{input}", consumes = "application/json")  
	Response getResponse(@PathVariable("input") String input);  

}

코드를 확인해보면,
OpenFeignServiceImpl 에서 OpenFeign 를 주입받아서 OpenFeign 의 getResponse 메소드를 사용하는 형태이다.

에러 화면

circular reference error

나는 mvcResourceUrlProvider를 참조하지 않았는데, 참조되어서 저 mvcResourceUrlProviderGraphql Servlet을 참조하고 … 꼬리를 물어서 순환참조가 되었다.

순환참조가 일어나는 이유

OpenFeign은 RESTFul Service를 쉽게 부르기 위한 라이브러리이고, mvcResourceUrlProvider은 정적리소스에 url을 제공하는 스프링 빈이다.
OpenFeign의 value인  “/api/v1/test/{input}” 가 정적인 url이라서 mvcResourceUrlProvider을 부르는 것으로 판단했다.

순환참조를 끊어내는 방법

순환참조를 끊어내기 위해 빈을 늦게 생성해주면 되는데, 2가지의 옵션이 있다.

  • @Lazy
  • ObjectProvider

하지만 실질적으로 @Lazy는 순환참조를 제대로 끊어내지 못하는데, 그 이유의 둘의 차이에 있다. @Lazy는 단순히 만드는 걸 늦게 만들게 하는 어노테이션이고, ObjectProvider는 실제 사용될때 생성하게 만들어주는 빈이기 때문에 ObjectProvider 를 사용해야 순환참조가 끊긴다.

1
2
3
4
5
6
7
8
9
10
11
@Service  
@RequiredArgsConstructor  
public class OpenFeignServiceImpl implements OpenFeignService {  
	
	private final ObjectProvider<OpenFeign> sendOpenFeign;  // ObjectProvider로 한번 감싼서 참조한다.
  
	@Override  
	public Response getResponse(final Input input) {  
		return sendOpenFeign.getObject.getResponse(input);  
	}  
}

결국 ObjectProvider 를 사용해서 문제는 해결되었다… 욕 먹어서 배부르다.. 하하


번외

근데 왜 mvcResourceUrlProvidergraphqlServletRegistrationBean를 왜 참조하지?

mvcResourceUrlProvider는 Spring Boot에서 제공하는 웹 관련 기능의 필수적인 부분인 GraphQL 요청을 처리하는 데 필요하기 때문에 간접적으로 graphqlServletRegistrationBean을 참조합니다.

그럼 gql 쓰면 무조건 ObjectProvider 써야 하나?

graphql과 spring boot 에서 제공하는 웹 관련 기능을 같이 사용하게 되면 ObjectProvider 혹은 다른 lazy 를 권장합니다.

This post is licensed under CC BY 4.0 by the author.

API 게이트웨이

Transactional isolation(격리수준)