콘텐츠로 이동

커스텀 Docs UI 정적 에셋(자체 호스팅)

API 문서는 Swagger UIReDoc을 사용하며, 각각 JavaScript와 CSS 파일이 필요합니다.

기본적으로 이러한 파일은 CDN에서 제공됩니다.

하지만 이를 커스터마이징할 수 있으며, 특정 CDN을 지정하거나 파일을 직접 제공할 수도 있습니다.

JavaScript와 CSS용 커스텀 CDN

예를 들어 다른 CDN을 사용하고 싶다고 해봅시다. 예를 들면 https://unpkg.com/을 사용하려는 경우입니다.

이는 예를 들어 특정 국가에서 일부 URL을 제한하는 경우에 유용할 수 있습니다.

자동 문서 비활성화하기

첫 번째 단계는 자동 문서를 비활성화하는 것입니다. 기본적으로 자동 문서는 기본 CDN을 사용하기 때문입니다.

비활성화하려면 FastAPI 앱을 생성할 때 해당 URL을 None으로 설정하세요:

from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_redoc_html,
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)

app = FastAPI(docs_url=None, redoc_url=None)


@app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
    return get_swagger_ui_html(
        openapi_url=app.openapi_url,
        title=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js",
        swagger_css_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()


@app.get("/redoc", include_in_schema=False)
async def redoc_html():
    return get_redoc_html(
        openapi_url=app.openapi_url,
        title=app.title + " - ReDoc",
        redoc_js_url="https://unpkg.com/redoc@2/bundles/redoc.standalone.js",
    )


@app.get("/users/{username}")
async def read_user(username: str):
    return {"message": f"Hello {username}"}

커스텀 문서 포함하기

이제 커스텀 문서를 위한 경로 처리를 만들 수 있습니다.

FastAPI 내부 함수를 재사용해 문서용 HTML 페이지를 생성하고, 필요한 인자를 전달할 수 있습니다:

  • openapi_url: 문서 HTML 페이지가 API의 OpenAPI 스키마를 가져올 수 있는 URL입니다. 여기서는 app.openapi_url 속성을 사용할 수 있습니다.
  • title: API의 제목입니다.
  • oauth2_redirect_url: 기본값을 사용하려면 여기서 app.swagger_ui_oauth2_redirect_url을 사용할 수 있습니다.
  • swagger_js_url: Swagger UI 문서의 HTML이 JavaScript 파일을 가져올 수 있는 URL입니다. 커스텀 CDN URL입니다.
  • swagger_css_url: Swagger UI 문서의 HTML이 CSS 파일을 가져올 수 있는 URL입니다. 커스텀 CDN URL입니다.

ReDoc도 마찬가지입니다...

from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_redoc_html,
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)

app = FastAPI(docs_url=None, redoc_url=None)


@app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
    return get_swagger_ui_html(
        openapi_url=app.openapi_url,
        title=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js",
        swagger_css_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()


@app.get("/redoc", include_in_schema=False)
async def redoc_html():
    return get_redoc_html(
        openapi_url=app.openapi_url,
        title=app.title + " - ReDoc",
        redoc_js_url="https://unpkg.com/redoc@2/bundles/redoc.standalone.js",
    )


@app.get("/users/{username}")
async def read_user(username: str):
    return {"message": f"Hello {username}"}

swagger_ui_redirect에 대한 경로 처리는 OAuth2를 사용할 때 도움이 되는 헬퍼입니다.

API를 OAuth2 provider와 통합하면 인증을 수행한 뒤 획득한 자격 증명으로 API 문서로 다시 돌아올 수 있습니다. 그리고 실제 OAuth2 인증을 사용해 API와 상호작용할 수 있습니다.

Swagger UI가 이 과정을 백그라운드에서 처리해 주지만, 이를 위해 이 "redirect" 헬퍼가 필요합니다.

테스트용 경로 처리 만들기

이제 모든 것이 제대로 동작하는지 테스트할 수 있도록 경로 처리를 하나 만드세요:

from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_redoc_html,
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)

app = FastAPI(docs_url=None, redoc_url=None)


