
API를 개발하면서 이에 대한 문서를 작성하기 위해 SpringDoc Swagger3를 사용하게 되었다.
적용하면서 로컬 환경에서는 큰 문제 없이 잘 동작하였지만, 어플리케이션을 배포 후 Swagger에 접속하자 MIME타입 에러가 발생하였다.
간단히 MIME타입 설정만 하면 쉽게 해결될 줄 알았지만, 설정 후 CSS, JS와 같은 정적 리소스에 대한 404에러가 날 반겨주었다.
현재는 문제를 해결했으며, 해결한 과정을 기록하려고 한다.
인프라의 구성은 아래 나타낸 그림과 같이 Nginx Proxy Manager를 이용한 Reverse Proxy
경량 쿠버네티스인 Minikube를 사용하여 Kubectl Proxy를 통한 Service로 접근,
Pod내 Container로 동작중인 어플리케이션에 접근하는 구조로 되어있다.

특정 도메인으로 API로 접근이 가능하게하기 위해. Proxy Host에 등록하고 SSL 인증서를 적용하였다.
그리고 나서 아래와 같이 Kubectl Proxy로 접근하기 위해 location 블럭을 만들어 설정을 등록하였다.
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
return 200;
}
rewrite ^/(.*)$ /api/v1/namespaces/default/services/http:서비스명:포트/proxy/$1 break;
proxy_pass 경로;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
kubectl proxy로 접근하기 위해서 location블록을 추가하고 rewrite하여 kubectl proxy api경로로 보냈다. 이렇게 하면 이제 해당 proxy host로 들어온 요청은 kubectl proxy로 접근하여 해당 service로 접근하게 된다.
Swagger-ui로 접근하기 위해서 https://example.dev.com/swagger-ui/index.html로 접근을 해보았지만 하얀색 화면 외에 아무것도 표시가 되지 않는다...😅
해결해보기 위해서 브라우저의 개발자 도구를 열어보았다.
포스팅 초반부에 말했던 MIME타입 에러가 발생하고 있었다.
MIME 타입이란?
인터넷에서 전송되는 다양한 종류의 데이터를 식별하기 위한 형식
주로 웹 브라우저가 웹 서버로 받은 데이터를 해석할 때 사용됨
MIME TYPE은 HTTP 헤더에서 Content-Type 등으로 지정됨
이 문제를 해결하기 위해서 Nginx Proxy Manager에 등록한 Proxy Host에 해당 설정을 추가 하였다.
# Nginx에 정의된 MIME 타입 정의 파일을 포함시킨다.
include mime.types;
# MIME 타입이 정의되어있지 않다면 application/octet-stream로 설정한다.
default_type application/octet-stream;
이렇게 하면 모든 파일에 대한 적절한 MIME Type 설정이 가능하다.
하지만 다시 Swagger-ui로 접근해보았지만 아직도 하얀색 화면외 아무것도 나타나지 않는다.
개발자 도구를 다시 열어보니 MIME Type Error가 사라졌지만, 이제는 CSS, Js와 같은 정적 리소스에 대한 404 에러가 발생하고 있었다...😡
처음 404 Error를 마주했을때는 왜 발생하는지 몰랐다.
Swagger에서 다 설정된데로 경로에서 가져오는데 왜 못찾는가... 설정을 살펴보았지만 도저히
알 수 없어 구글링을 하면서 비슷한 사례들을 찾아봤다.
보통 Swagger2를 사용하다가 Swagger3로 넘어오면서 Swagger-ui접속 경로가 달라져
접근이 안되는 사례가 다반사였다. 하지만 나는 접근경로도 문제가 없는데 왜..??
그러다 문득 kubectl proxy or Reverse Proxy 쪽이 의심이 가기 시작했다.
먼저 Nginx Proxy Manager에 설정해둔 사항을 확인해보았다.
# Nginx Proxy Manager 설정
# Nginx에 정의된 MIME 타입 정의 파일을 포함시킨다.
include mime.types;
# MIME 타입이 정의되어있지 않다면 application/octet-stream로 설정한다.
default_type application/octet-stream;
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
return 200;
}
rewrite ^/(.*)$ /api/v1/namespaces/default/services/http:서비스명:포트/proxy/$1 break;
proxy_pass 경로;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
분명 /api/v1/namespaces/default/services/http:서비스명:포트/proxy/ 로 요청해서
다른 엔드포인트를 호출했을때는 문제가 없이 호출이 된다는 것을 알았다. 그럼 kubectl proxy api 경로의 문제는 아니다.
리눅스 터미널을 이용해 curl로 직접 404 Error가 발생하는 css, js 파일을 요청해보았다.

아주 잘 가지고온다. 그럼 무엇이 문제일까..!
남은건 Nginx Proxy Manager내 설정에서 정적 리소스들에 대한 location 처리를 해준다면??
우리의 애플리케이션은 kubernetes 내에서 실행된다. 그 이야기는 kubectl proxy등을 이용해야 어플리케이션에 접근 할 수 있다는 것이다. 아까 위에서 '/'에 대한 proxy api로의 rewrite를 처리했기 때문에 사용자는 그냥 호출하듯이 해도 proxy를 타게된다.
그 작업을 /swagger-ui 경로에도 적용해주고, 정적 리소스에 대해서도 처리를 해주면 된다.
#Nginx Proxy Manager에 /swagger-ui 경로에 대한 처리
location /swagger-ui {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
add_header 'X-Content-Type-Options' 'nosniff';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
return 200;
}
# 요청 Rewrite
rewrite ^/swagger-ui/(.*)$ /api/v1/namespaces/default/services/http:서비스명:포트/proxy/swagger-ui/$1 break;
proxy_pass 경로;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Prefix "/swagger-ui";
# Css, Js에 대해서도 적용시켜주자
location ~ ^/swagger-ui/(.+\.css)$ {
proxy_pass 경로/api/v1/namespaces/default/services/http:서비스명:포트/proxy/swagger-ui/$1;
}
location ~ ^/swagger-ui/(.+\.js)$ {
proxy_pass 경로/api/v1/namespaces/default/services/http:서비스명:포트/proxy/swagger-ui/$1;
}
# favicon에 대한 처리
location ~ ^/swagger-ui/(.+\.png)$ {
proxy_pass 경로/api/v1/namespaces/default/services/http:서비스명:포트/proxy/swagger-ui/$1;
}
}
이제 설정을 적용하고 다시 Swagger-ui에 접근해보자
이제 완벽히 작동한다...!👍