Framework/Spring-boot

[Spring-Boot] Swagger(OpenAPI) - Failed to load remote configuration (Reverse-Proxy)

dev_ss 2023. 9. 14. 22:49

사내 프로젝트를 진행하면서, 쿠버네티스 환경에서 각각의 Micro-Service에 요청을 하기 위하여 Kong Ingress Controller를 이용하였는데, 그 과정에서 Swagger 접속 시 발생한 에러에 관한 내용이다.

 

[ 출처 : https://medium.com/devops-mojo/kubernetes-ingress-overview-what-is-kubernetes-ingress-introduction-to-k8s-ingress-b0f81525ffe2]

 

위의 사진을 보면, URI의 End-Point를 기반으로 서비스를 분기하여 각 파드에 요청을 보내는 것을 볼 수 있다.

 

운영하는 환경에서는 각 Pod에서 Spring-boot 기반의 애플리케이션 서버를 운영하고 있었는데, Springdoc의 Swagger에 접속하면 다음의 화면을 볼 수 있었다.

[ Swagger 접속 시 화면]

 

이와 관련하여 빠르게 네트워크 상의 문제라고 인지하였고, Springdoc의 공식 문서에서 관련된 자료를 찾았다.

 

 

https://springdoc.org/#how-can-i-deploy-springdoc-openapi-starter-webmvc-ui-behind-a-reverse-proxy

 

OpenAPI 3 Library for spring-boot

Library for OpenAPI 3 with spring boot projects. Is based on swagger-ui, to display the OpenAPI description.Generates automatically the OpenAPI file.

springdoc.org

 

위의 공식 Docs의 링크에 들어가 보면 FAQ에 관련 내용을 찾아볼 수 있다.

 

Nginx와 같은 웹 서버에서 Reverse-Proxy를 사용하게 되면, spring-boot에서는 처음 받았던 요청을 기반으로, spring-doc의 html과 config를 조회하게 되는데, 여기서 에러가 발생하게 되는 것이다.


간단하게 아래의 예시를 볼 수 있다.

 

127.0.0.1:8000이라는 포트에서 Spring-boot를 이용할 때, 해당 Host(127.0.0.1)와 Port(8000)을 이용하여, 하위 경로의 Swagger의 데이터를 가져오게 된다.

 

ex ) 127.0.0.1:8000/swagger-ui/index.html

 

하지만 Reverse-proxy를 이용하게 된다면 얘기가 달라진다.


Nginx를 이용하고 아래와 같이 A와 B라는 서버로 reverse-proxy 설정을 했다고 가정하면,

  • A : 127.0.0.1/api/apple -> 127.0.0.1:8000
  • B : 127.0.0.1/api/banana  -> 127.0.0.1:9000

8000번 포트를 이용하고 있는 A서버를 호출하려면 127.0.0.1/api/apple을 호출하면 되고,

9000번 포트를 이용하고 있는 B서버를 호출하려면 127.0.0.1/api/banana를 호출하면 된다.

 

위 두 서버에 대하여 요청할 때, Nginx의 포트를 이용하되, 경로를 통하여 다른 서버를 호출하게 된다.

 

그렇다면 A 서버의 swagger를 접속하기 위해서는 단순하게 생각한다면, 127.0.0.1/api/apple/swagger-ui/index.html라는 주소로 요청을 해야 된다고 생각할 것이다.

 

하지만 경로는 맞지만 결과는 다르게 된다.

 

127.0.0.1/api/apple/swagger-ui/index.html에 요청을 하게 된다면,

 

127.0.0.1:8000/swagger-ui/index.html으로 요청이 가는 것이 아닌,

 

127.0.0.1/swagger-ui/index.html의 주소로 연결이 될 것이다.

 

이는 초기에 받은 웹 서버(Nginx)의 요청(Request)을 기준으로 swagger에 연결하는 것으로 설정이 되어있기 때문이다.

 


해결 방법은 간단한데, Spring-boot 서버에서 이용할 Forward-proxy와 관련된 설정만 하면 끝이다.

 

공식문서에 나와있는 것처럼, application.properties(yaml)에 설정을 추가하고 

# application.properties(yaml)에 아래 추가
server.forward-headers-strategy=framework

 

ForwaredHeader를 이용하기 위한 Bean을 등록해주기만 하면 된다.

// Bean 등록
@Bean
ForwardedHeaderFilter forwardedHeaderFilter() {
   return new ForwardedHeaderFilter();
}

 

 

 

반응형