@app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
    return get_swagger_ui_html(
        openapi_url=app.openapi_url,
        title=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js",
        swagger_css_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()


@app.get("/redoc", include_in_schema=False)
async def redoc_html():
    return get_redoc_html(
        openapi_url=app.openapi_url,
        title=app.title + " - ReDoc",
        redoc_js_url="https://unpkg.com/redoc@2/bundles/redoc.standalone.js",
    )


@app.get("/users/{username}")
async def read_user(username: str):
    return {"message": f"Hello {username}"}

테스트하기

이제 http://127.0.0.1:8000/docs에서 문서에 접속한 뒤 페이지를 새로고침하면, 새 CDN에서 에셋을 불러오는 것을 확인할 수 있습니다.

문서용 JavaScript와 CSS 자체 호스팅하기

JavaScript와 CSS를 자체 호스팅하는 것은 예를 들어, 오프라인 상태이거나 외부 인터넷에 접근할 수 없는 환경, 또는 로컬 네트워크에서도 앱이 계속 동작해야 할 때 유용할 수 있습니다.

여기서는 동일한 FastAPI 앱에서 해당 파일을 직접 제공하고, 문서가 이를 사용하도록 설정하는 방법을 살펴봅니다.

프로젝트 파일 구조

프로젝트 파일 구조가 다음과 같다고 해봅시다:

.
├── app
│   ├── __init__.py
│   ├── main.py

이제 해당 정적 파일을 저장할 디렉터리를 만드세요.

새 파일 구조는 다음과 같을 수 있습니다:

.
├── app
│   ├── __init__.py
│   ├── main.py
└── static/

파일 다운로드하기

문서에 필요한 정적 파일을 다운로드해서 static/ 디렉터리에 넣으세요.

각 링크를 우클릭한 뒤 "링크를 다른 이름으로 저장..."과 비슷한 옵션을 선택하면 될 것입니다.

Swagger UI는 다음 파일을 사용합니다:

ReDoc은 다음 파일을 사용합니다:

이후 파일 구조는 다음과 같을 수 있습니다:

.
├── app
│   ├── __init__.py
│   ├── main.py
└── static
    ├── redoc.standalone.js
    ├── swagger-ui-bundle.js
    └── swagger-ui.css

정적 파일 제공하기

  • StaticFiles를 import합니다.
  • 특정 경로에 StaticFiles() 인스턴스를 "마운트(mount)"합니다.
from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_redoc_html,
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)
from fastapi.staticfiles import StaticFiles

app = FastAPI(docs_url=None, redoc_url=None)

app.mount("/static", StaticFiles(directory="static"), name="static")


@app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
    return get_swagger_ui_html(
        openapi_url=app.openapi_url,
        title=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="/static/swagger-ui-bundle.js",
        swagger_css_url="/static/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()


@app.get("/redoc", include_in_schema=False)
async def redoc_html():
    return get_redoc_html(
        openapi_url=app.openapi_url,
        title=app.title + " - ReDoc",
        redoc_js_url="/static/redoc.standalone.js",
    )


@app.get("/users/{username}")
async def read_user(username: str):
    return {"message": f"Hello {username}"}

정적 파일 테스트하기

애플리케이션을 시작하고 http://127.0.0.1:8000/static/redoc.standalone.js로 이동하세요.

ReDoc용 매우 긴 JavaScript 파일이 보일 것입니다.

예를 들어 다음과 같이 시작할 수 있습니다:

/*! For license information please see redoc.standalone.js.LICENSE.txt */
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")):
...

이는 앱에서 정적 파일을 제공할 수 있고, 문서용 정적 파일을 올바른 위치에 배치했다는 것을 확인해 줍니다.

이제 문서가 이 정적 파일을 사용하도록 앱을 설정할 수 있습니다.

정적 파일을 위한 자동 문서 비활성화하기

커스텀 CDN을 사용할 때와 마찬가지로, 첫 단계는 자동 문서를 비활성화하는 것입니다. 자동 문서는 기본적으로 CDN을 사용합니다.

비활성화하려면 FastAPI 앱을 생성할 때 해당 URL을 None으로 설정하세요:

from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_redoc_html,
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)
from fastapi.staticfiles import StaticFiles

app = FastAPI(docs_url=None, redoc_url=None)

app.mount("/static", StaticFiles(directory="static"), name="static")


