Browse Source

Merge branch 'master' into fix-duplicate-special-dependency-handling

pull/12406/head
Peter Volf 6 months ago
committed by GitHub
parent
commit
f78d00b17b
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      .github/workflows/deploy-docs.yml
  2. 2
      .github/workflows/publish.yml
  3. 2
      .pre-commit-config.yaml
  4. 12
      docs/en/docs/release-notes.md
  5. 179
      docs/ko/docs/advanced/advanced-dependencies.md
  6. 7
      docs/ko/docs/advanced/testing-events.md
  7. 58
      docs/ko/docs/advanced/using-request-directly.md
  8. 298
      docs/ko/docs/environment-variables.md
  9. 81
      docs/ko/docs/history-design-future.md
  10. 61
      docs/ko/docs/how-to/conditional-openapi.md
  11. 19
      docs/ko/docs/security/index.md
  12. 212
      docs/pt/docs/advanced/path-operation-advanced-configuration.md

2
.github/workflows/deploy-docs.yml

@ -64,7 +64,7 @@ jobs:
BRANCH: ${{ ( github.event.workflow_run.head_repository.full_name == github.repository && github.event.workflow_run.head_branch == 'master' && 'main' ) || ( github.event.workflow_run.head_sha ) }}
# TODO: Use v3 when it's fixed, probably in v3.11
# https://github.com/cloudflare/wrangler-action/issues/307
uses: cloudflare/[email protected]1
uses: cloudflare/[email protected]2
# uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}

2
.github/workflows/publish.yml

@ -35,7 +35,7 @@ jobs:
TIANGOLO_BUILD_PACKAGE: ${{ matrix.package }}
run: python -m build
- name: Publish
uses: pypa/[email protected]1.0
uses: pypa/[email protected]2.2
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}

2
.pre-commit-config.yaml

@ -14,7 +14,7 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.1
rev: v0.7.2
hooks:
- id: ruff
args:

12
docs/en/docs/release-notes.md

