[Spring-Boot] Swagger(OpenAPI) - Failed to load remote configuration (Reverse-Proxy)
사내 프로젝트를 진행하면서, 쿠버네티스 환경에서 각각의 Micro-Service에 요청을 하기 위하여 Kong Ingress Controller를 이용하였는데, 그 과정에서 Swagger 접속 시 발생한 에러에 관한 내용이다.
위의 사진을 보면, URI의 End-Point를 기반으로 서비스를 분기하여 각 파드에 요청을 보내는 것을 볼 수 있다.
운영하는 환경에서는 각 Pod에서 Spring-boot 기반의 애플리케이션 서버를 운영하고 있었는데, Springdoc의 Swagger에 접속하면 다음의 화면을 볼 수 있었다.
이와 관련하여 빠르게 네트워크 상의 문제라고 인지하였고, Springdoc의 공식 문서에서 관련된 자료를 찾았다.
https://springdoc.org/#how-can-i-deploy-springdoc-openapi-starter-webmvc-ui-behind-a-reverse-proxy
위의 공식 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();
}