@app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
    return get_swagger_ui_html(
        openapi_url=app.openapi_url,
        title=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="/static/swagger-ui-bundle.js",
        swagger_css_url="/static/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()


@app.get("/redoc", include_in_schema=False)
async def redoc_html():
    return get_redoc_html(
        openapi_url=app.openapi_url,
        title=app.title + " - ReDoc",
        redoc_js_url="/static/redoc.standalone.js",
    )


@app.get("/users/{username}")
async def read_user(username: str):
    return {"message": f"Hello {username}"}

정적 파일을 위한 커스텀 문서 포함하기

그리고 커스텀 CDN을 사용할 때와 동일한 방식으로, 이제 커스텀 문서를 위한 경로 처리를 만들 수 있습니다.

다시 한 번, FastAPI 내부 함수를 재사용해 문서용 HTML 페이지를 생성하고, 필요한 인자를 전달할 수 있습니다:

  • openapi_url: 문서 HTML 페이지가 API의 OpenAPI 스키마를 가져올 수 있는 URL입니다. 여기서는 app.openapi_url 속성을 사용할 수 있습니다.
  • title: API의 제목입니다.
  • oauth2_redirect_url: 기본값을 사용하려면 여기서 app.swagger_ui_oauth2_redirect_url을 사용할 수 있습니다.
  • swagger_js_url: Swagger UI 문서의 HTML이 JavaScript 파일을 가져올 수 있는 URL입니다. 이제는 여러분의 앱이 직접 제공하는 파일입니다.
  • swagger_css_url: Swagger UI 문서의 HTML이 CSS 파일을 가져올 수 있는 URL입니다. 이제는 여러분의 앱이 직접 제공하는 파일입니다.

ReDoc도 마찬가지입니다...

from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_redoc_html,
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)
from fastapi.staticfiles import StaticFiles

app = FastAPI(docs_url=None, redoc_url=None)

app.mount("/static", StaticFiles(directory="static"), name="static")


@app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
    return get_swagger_ui_html(
        openapi_url=app.openapi_url,
        title=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="/static/swagger-ui-bundle.js",
        swagger_css_url="/static/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()


@app.get("/redoc", include_in_schema=False)
async def redoc_html():
    return get_redoc_html(
        openapi_url=app.openapi_url,
        title=app.title + " - ReDoc",
        redoc_js_url="/static/redoc.standalone.js",
    )


@app.get("/users/{username}")
async def read_user(username: str):
    return {"message": f"Hello {username}"}

swagger_ui_redirect에 대한 경로 처리는 OAuth2를 사용할 때 도움이 되는 헬퍼입니다.

API를 OAuth2 provider와 통합하면 인증을 수행한 뒤 획득한 자격 증명으로 API 문서로 다시 돌아올 수 있습니다. 그리고 실제 OAuth2 인증을 사용해 API와 상호작용할 수 있습니다.

Swagger UI가 이 과정을 백그라운드에서 처리해 주지만, 이를 위해 이 "redirect" 헬퍼가 필요합니다.

정적 파일 테스트용 경로 처리 만들기

이제 모든 것이 제대로 동작하는지 테스트할 수 있도록 경로 처리를 하나 만드세요:

from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_redoc_html,
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)
from fastapi.staticfiles import StaticFiles

app = FastAPI(docs_url=None, redoc_url=None)

app.mount("/static", StaticFiles(directory="static"), name="static")


@app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
    return get_swagger_ui_html(
        openapi_url=app.openapi_url,
        title=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="/static/swagger-ui-bundle.js",
        swagger_css_url="/static/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()


@app.get("/redoc", include_in_schema=False)
async def redoc_html():
    return get_redoc_html(
        openapi_url=app.openapi_url,
        title=app.title + " - ReDoc",
        redoc_js_url="/static/redoc.standalone.js",
    )


@app.get("/users/{username}")
async def read_user(username: str):
    return {"message": f"Hello {username}"}

정적 파일 UI 테스트하기

이제 WiFi 연결을 끊고 http://127.0.0.1:8000/docs에서 문서에 접속한 뒤 페이지를 새로고침해 보세요.

인터넷이 없어도 API 문서를 보고, API와 상호작용할 수 있을 것입니다.