@ -27,6 +27,14 @@ hide:
### Translations
* 🌐 Add Korean translation for `/docs/ko/docs/environment-variables.md`. PR [#12526](https://github.com/fastapi/fastapi/pull/12526) by [@Tolerblanc](https://github.com/Tolerblanc).
* 🌐 Add Korean translation for `docs/ko/docs/history-design-future.md`. PR [#12646](https://github.com/fastapi/fastapi/pull/12646) by [@saeye](https://github.com/saeye).
* 🌐 Add Korean translation for `docs/ko/docs/advanced/advanced-dependencies.md`. PR [#12675](https://github.com/fastapi/fastapi/pull/12675) by [@kim-sangah](https://github.com/kim-sangah).
* 🌐 Add Korean translation for `docs/ko/docs/how-to/conditional-openapi.md`. PR [#12731](https://github.com/fastapi/fastapi/pull/12731) by [@sptcnl](https://github.com/sptcnl).
* 🌐 Add Korean translation for `docs/ko/docs/advanced/using_request_directly.md`. PR [#12738](https://github.com/fastapi/fastapi/pull/12738) by [@kwang1215](https://github.com/kwang1215).
* 🌐 Add Korean translation for `docs/ko/docs/advanced/testing-events.md`. PR [#12741](https://github.com/fastapi/fastapi/pull/12741) by [@9zimin9](https://github.com/9zimin9).
* 🌐 Add Korean translation for `docs/ko/docs/security/index.md`. PR [#12743](https://github.com/fastapi/fastapi/pull/12743) by [@kim-sangah](https://github.com/kim-sangah).
* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/path-operation-advanced-configuration.md`. PR [#12762](https://github.com/fastapi/fastapi/pull/12762) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda).
* 🌐 Add Korean translation for `docs/ko/docs/advanced/wsgi.md`. PR [#12659](https://github.com/fastapi/fastapi/pull/12659) by [@Limsunoh](https://github.com/Limsunoh).
* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/websockets.md`. PR [#12703](https://github.com/fastapi/fastapi/pull/12703) by [@devfernandoa](https://github.com/devfernandoa).
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/security/simple-oauth2.md`. PR [#12520](https://github.com/fastapi/fastapi/pull/12520) by [@LidiaDomingos](https://github.com/LidiaDomingos).
@ -43,6 +51,10 @@ hide:
### Internal
* ⬆ Bump pypa/gh-action-pypi-publish from 1.12.0 to 1.12.2. PR [#12788](https://github.com/fastapi/fastapi/pull/12788) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump pypa/gh-action-pypi-publish from 1.11.0 to 1.12.0. PR [#12781](https://github.com/fastapi/fastapi/pull/12781) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump cloudflare/wrangler-action from 3.11 to 3.12. PR [#12777](https://github.com/fastapi/fastapi/pull/12777) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12766](https://github.com/fastapi/fastapi/pull/12766) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ⬆ Bump pypa/gh-action-pypi-publish from 1.10.3 to 1.11.0. PR [#12721](https://github.com/fastapi/fastapi/pull/12721) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Update pre-commit requirement from <4.0.0,>=2.17.0 to >=2.17.0,<5.0.0. PR [#12749](https://github.com/fastapi/fastapi/pull/12749) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump typer from 0.12.3 to 0.12.5. PR [#12748](https://github.com/fastapi/fastapi/pull/12748) by [@dependabot[bot]](https://github.com/apps/dependabot).

179
docs/ko/docs/advanced/advanced-dependencies.md

@ -0,0 +1,179 @@
# 고급 의존성
## 매개변수화된 의존성
지금까지 본 모든 의존성은 고정된 함수 또는 클래스입니다.
하지만 여러 개의 함수나 클래스를 선언하지 않고도 의존성에 매개변수를 설정해야 하는 경우가 있을 수 있습니다.
예를 들어, `q` 쿼리 매개변수가 특정 고정된 내용을 포함하고 있는지 확인하는 의존성을 원한다고 가정해 봅시다.
이때 해당 고정된 내용을 매개변수화할 수 있길 바랍니다.
## "호출 가능한" 인스턴스
Python에는 클래스의 인스턴스를 "호출 가능"하게 만드는 방법이 있습니다.
클래스 자체(이미 호출 가능함)가 아니라 해당 클래스의 인스턴스에 대해 호출 가능하게 하는 것입니다.
이를 위해 `__call__` 메서드를 선언합니다:
//// tab | Python 3.9+
```Python hl_lines="12"
{!> ../../docs_src/dependencies/tutorial011_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="11"
{!> ../../docs_src/dependencies/tutorial011_an.py!}
```
////
//// tab | Python 3.8+ non-Annotated
/// tip | 참고
가능하다면 `Annotated` 버전을 사용하는 것이 좋습니다.
///
```Python hl_lines="10"
{!> ../../docs_src/dependencies/tutorial011.py!}
```
////
이 경우, **FastAPI**는 추가 매개변수와 하위 의존성을 확인하기 위해 `__call__`을 사용하게 되며,
나중에 *경로 연산 함수*에서 매개변수에 값을 전달할 때 이를 호출하게 됩니다.
## 인스턴스 매개변수화하기
이제 `__init__`을 사용하여 의존성을 "매개변수화"할 수 있는 인스턴스의 매개변수를 선언할 수 있습니다:
//// tab | Python 3.9+
```Python hl_lines="9"
{!> ../../docs_src/dependencies/tutorial011_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="8"
{!> ../../docs_src/dependencies/tutorial011_an.py!}
```
////
//// tab | Python 3.8+ non-Annotated
/// tip | 참고
가능하다면 `Annotated` 버전을 사용하는 것이 좋습니다.
///
```Python hl_lines="7"
{!> ../../docs_src/dependencies/tutorial011.py!}
```
////
이 경우, **FastAPI**는 `__init__`에 전혀 관여하지 않으며, 우리는 이 메서드를 코드에서 직접 사용하게 됩니다.
## 인스턴스 생성하기
다음과 같이 이 클래스의 인스턴스를 생성할 수 있습니다:
//// tab | Python 3.9+
```Python hl_lines="18"
{!> ../../docs_src/dependencies/tutorial011_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="17"
{!> ../../docs_src/dependencies/tutorial011_an.py!}
```
////
//// tab | Python 3.8+ non-Annotated
/// tip | 참고
가능하다면 `Annotated` 버전을 사용하는 것이 좋습니다.
///
```Python hl_lines="16"
{!> ../../docs_src/dependencies/tutorial011.py!}
```
////
이렇게 하면 `checker.fixed_content` 속성에 `"bar"`라는 값을 담아 의존성을 "매개변수화"할 수 있습니다.
## 인스턴스를 의존성으로 사용하기
그런 다음, `Depends(FixedContentQueryChecker)` 대신 `Depends(checker)`에서 이 `checker` 인스턴스를 사용할 수 있으며,
클래스 자체가 아닌 인스턴스 `checker`가 의존성이 됩니다.
의존성을 해결할 때 **FastAPI**는 이 `checker`를 다음과 같이 호출합니다:
```Python
checker(q="somequery")
```
...그리고 이때 반환되는 값을 *경로 연산 함수*의 `fixed_content_included` 매개변수로 전달합니다:
//// tab | Python 3.9+
```Python hl_lines="22"
{!> ../../docs_src/dependencies/tutorial011_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="21"
{!> ../../docs_src/dependencies/tutorial011_an.py!}
```
////
//// tab | Python 3.8+ non-Annotated
/// tip | 참고
가능하다면 `Annotated` 버전을 사용하는 것이 좋습니다.
///
```Python hl_lines="20"
{!> ../../docs_src/dependencies/tutorial011.py!}
```
////
/// tip | 참고
이 모든 과정이 복잡하게 느껴질 수 있습니다. 그리고 지금은 이 방법이 얼마나 유용한지 명확하지 않을 수도 있습니다.
이 예시는 의도적으로 간단하게 만들었지만, 전체 구조가 어떻게 작동하는지 보여줍니다.
보안 관련 장에서는 이와 같은 방식으로 구현된 편의 함수들이 있습니다.
이 모든 과정을 이해했다면, 이러한 보안 도구들이 내부적으로 어떻게 작동하는지 이미 파악한 것입니다.
///

7
docs/ko/docs/advanced/testing-events.md

@ -0,0 +1,7 @@
# 이벤트 테스트: 시작 - 종료
테스트에서 이벤트 핸들러(`startup` 및 `shutdown`)를 실행해야 하는 경우, `with` 문과 함께 `TestClient`를 사용할 수 있습니다.
```Python hl_lines="9-12 20-24"
{!../../docs_src/app_testing/tutorial003.py!}
```

58
docs/ko/docs/advanced/using-request-directly.md

@ -0,0 +1,58 @@
# `Request` 직접 사용하기
지금까지 요청에서 필요한 부분을 각 타입으로 선언하여 사용해 왔습니다.
다음과 같은 곳에서 데이터를 가져왔습니다:
* 경로의 파라미터로부터.
* 헤더.
* 쿠키.
* 기타 등등.
이렇게 함으로써, **FastAPI**는 데이터를 검증하고 변환하며, API에 대한 문서를 자동화로 생성합니다.
하지만 `Request` 객체에 직접 접근해야 하는 상황이 있을 수 있습니다.
## `Request` 객체에 대한 세부 사항
**FastAPI**는 실제로 내부에 **Starlette**을 사용하며, 그 위에 여러 도구를 덧붙인 구조입니다. 따라서 여러분이 필요할 때 Starlette의 <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">`Request`</a> 객체를 직접 사용할 수 있습니다.
`Request` 객체에서 데이터를 직접 가져오는 경우(예: 본문을 읽기)에는 FastAPI가 해당 데이터를 검증하거나 변환하지 않으며, 문서화(OpenAPI를 통한 문서 자동화(로 생성된) API 사용자 인터페이스)도 되지 않습니다.
그러나 다른 매개변수(예: Pydantic 모델을 사용한 본문)는 여전히 검증, 변환, 주석 추가 등이 이루어집니다.
하지만 특정한 경우에는 `Request` 객체에 직접 접근하는 것이 유용할 수 있습니다.
## `Request` 객체를 직접 사용하기
여러분이 클라이언트의 IP 주소/호스트 정보를 *경로 작동 함수* 내부에서 가져와야 한다고 가정해 보겠습니다.
이를 위해서는 요청에 직접 접근해야 합니다.
```Python hl_lines="1 7-8"
{!../../docs_src/using_request_directly/tutorial001.py!}
```
*경로 작동 함수* 매개변수를 `Request` 타입으로 선언하면 **FastAPI**가 해당 매개변수에 `Request` 객체를 전달하는 것을 알게 됩니다.
/// tip | 팁
이 경우, 요청 매개변수와 함께 경로 매개변수를 선언한 것을 볼 수 있습니다.
따라서, 경로 매개변수는 추출되고 검증되며 지정된 타입으로 변환되고 OpenAPI로 주석이 추가됩니다.
이와 같은 방식으로, 다른 매개변수들을 평소처럼 선언하면서, 부가적으로 `Request`도 가져올 수 있습니다.
///
## `Request` 설명서
여러분은 `Request` 객체에 대한 더 자세한 내용을 <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">공식 Starlette 설명서 사이트</a>에서 읽어볼 수 있습니다.
/// note | 기술 세부사항
`from starlette.requests import Request`를 사용할 수도 있습니다.
**FastAPI**는 여러분(개발자)를 위한 편의를 위해 이를 직접 제공하지만, 실제로는 Starlette에서 가져온 것입니다.
///

298
docs/ko/docs/environment-variables.md

@ -0,0 +1,298 @@
# 환경 변수
/// tip | "팁"
만약 "환경 변수"가 무엇이고, 어떻게 사용하는지 알고 계시다면, 이 챕터를 스킵하셔도 좋습니다.
///
환경 변수는 파이썬 코드의 **바깥**인, **운영 체제**에 존재하는 변수입니다. 파이썬 코드나 다른 프로그램에서 읽을 수 있습니다.
환경 변수는 애플리케이션 **설정**을 처리하거나, 파이썬의 **설치** 과정의 일부로 유용합니다.
## 환경 변수를 만들고 사용하기
파이썬 없이도, **셸 (터미널)** 에서 환경 변수를 **생성** 하고 사용할 수 있습니다.
//// tab | Linux, macOS, Windows Bash
<div class="termy">
```console
// You could create an env var MY_NAME with
$ export MY_NAME="Wade Wilson"
// Then you could use it with other programs, like
$ echo "Hello $MY_NAME"
Hello Wade Wilson
```
</div>
////
//// tab | Windows PowerShell
<div class="termy">
```console
// Create an env var MY_NAME
$ $Env:MY_NAME = "Wade Wilson"
// Use it with other programs, like
$ echo "Hello $Env:MY_NAME"
Hello Wade Wilson
```
</div>
////
## 파이썬에서 환경 변수 읽기
파이썬 **바깥**인 터미널에서(다른 도구로도 가능) 환경 변수를 생성도 할 수도 있고, 이를 **파이썬에서 읽을 수 있습니다.**
예를 들어 다음과 같은 `main.py` 파일이 있다고 합시다:
```Python hl_lines="3"
import os
name = os.getenv("MY_NAME", "World")
print(f"Hello {name} from Python")
```
/// tip | "팁"
<a href="https://docs.python.org/3.8/library/os.html#os.getenv" class="external-link" target="_blank">`os.getenv()`</a> 의 두 번째 인자는 반환할 기본값입니다.
여기서는 `"World"`를 넣었기에 기본값으로써 사용됩니다. 넣지 않으면 `None` 이 기본값으로 사용됩니다.
///
그러면 해당 파이썬 프로그램을 다음과 같이 호출할 수 있습니다:
//// tab | Linux, macOS, Windows Bash
<div class="termy">
```console
// Here we don't set the env var yet
$ python main.py
// As we didn't set the env var, we get the default value
Hello World from Python
// But if we create an environment variable first
$ export MY_NAME="Wade Wilson"
// And then call the program again
$ python main.py
// Now it can read the environment variable
Hello Wade Wilson from Python
```
</div>
////
//// tab | Windows PowerShell
<div class="termy">
```console
// Here we don't set the env var yet
$ python main.py
// As we didn't set the env var, we get the default value
Hello World from Python
// But if we create an environment variable first
$ $Env:MY_NAME = "Wade Wilson"
// And then call the program again
$ python main.py
// Now it can read the environment variable
Hello Wade Wilson from Python
```
</div>
////
환경변수는 코드 바깥에서 설정될 수 있지만, 코드에서 읽을 수 있고, 나머지 파일과 함께 저장(`git`에 커밋)할 필요가 없으므로, 구성이나 **설정** 에 사용하는 것이 일반적입니다.
**특정 프로그램 호출**에 대해서만 사용할 수 있는 환경 변수를 만들 수도 있습니다. 해당 프로그램에서만 사용할 수 있고, 해당 프로그램이 실행되는 동안만 사용할 수 있습니다.
그렇게 하려면 프로그램 바로 앞, 같은 줄에 환경 변수를 만들어야 합니다:
<div class="termy">
```console
// Create an env var MY_NAME in line for this program call
$ MY_NAME="Wade Wilson" python main.py
// Now it can read the environment variable
Hello Wade Wilson from Python
// The env var no longer exists afterwards
$ python main.py
Hello World from Python
```
</div>
/// tip | "팁"
<a href="https://12factor.net/config" class="external-link" target="_blank">The Twelve-Factor App: Config</a> 에서 좀 더 자세히 알아볼 수 있습니다.
///
## 타입과 검증
이 환경변수들은 오직 **텍스트 문자열**로만 처리할 수 있습니다. 텍스트 문자열은 파이썬 외부에 있으며 다른 프로그램 및 나머지 시스템(Linux, Windows, macOS 등 다른 운영 체제)과 호환되어야 합니다.
즉, 파이썬에서 환경 변수로부터 읽은 **모든 값**은 **`str`**이 되고, 다른 타입으로의 변환이나 검증은 코드에서 수행해야 합니다.
**애플리케이션 설정**을 처리하기 위한 환경 변수 사용에 대한 자세한 내용은 [고급 사용자 가이드 - 설정 및 환경 변수](./advanced/settings.md){.internal-link target=\_blank} 에서 확인할 수 있습니다.
## `PATH` 환경 변수
**`PATH`**라고 불리는, **특별한** 환경변수가 있습니다. 운영체제(Linux, Windows, macOS 등)에서 실행할 프로그램을 찾기위해 사용됩니다.
변수 `PATH`의 값은 Linux와 macOS에서는 콜론 `:`, Windows에서는 세미콜론 `;`으로 구분된 디렉토리로 구성된 긴 문자열입니다.
예를 들어, `PATH` 환경 변수는 다음과 같습니다:
//// tab | Linux, macOS
```plaintext
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
```
이는 시스템이 다음 디렉토리에서 프로그램을 찾아야 함을 의미합니다:
- `/usr/local/bin`
- `/usr/bin`
- `/bin`
- `/usr/sbin`
- `/sbin`
////
//// tab | Windows
```plaintext
C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32
```
이는 시스템이 다음 디렉토리에서 프로그램을 찾아야 함을 의미합니다:
- `C:\Program Files\Python312\Scripts`
- `C:\Program Files\Python312`
- `C:\Windows\System32`
////
터미널에 **명령어**를 입력하면 운영 체제는 `PATH` 환경 변수에 나열된 **각 디렉토리**에서 프로그램을 **찾습니다.**
예를 들어 터미널에 `python`을 입력하면 운영 체제는 해당 목록의 **첫 번째 디렉토리**에서 `python`이라는 프로그램을 찾습니다.
찾으면 **사용합니다**. 그렇지 않으면 **다른 디렉토리**에서 계속 찾습니다.
### 파이썬 설치와 `PATH` 업데이트
파이썬을 설치할 때, 아마 `PATH` 환경 변수를 업데이트 할 것이냐고 물어봤을 겁니다.
//// tab | Linux, macOS
파이썬을 설치하고 그것이 `/opt/custompython/bin` 디렉토리에 있다고 가정해 보겠습니다.
`PATH` 환경 변수를 업데이트하도록 "예"라고 하면 설치 관리자가 `/opt/custompython/bin``PATH` 환경 변수에 추가합니다.
다음과 같이 보일 수 있습니다:
```plaintext
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin
```
이렇게 하면 터미널에 `python`을 입력할 때, 시스템이 `/opt/custompython/bin`(마지막 디렉토리)에서 파이썬 프로그램을 찾아 사용합니다.
////
//// tab | Windows
파이썬을 설치하고 그것이 `C:\opt\custompython\bin` 디렉토리에 있다고 가정해 보겠습니다.
`PATH` 환경 변수를 업데이트하도록 "예"라고 하면 설치 관리자가 `C:\opt\custompython\bin``PATH` 환경 변수에 추가합니다.
```plaintext
C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin
```
이렇게 하면 터미널에 `python`을 입력할 때, 시스템이 `C:\opt\custompython\bin`(마지막 디렉토리)에서 파이썬 프로그램을 찾아 사용합니다.
////
그래서, 다음과 같이 입력한다면:
<div class="termy">
```console
$ python
```
</div>
//// tab | Linux, macOS
시스템은 `/opt/custompython/bin`에서 `python` 프로그램을 **찾아** 실행합니다.
다음과 같이 입력하는 것과 거의 같습니다:
<div class="termy">
```console
$ /opt/custompython/bin/python
```
</div>
////
//// tab | Windows
시스템은 `C:\opt\custompython\bin\python`에서 `python` 프로그램을 **찾아** 실행합니다.
다음과 같이 입력하는 것과 거의 같습니다:
<div class="termy">
```console
$ C:\opt\custompython\bin\python
```
</div>
////
이 정보는 [가상 환경](virtual-environments.md){.internal-link target=\_blank} 에 대해 알아볼 때 유용할 것입니다.
## 결론
이 문서를 읽고 **환경 변수**가 무엇이고 파이썬에서 어떻게 사용하는지 기본적으로 이해하셨을 겁니다.
또한 <a href="https://ko.wikipedia.org/wiki/환경_변수" class="external-link" target="_blank">환경 변수에 대한 위키피디아(한국어)</a>에서 이에 대해 자세히 알아볼 수 있습니다.
많은 경우에서, 환경 변수가 어떻게 유용하고 적용 가능한지 바로 명확하게 알 수는 없습니다. 하지만 개발할 때 다양한 시나리오에서 계속 나타나므로 이에 대해 아는 것이 좋습니다.
예를 들어, 다음 섹션인 [가상 환경](virtual-environments.md)에서 이 정보가 필요합니다.

81
docs/ko/docs/history-design-future.md

@ -0,0 +1,81 @@
# 역사, 디자인 그리고 미래
어느 날, [한 FastAPI 사용자](https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920)가 이렇게 물었습니다:
> 이 프로젝트의 역사를 알려 주실 수 있나요? 몇 주 만에 멋진 결과를 낸 것 같아요. [...]
여기서 그 역사에 대해 간단히 설명하겠습니다.
---
## 대안
저는 여러 해 동안 머신러닝, 분산 시스템, 비동기 작업, NoSQL 데이터베이스 같은 복잡한 요구사항을 가진 API를 개발하며 여러 팀을 이끌어 왔습니다.
이 과정에서 많은 대안을 조사하고, 테스트하며, 사용해야 했습니다. **FastAPI**의 역사는 그 이전에 나왔던 여러 도구의 역사와 밀접하게 연관되어 있습니다.
[대안](alternatives.md){.internal-link target=_blank} 섹션에서 언급된 것처럼:
> **FastAPI**는 이전에 나왔던 많은 도구들의 노력 없이는 존재하지 않았을 것입니다.
>
> 이전에 개발된 여러 도구들이 이 프로젝트에 영감을 주었습니다.
>
> 저는 오랫동안 새로운 프레임워크를 만드는 것을 피하고자 했습니다. 처음에는 **FastAPI**가 제공하는 기능들을 다양한 프레임워크와 플러그인, 도구들을 조합해 해결하려 했습니다.
>
> 하지만 결국에는 이 모든 기능을 통합하는 도구가 필요해졌습니다. 이전 도구들로부터 최고의 아이디어들을 모으고, 이를 최적의 방식으로 조합해야만 했습니다. 이는 :term:Python 3.6+ 타입 힌트 <type hints>와 같은, 이전에는 사용할 수 없었던 언어 기능이 가능했기 때문입니다.
---
## 조사
여러 대안을 사용해 보며 다양한 도구에서 배운 점들을 모아 저와 개발팀에게 가장 적합한 방식을 찾았습니다.
예를 들어, 표준 :term:Python 타입 힌트 <type hints>에 기반하는 것이 이상적이라는 점이 명확했습니다.
또한, 이미 존재하는 표준을 활용하는 것이 가장 좋은 접근법이라 판단했습니다.
그래서 **FastAPI**의 코드를 작성하기 전에 몇 달 동안 OpenAPI, JSON Schema, OAuth2 명세를 연구하며 이들의 관계와 겹치는 부분, 차이점을 이해했습니다.
---
## 디자인
그 후, **FastAPI** 사용자가 될 개발자로서 사용하고 싶은 개발자 "API"를 디자인했습니다.
[Python Developer Survey](https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools)에 따르면 약 80%의 Python 개발자가 PyCharm, VS Code, Jedi 기반 편집기 등에서 개발합니다. 이 과정에서 여러 아이디어를 테스트했습니다.
대부분의 다른 편집기도 유사하게 동작하기 때문에, **FastAPI**의 이점은 거의 모든 편집기에서 누릴 수 있습니다.
이 과정을 통해 코드 중복을 최소화하고, 모든 곳에서 자동 완성, 타입 검사, 에러 확인 기능이 제공되는 최적의 방식을 찾아냈습니다.
이 모든 것은 개발자들에게 최고의 개발 경험을 제공하기 위해 설계되었습니다.
---
## 필요조건
여러 대안을 테스트한 후, [Pydantic](https://docs.pydantic.dev/)을 사용하기로 결정했습니다.
이후 저는 **Pydantic**이 JSON Schema와 완벽히 호환되도록 개선하고, 다양한 제약 조건 선언을 지원하며, 여러 편집기에서의 자동 완성과 타입 검사 기능을 향상하기 위해 기여했습니다.
또한, 또 다른 주요 필요조건이었던 [Starlette](https://www.starlette.io/)에도 기여했습니다.
---
## 개발
**FastAPI**를 개발하기 시작할 즈음에는 대부분의 준비가 이미 완료된 상태였습니다. 설계가 정의되었고, 필요조건과 도구가 준비되었으며, 표준과 명세에 대한 지식도 충분했습니다.
---
## 미래
현시점에서 **FastAPI**가 많은 사람들에게 유용하다는 것이 명백해졌습니다.
여러 용도에 더 적합한 도구로서 기존 대안보다 선호되고 있습니다.
이미 많은 개발자와 팀들이 **FastAPI**에 의존해 프로젝트를 진행 중입니다 (저와 제 팀도 마찬가지입니다).
하지만 여전히 개선해야 할 점과 추가할 기능들이 많이 남아 있습니다.
**FastAPI**는 밝은 미래로 나아가고 있습니다.
그리고 [여러분의 도움](help-fastapi.md){.internal-link target=_blank}은 큰 힘이 됩니다.

61
docs/ko/docs/how-to/conditional-openapi.md

@ -0,0 +1,61 @@
# 조건부적인 OpenAPI
필요한 경우, 설정 및 환경 변수를 사용하여 환경에 따라 조건부로 OpenAPI를 구성하고 완전히 비활성화할 수도 있습니다.
## 보안, API 및 docs에 대해서
프로덕션에서, 문서화된 사용자 인터페이스(UI)를 숨기는 것이 API를 보호하는 방법이 *되어서는 안 됩니다*.
이는 API에 추가적인 보안을 제공하지 않으며, *경로 작업*은 여전히 동일한 위치에서 사용 할 수 있습니다.
코드에 보안 결함이 있다면, 그 결함은 여전히 존재할 것입니다.
문서를 숨기는 것은 API와 상호작용하는 방법을 이해하기 어렵게 만들며, 프로덕션에서 디버깅을 더 어렵게 만들 수 있습니다. 이는 단순히 <a href="https://en.wikipedia.org/wiki/Security_through_obscurity" class="external-link" target="_blank">'모호성에 의한 보안'</a>의 한 형태로 간주될 수 있습니다.
API를 보호하고 싶다면, 예를 들어 다음과 같은 더 나은 방법들이 있습니다:
* 요청 본문과 응답에 대해 잘 정의된 Pydantic 모델을 사용하도록 하세요.
* 종속성을 사용하여 필요한 권한과 역할을 구성하세요.
* 평문 비밀번호를 절대 저장하지 말고, 오직 암호화된 비밀번호만 저장하세요.
* Passlib과 JWT 토큰과 같은 잘 알려진 암호화 도구들을 구현하고 사용하세요.
* 필요한 곳에 OAuth2 범위를 사용하여 더 세분화된 권한 제어를 추가하세요.
* 등등....
그럼에도 불구하고, 특정 환경(예: 프로덕션)에서 또는 환경 변수의 설정에 따라 API 문서를 비활성화해야 하는 매우 특정한 사용 사례가 있을 수 있습니다.
## 설정 및 환경변수의 조건부 OpenAPI
동일한 Pydantic 설정을 사용하여 생성된 OpenAPI 및 문서 UI를 쉽게 구성할 수 있습니다.
예를 들어:
{* ../../docs_src/conditional_openapi/tutorial001.py hl[6,11] *}
여기서 `openapi_url` 설정을 기본값인 `"/openapi.json"`으로 선언합니다.
그런 뒤, 우리는 `FastAPI` 앱을 만들 때 그것을 사용합니다.
환경 변수 `OPENAPI_URL`을 빈 문자열로 설정하여 OpenAPI(문서 UI 포함)를 비활성화할 수도 있습니다. 예를 들어:
<div class="termy">
```console
$ OPENAPI_URL= uvicorn main:app
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
그리고 `/openapi.json`, `/docs` 또는 `/redoc`의 URL로 이동하면 `404 Not Found`라는 오류가 다음과 같이 표시됩니다:
```JSON
{
"detail": "Not Found"
}
```

19
docs/ko/docs/security/index.md

@ -0,0 +1,19 @@
# 고급 보안
## 추가 기능
[자습서 - 사용자 가이드: 보안](../../tutorial/security/index.md){.internal-link target=_blank} 문서에서 다룬 내용 외에도 보안 처리를 위한 몇 가지 추가 기능이 있습니다.
/// tip
다음 섹션은 **반드시 "고급"** 기능은 아닙니다.
그리고 여러분의 사용 사례에 따라, 적합한 해결책이 그 중 하나에 있을 가능성이 있습니다.
///
## 먼저 자습서 읽기
다음 섹션은 이미 [자습서 - 사용자 가이드: 보안](../../tutorial/security/index.md){.internal-link target=_blank} 문서를 읽었다고 가정합니다.
이 섹션들은 모두 동일한 개념을 바탕으로 하며, 추가 기능을 제공합니다.

212
docs/pt/docs/advanced/path-operation-advanced-configuration.md

@ -0,0 +1,212 @@
# Configuração Avançada da Operação de Rota
## operationId do OpenAPI
/// warning | Aviso
Se você não é um "especialista" no OpenAPI, você provavelmente não precisa disso.
///
Você pode definir o `operationId` do OpenAPI que será utilizado na sua *operação de rota* com o parâmetro `operation_id`.
Você precisa ter certeza que ele é único para cada operação.
{* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *}
### Utilizando o nome da *função de operação de rota* como o operationId
Se você quiser utilizar o nome das funções da sua API como `operationId`s, você pode iterar sobre todos esses nomes e sobrescrever o `operationId` em cada *operação de rota* utilizando o `APIRoute.name` dela.
Você deve fazer isso depois de adicionar todas as suas *operações de rota*.
{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2,12:21,24] *}
/// tip | Dica
Se você chamar `app.openapi()` manualmente, os `operationId`s devem ser atualizados antes dessa chamada.
///
/// warning | Aviso
Se você fizer isso, você tem que ter certeza de que cada uma das suas *funções de operação de rota* tem um nome único.
Mesmo que elas estejam em módulos (arquivos Python) diferentes.
///
## Excluir do OpenAPI
Para excluir uma *operação de rota* do esquema OpenAPI gerado (e por consequência, dos sistemas de documentação automáticos), utilize o parâmetro `include_in_schema` e defina ele como `False`:
{* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *}
## Descrição avançada a partir de docstring
Você pode limitar as linhas utilizadas a partir de uma docstring de uma *função de operação de rota* para o OpenAPI.
Adicionar um `\f` (um caractere de escape para alimentação de formulário) faz com que o **FastAPI** restrinja a saída utilizada pelo OpenAPI até esse ponto.
Ele não será mostrado na documentação, mas outras ferramentas (como o Sphinx) serão capazes de utilizar o resto do texto.
{* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *}
## Respostas Adicionais
Você provavelmente já viu como declarar o `response_model` e `status_code` para uma *operação de rota*.
Isso define os metadados sobre a resposta principal da *operação de rota*.
Você também pode declarar respostas adicionais, com seus modelos, códigos de status, etc.
Existe um capítulo inteiro da nossa documentação sobre isso, você pode ler em [Retornos Adicionais no OpenAPI](additional-responses.md){.internal-link target=_blank}.
## Extras do OpenAPI
Quando você declara uma *operação de rota* na sua aplicação, o **FastAPI** irá gerar os metadados relevantes da *operação de rota* automaticamente para serem incluídos no esquema do OpenAPI.
/// note | Nota
Na especificação do OpenAPI, isso é chamado de um <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object" class="external-link" target="_blank">Objeto de Operação</a>.
///
Ele possui toda a informação sobre a *operação de rota* e é usado para gerar a documentação automaticamente.
Ele inclui os atributos `tags`, `parameters`, `requestBody`, `responses`, etc.
Esse esquema específico para uma *operação de rota* normalmente é gerado automaticamente pelo **FastAPI**, mas você também pode estender ele.
/// tip | Dica
Esse é um ponto de extensão de baixo nível.
Caso você só precise declarar respostas adicionais, uma forma conveniente de fazer isso é com [Retornos Adicionais no OpenAPI](additional-responses.md){.internal-link target=_blank}.
///
Você pode estender o esquema do OpenAPI para uma *operação de rota* utilizando o parâmetro `openapi_extra`.
### Extensões do OpenAPI
Esse parâmetro `openapi_extra` pode ser útil, por exemplo, para declarar [Extensões do OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions):
{* ../../docs_src/path_operation_advanced_configuration/tutorial005.py hl[6] *}
Se você abrir os documentos criados automaticamente para a API, sua extensão aparecerá no final da *operação de rota* específica.
<img src="/img/tutorial/path-operation-advanced-configuration/image01.png">
E se você olhar o esquema OpenAPI resultante (na rota `/openapi.json` da sua API), você verá que a sua extensão também faz parte da *operação de rota* específica:
```JSON hl_lines="22"
{
"openapi": "3.1.0",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"paths": {
"/items/": {
"get": {
"summary": "Read Items",
"operationId": "read_items_items__get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {}
}
}
}
},
"x-aperture-labs-portal": "blue"
}
}
}
}
```
### Esquema de *operação de rota* do OpenAPI personalizado
O dicionário em `openapi_extra` vai ter todos os seus níveis mesclados dentro do esquema OpenAPI gerado automaticamente para a *operação de rota*.
Então, você pode adicionar dados extras para o esquema gerado automaticamente.
Por exemplo, você poderia optar por ler e validar a requisição com seu próprio código, sem utilizar funcionalidades automatizadas do FastAPI com o Pydantic, mas você ainda pode quere definir a requisição no esquema OpenAPI.
Você pode fazer isso com `openapi_extra`:
{* ../../docs_src/path_operation_advanced_configuration/tutorial006.py hl[19:36,39:40] *}
Nesse exemplo, nós não declaramos nenhum modelo do Pydantic. Na verdade, o corpo da requisição não está nem mesmo <abbr title="convertido de um formato plano, como bytes, para objetos Python">analisado</abbr> como JSON, ele é lido diretamente como `bytes` e a função `magic_data_reader()` seria a responsável por analisar ele de alguma forma.
De toda forma, nós podemos declarar o esquema esperado para o corpo da requisição.
### Tipo de conteúdo do OpenAPI personalizado
Utilizando esse mesmo truque, você pode utilizar um modelo Pydantic para definir o esquema JSON que é então incluído na seção do esquema personalizado do OpenAPI na *operação de rota*.
E você pode fazer isso até mesmo quando os dados da requisição não seguem o formato JSON.
Por exemplo, nesta aplicação nós não usamos a funcionalidade integrada ao FastAPI de extrair o esquema JSON dos modelos Pydantic nem a validação automática do JSON. Na verdade, estamos declarando o tipo do conteúdo da requisição como YAML, em vez de JSON:
//// tab | Pydantic v2
```Python hl_lines="17-22 24"
{!> ../../docs_src/path_operation_advanced_configuration/tutorial007.py!}
```
////
//// tab | Pydantic v1
```Python hl_lines="17-22 24"
{!> ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py!}
```
////
/// info | Informação
Na versão 1 do Pydantic, o método para obter o esquema JSON de um modelo é `Item.schema()`, na versão 2 do Pydantic, o método é `Item.model_json_schema()`
///
Entretanto, mesmo que não utilizemos a funcionalidade integrada por padrão, ainda estamos usando um modelo Pydantic para gerar um esquema JSON manualmente para os dados que queremos receber no formato YAML.
Então utilizamos a requisição diretamente, e extraímos o corpo como `bytes`. Isso significa que o FastAPI não vai sequer tentar analisar o corpo da requisição como JSON.
E então no nosso código, nós analisamos o conteúdo YAML diretamente, e estamos utilizando o mesmo modelo Pydantic para validar o conteúdo YAML:
//// tab | Pydantic v2
```Python hl_lines="26-33"
{!> ../../docs_src/path_operation_advanced_configuration/tutorial007.py!}
```
////
//// tab | Pydantic v1
```Python hl_lines="26-33"
{!> ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py!}
```
////
/// info | Informação
Na versão 1 do Pydantic, o método para analisar e validar um objeto era `Item.parse_obj()`, na versão 2 do Pydantic, o método é chamado de `Item.model_validate()`.
///
///tip | Dica
Aqui reutilizamos o mesmo modelo do Pydantic.
Mas da mesma forma, nós poderíamos ter validado de alguma outra forma.
///
Loading…
Cancel
Save