🌐 Update translations for ko (add-missing) (#15168)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Sebastián Ramírez 2026-03-19 19:56:39 +01:00 committed by GitHub
parent 019471bc6c
commit 07dfa9a5ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 522 additions and 0 deletions

View File

@ -0,0 +1,63 @@
# 바이트를 Base64로 포함하는 JSON { #json-with-bytes-as-base64 }
애플리케이션에서 JSON 데이터를 주고받아야 하지만 그 안에 바이너리 데이터를 포함해야 한다면, base64로 인코딩해서 포함할 수 있습니다.
## Base64와 파일 { #base64-vs-files }
바이너리 데이터 업로드에는 [요청 파일](../tutorial/request-files.md)을, 바이너리 데이터 전송에는 [커스텀 응답 - FileResponse](./custom-response.md#fileresponse--fileresponse-)를 사용할 수 있는지 먼저 고려하세요. JSON으로 인코딩하는 대신 말입니다.
JSON은 UTF-8로 인코딩된 문자열만 포함할 수 있으므로, 원시 바이트를 그대로 담을 수 없습니다.
Base64는 바이너리 데이터를 문자열로 인코딩할 수 있지만, 이를 위해 원래의 바이너리 데이터보다 더 많은 문자 수를 사용해야 하므로 일반적인 파일 전송보다 비효율적일 수 있습니다.
반드시 JSON 안에 바이너리 데이터를 포함해야 하고, 파일을 사용할 수 없을 때만 base64를 사용하세요.
## Pydantic `bytes` { #pydantic-bytes }
`bytes` 필드를 가진 Pydantic 모델을 선언하고, 모델 설정에서 `val_json_bytes`를 사용하도록 지정하면 입력 JSON 데이터를 base64로 “검증”하도록 할 수 있습니다. 이 검증 과정의 일부로 base64 문자열을 바이트로 디코딩합니다.
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *}
`/docs`를 확인하면 `data` 필드가 base64로 인코딩된 bytes를 기대한다고 표시됩니다:
<div class="screenshot">
<img src="/img/tutorial/json-base64-bytes/image01.png">
</div>
아래와 같은 요청을 보낼 수 있습니다:
```json
{
"description": "Some data",
"data": "aGVsbG8="
}
```
/// tip | 팁
`aGVsbG8=``hello`의 base64 인코딩입니다.
///
그러면 Pydantic이 base64 문자열을 디코딩하여 모델의 `data` 필드에 원래 바이트를 제공합니다.
다음과 같은 응답을 받게 됩니다:
```json
{
"description": "Some data",
"content": "hello"
}
```
## 출력 데이터용 Pydantic `bytes` { #pydantic-bytes-for-output-data }
출력 데이터에도 모델 설정에서 `ser_json_bytes`와 함께 `bytes` 필드를 사용할 수 있습니다. 그러면 Pydantic이 JSON 응답을 생성할 때 바이트를 base64로 “직렬화”합니다.
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *}
## 입력과 출력 데이터용 Pydantic `bytes` { #pydantic-bytes-for-input-and-output-data }
물론, 동일한 모델을 사용해 JSON 데이터를 받을 때는 `val_json_bytes`로 입력을 “검증”하고, JSON 데이터를 보낼 때는 `ser_json_bytes`로 출력을 “직렬화”하도록 base64를 모두 처리하게 구성할 수 있습니다.
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *}

View File

@ -0,0 +1,117 @@
# 데이터 스트리밍 { #stream-data }
JSON으로 구조화할 수 있는 데이터를 스트리밍하려면 [JSON Lines 스트리밍](../tutorial/stream-json-lines.md)을 사용하세요.
하지만 순수 바이너리 데이터나 문자열을 스트리밍하려면 다음과 같이 하면 됩니다.
/// info | 정보
FastAPI 0.134.0에 추가되었습니다.
///
## 사용 예시 { #use-cases }
예를 들어 AI LLM 서비스의 출력에서 바로 순수 문자열을 스트리밍하고 싶다면 이를 사용할 수 있습니다.
또한 큰 바이너리 파일을 스트리밍하는 데 사용할 수 있습니다. 한 번에 모두 메모리로 읽지 않고, 읽는 즉시 데이터 청크를 순차적으로 스트리밍합니다.
이 방식으로 비디오나 오디오를 스트리밍할 수도 있으며, 처리하면서 생성된 데이터를 곧바로 전송할 수도 있습니다.
## `yield`와 함께 `StreamingResponse` 사용하기 { #a-streamingresponse-with-yield }
경로 처리 함수에서 `response_class=StreamingResponse`를 선언하면 `yield`를 사용해 데이터 청크를 순차적으로 보낼 수 있습니다.
{* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *}
FastAPI는 각 데이터 청크를 있는 그대로 `StreamingResponse`에 전달하며, JSON 등으로 변환하려고 하지 않습니다.
### async가 아닌 경로 처리 함수 { #non-async-path-operation-functions }
`async`가 없는 일반 `def` 함수에서도 동일하게 `yield`를 사용할 수 있습니다.
{* ../../docs_src/stream_data/tutorial001_py310.py ln[26:29] hl[27] *}
### 타입 애너테이션 생략하기 { #no-annotation }
바이너리 데이터를 스트리밍할 때는 반환 타입 애너테이션을 굳이 선언할 필요가 없습니다.
FastAPI는 데이터를 Pydantic으로 JSON으로 변환하거나 어떤 방식으로든 직렬화하지 않으므로, 이 경우 타입 애너테이션은 편집기나 도구를 위한 용도일 뿐이며 FastAPI에서는 사용되지 않습니다.
{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *}
이는 곧 `StreamingResponse`를 사용할 때 타입 애너테이션과 무관하게, 전송 기준에 맞춰 바이트 데이터를 생성하고 인코딩할 자유와 책임이 여러분에게 있음을 의미합니다. 🤓
### 바이트 스트리밍 { #stream-bytes }
주요 사용 사례 중 하나는 문자열 대신 `bytes`를 스트리밍하는 것입니다. 물론 그렇게 할 수 있습니다.
{* ../../docs_src/stream_data/tutorial001_py310.py ln[44:47] hl[47] *}
## 사용자 정의 `PNGStreamingResponse` { #a-custom-pngstreamingresponse }
위 예시에서는 바이트 데이터를 스트리밍했지만, 응답에 `Content-Type` 헤더가 없어 클라이언트는 어떤 유형의 데이터를 받는지 알 수 없습니다.
스트리밍하는 데이터 유형에 맞춰 `Content-Type` 헤더를 설정하는 `StreamingResponse`의 하위 클래스를 직접 만들 수 있습니다.
예를 들어 `media_type` 속성을 사용해 `Content-Type` 헤더를 `image/png`로 설정하는 `PNGStreamingResponse`를 만들 수 있습니다:
{* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *}
그런 다음 경로 처리 함수에서 `response_class=PNGStreamingResponse`로 이 새 클래스를 사용할 수 있습니다:
{* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *}
### 파일 시뮬레이션 { #simulate-a-file }
이 예시에서는 `io.BytesIO`로 파일을 시뮬레이션합니다. 이는 메모리에서만 존재하지만 파일과 동일한 인터페이스를 제공하는 파일 유사 객체입니다.
예를 들어 실제 파일처럼 내용을 소비하기 위해 순회(iterate)할 수 있습니다.
{* ../../docs_src/stream_data/tutorial002_py310.py ln[1:27] hl[3,12:13,25] *}
/// note | 기술 세부사항
다른 두 변수 `image_base64``binary_image`는 이미지를 Base64로 인코딩한 뒤 바이트로 변환한 것이며, 이를 `io.BytesIO`에 전달합니다.
이 예시에서 하나의 파일 안에 모두 담아, 그대로 복사해 실행할 수 있도록 하기 위한 목적입니다. 🥚
///
`with` 블록을 사용하면 제너레이터 함수(`yield`가 있는 함수)가 끝난 뒤, 즉 응답 전송이 완료된 후 파일 유사 객체가 닫히도록 보장합니다.
이 예시처럼 메모리 상의 가짜 파일(`io.BytesIO`)이라면 크게 중요하지 않지만, 실제 파일의 경우 작업이 끝난 뒤 파일을 닫는 것이 매우 중요합니다.
### 파일과 비동기 { #files-and-async }
대부분의 경우 파일 유사 객체는 기본적으로 async/await와 호환되지 않습니다.
예를 들어 `await file.read()``async for chunk in file`과 같은 패턴을 지원하지 않습니다.
또한 디스크나 네트워크에서 읽기 때문에, 많은 경우 읽기 작업은 이벤트 루프를 막을 수 있는 블로킹 연산입니다.
/// info | 정보
위의 예시는 예외적인 경우입니다. `io.BytesIO` 객체는 이미 메모리에 있으므로 읽기가 아무 것도 차단하지 않습니다.
하지만 실제 파일이나 파일 유사 객체를 읽을 때는 블로킹되는 경우가 많습니다.
///
이벤트 루프가 블로킹되는 것을 피하려면 경로 처리 함수를 `async def` 대신 일반 `def`로 선언하세요. 그러면 FastAPI가 스레드풀 워커에서 실행하여 메인 루프가 막히지 않도록 합니다.
{* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *}
/// tip | 팁
비동기 함수 안에서 블로킹 코드를 호출해야 하거나, 반대로 블로킹 함수 안에서 비동기 함수를 호출해야 한다면 FastAPI의 형제 라이브러리인 [Asyncer](https://asyncer.tiangolo.com)를 사용할 수 있습니다.
///
### `yield from` { #yield-from }
파일 유사 객체처럼 어떤 것을 순회하면서 각 항목마다 `yield`를 하는 대신, `yield from`을 사용해 각 항목을 직접 전달하고 `for` 루프를 생략할 수 있습니다.
이는 FastAPI에 특화된 기능이 아니라 순수한 파이썬 기능이지만, 알아두면 유용한 트릭입니다. 😎
{* ../../docs_src/stream_data/tutorial002_py310.py ln[37:40] hl[40] *}

View File

@ -0,0 +1,88 @@
# 엄격한 Content-Type 확인 { #strict-content-type-checking }
기본적으로 **FastAPI**는 JSON 요청 본문에 대해 엄격한 `Content-Type` 헤더 검사를 사용합니다. 이는 JSON 요청의 본문을 JSON으로 파싱하려면 유효한 `Content-Type` 헤더(예: `application/json`)를 반드시 포함해야 함을 의미합니다.
## CSRF 위험 { #csrf-risk }
이 기본 동작은 매우 특정한 시나리오에서 **Cross-Site Request Forgery (CSRF)** 공격의 한 유형에 대한 보호를 제공합니다.
이러한 공격은 브라우저가 다음과 같은 경우 CORS 사전 요청(preflight) 검사를 수행하지 않고 스크립트가 요청을 보내도록 허용한다는 점을 악용합니다:
- `Content-Type` 헤더가 없음(예: `Blob` 본문과 함께 `fetch()` 사용)
- 그리고 어떠한 인증 자격 증명도 보내지 않음
이 유형의 공격은 주로 다음과 같은 경우에 관련이 있습니다:
- 애플리케이션이 로컬(예: `localhost`) 또는 내부 네트워크에서 실행 중이고
- 애플리케이션에 인증이 없어 같은 네트워크에서 오는 모든 요청을 신뢰한다고 가정하는 경우
## 공격 예시 { #example-attack }
로컬 AI 에이전트를 실행하는 방법을 만들었다고 가정해 봅시다.
이 에이전트는 다음 위치에 API를 제공합니다:
```
http://localhost:8000/v1/agents/multivac
```
또한 다음 위치에 프론트엔드가 있습니다:
```
http://localhost:8000
```
/// tip | 팁
두 주소 모두 같은 호스트를 사용합니다.
///
그런 다음 프론트엔드를 통해 AI 에이전트가 여러분을 대신해 작업을 수행하도록 할 수 있습니다.
이는 공개 인터넷이 아니라 로컬에서 실행되므로, 여러분은 로컬 네트워크 접근만을 신뢰하고 별도의 인증을 설정하지 않기로 합니다.
그 후 사용자는 이를 설치해 로컬에서 실행할 수 있습니다.
그리고 다음과 같은 악성 웹사이트를 열 수 있습니다:
```
https://evilhackers.example.com
```
그 악성 웹사이트가 `Blob` 본문으로 `fetch()`를 사용해 로컬 API로 요청을 보냅니다:
```
http://localhost:8000/v1/agents/multivac
```
악성 웹사이트의 호스트와 로컬 앱의 호스트가 다르더라도, 브라우저는 다음과 같은 이유로 CORS 사전 요청(preflight)을 트리거하지 않습니다:
- 인증 없이 동작하므로 자격 증명을 보낼 필요가 없습니다.
- 브라우저는 JSON을 보내지 않는다고 판단합니다(`Content-Type` 헤더가 없기 때문).
그러면 악성 웹사이트가 로컬 AI 에이전트로 하여금 사용자의 전 직장 상사에게 화난 메시지를 보내게 하거나... 더 나쁜 일을 시킬 수도 있습니다. 😅
## 공개 인터넷 { #open-internet }
여러분의 앱이 공개 인터넷에 있다면, '네트워크를 신뢰'하여 누구나 인증 없이 권한 있는 요청을 보내도록 두지는 않을 것입니다.
공격자는 브라우저 상호작용 없이도 스크립트를 실행해 여러분의 API로 요청을 보낼 수 있으므로, 아마 이미 권한이 필요한 엔드포인트는 보호하고 있을 것입니다.
그런 경우에는 이 공격/위험은 해당하지 않습니다.
이 위험과 공격은 주로 앱이 **로컬 네트워크**에서 실행되고 그것이 **유일한 보호수단**이라고 가정할 때 관련이 있습니다.
## Content-Type 없이 요청 허용하기 { #allowing-requests-without-content-type }
만약 `Content-Type` 헤더를 보내지 않는 클라이언트를 지원해야 한다면, `strict_content_type=False`로 설정해 엄격한 검사를 비활성화할 수 있습니다:
{* ../../docs_src/strict_content_type/tutorial001_py310.py hl[4] *}
이 설정을 사용하면 `Content-Type` 헤더가 없는 요청도 본문이 JSON으로 파싱됩니다. 이는 이전 버전의 FastAPI와 동일한 동작입니다.
/// info | 정보
이 동작과 설정은 FastAPI 0.132.0에 추가되었습니다.
///

View File

@ -0,0 +1,23 @@
# 에디터 지원 { #editor-support }
공식 [FastAPI 확장](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode)은 FastAPI 개발 워크플로우를 강화해 줍니다. *경로 처리* 탐색 및 이동, FastAPI Cloud 배포, 실시간 로그 스트리밍을 제공합니다.
확장에 대한 자세한 내용은 [GitHub 저장소](https://github.com/fastapi/fastapi-vscode)의 README를 참고하세요.
## 설치 및 설정 { #setup-and-installation }
**FastAPI 확장**은 [VS Code](https://code.visualstudio.com/)와 [Cursor](https://www.cursor.com/)에서 사용할 수 있습니다. 각 에디터의 확장(Extensions) 패널에서 "FastAPI"로 검색한 뒤 **FastAPI Labs**가 배포한 확장을 선택해 바로 설치할 수 있습니다. 또한 [vscode.dev](https://vscode.dev), [github.dev](https://github.dev) 같은 브라우저 기반 에디터에서도 동작합니다.
### 애플리케이션 자동 감지 { #application-discovery }
기본적으로 이 확장은 작업 공간에서 `FastAPI()`를 생성하는 파일을 스캔하여 FastAPI 애플리케이션을 자동으로 감지합니다. 프로젝트 구조상 자동 감지가 어려운 경우, `pyproject.toml``[tool.fastapi]` 항목이나 VS Code 설정 `fastapi.entryPoint`에 모듈 표기(예: `myapp.main:app`)로 엔트리포인트를 지정할 수 있습니다.
## 기능 { #features }
- **경로 처리 탐색기** - 애플리케이션의 모든 <dfn title="경로, 엔드포인트">*경로 처리*</dfn>를 사이드바 트리 뷰로 확인합니다. 클릭하면 해당 경로 또는 라우터 정의로 바로 이동합니다.
- **경로 검색** - <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>E</kbd> (macOS: <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>E</kbd>)로 경로, 메서드, 이름으로 검색합니다.
- **CodeLens 탐색** - 테스트 클라이언트 호출(예: `client.get('/items')`) 위의 클릭 가능한 링크를 통해 해당 *경로 처리*로 즉시 이동하여 테스트와 구현 간을 빠르게 오갈 수 있습니다.
- **FastAPI Cloud에 배포** - [FastAPI Cloud](https://fastapicloud.com/)로 원클릭 배포를 지원합니다.
- **애플리케이션 로그 스트리밍** - FastAPI Cloud에 배포된 애플리케이션의 로그를 실시간으로 스트리밍하며, 레벨 필터링과 텍스트 검색을 제공합니다.
확장의 기능을 먼저 익혀보고 싶다면, 명령 팔레트(<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd>, macOS: <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd>)를 열고 "Welcome: Open walkthrough..."를 선택한 뒤 "Get started with FastAPI" walkthrough를 선택해 보세요.

View File

@ -0,0 +1,120 @@
# 서버 전송 이벤트(SSE) { #server-sent-events-sse }
브라우저 클라이언트로 데이터를 스트리밍하려면 **Server-Sent Events**(SSE)를 사용할 수 있습니다.
이는 [JSON Lines 스트리밍](stream-json-lines.md)과 비슷하지만, 브라우저가 기본적으로 [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource)를 통해 지원하는 `text/event-stream` 형식을 사용합니다.
/// info | 정보
FastAPI 0.135.0에 추가되었습니다.
///
## Server-Sent Events란 { #what-are-server-sent-events }
SSE는 서버에서 클라이언트로 HTTP를 통해 데이터를 스트리밍하기 위한 표준입니다.
각 이벤트는 `data`, `event`, `id`, `retry`와 같은 "필드"를 가진 작은 텍스트 블록이며, 빈 줄로 구분됩니다.
다음과 같습니다:
```
data: {"name": "Portal Gun", "price": 999.99}
data: {"name": "Plumbus", "price": 32.99}
```
SSE는 AI 채팅 스트리밍, 실시간 알림, 로그와 관측성, 그리고 서버가 클라이언트로 업데이트를 푸시하는 여러 경우에 흔히 사용됩니다.
/// tip | 팁
비디오나 오디오처럼 바이너리 데이터를 스트리밍하려면 고급 가이드: [데이터 스트리밍](../advanced/stream-data.md)을 확인하세요.
///
## FastAPI로 SSE 스트리밍 { #stream-sse-with-fastapi }
FastAPI에서 SSE를 스트리밍하려면, 경로 처리 함수에서 `yield`를 사용하고 `response_class=EventSourceResponse`를 설정하세요.
`EventSourceResponse``fastapi.sse`에서 임포트합니다:
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[4,22] *}
`yield`된 항목은 JSON으로 인코딩되어 SSE 이벤트의 `data:` 필드로 전송됩니다.
반환 타입을 `AsyncIterable[Item]`으로 선언하면 FastAPI가 이를 사용해 데이터를 Pydantic으로 **검증**, **문서화**, **직렬화**합니다.
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[10:12,23] *}
/// tip | 팁
Pydantic이 **Rust** 쪽에서 직렬화하므로, 반환 타입을 선언하지 않았을 때보다 훨씬 더 높은 **성능**을 얻을 수 있습니다.
///
### 비 async *경로 처리 함수* { #non-async-path-operation-functions }
`async`가 없는 일반 `def` 함수도 사용할 수 있으며, 동일하게 `yield`를 사용할 수 있습니다.
FastAPI가 이벤트 루프를 막지 않도록 올바르게 실행을 보장합니다.
이 경우 함수가 async가 아니므로 적절한 반환 타입은 `Iterable[Item]`입니다:
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[28:31] hl[29] *}
### 반환 타입 없음 { #no-return-type }
반환 타입을 생략할 수도 있습니다. FastAPI는 [`jsonable_encoder`](./encoder.md)를 사용해 데이터를 변환하고 전송합니다.
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[34:37] hl[35] *}
## `ServerSentEvent` { #serversentevent }
`event`, `id`, `retry`, `comment` 같은 SSE 필드를 설정해야 한다면, 일반 데이터 대신 `ServerSentEvent` 객체를 `yield`할 수 있습니다.
`ServerSentEvent``fastapi.sse`에서 임포트합니다:
{* ../../docs_src/server_sent_events/tutorial002_py310.py hl[4,26] *}
`data` 필드는 항상 JSON으로 인코딩됩니다. Pydantic 모델을 포함해 JSON으로 직렬화할 수 있는 값을 모두 전달할 수 있습니다.
## 원시 데이터 { #raw-data }
JSON 인코딩 없이 데이터를 보내야 한다면, `data` 대신 `raw_data`를 사용하세요.
미리 포맷된 텍스트, 로그 라인, 또는 `[DONE]`과 같은 특수한 <dfn title="특수한 조건이나 상태를 나타내는 데 사용되는 값">"센티널"</dfn> 값을 보낼 때 유용합니다.
{* ../../docs_src/server_sent_events/tutorial003_py310.py hl[17] *}
/// note | 참고
`data``raw_data`는 상호 배타적입니다. 각 `ServerSentEvent`에는 이 둘 중 하나만 설정할 수 있습니다.
///
## `Last-Event-ID`로 재개하기 { #resuming-with-last-event-id }
브라우저가 연결이 끊긴 후 재연결할 때, 마지막으로 받은 `id``Last-Event-ID` 헤더에 담아 보냅니다.
헤더 파라미터로 이를 읽어와 클라이언트가 중단한 지점부터 스트림을 재개할 수 있습니다:
{* ../../docs_src/server_sent_events/tutorial004_py310.py hl[25,27,31] *}
## POST로 SSE 사용하기 { #sse-with-post }
SSE는 `GET`뿐만 아니라 **모든 HTTP 메서드**와 함께 동작합니다.
이는 `POST`로 SSE를 스트리밍하는 [MCP](https://modelcontextprotocol.io) 같은 프로토콜에 유용합니다:
{* ../../docs_src/server_sent_events/tutorial005_py310.py hl[14] *}
## 기술 세부사항 { #technical-details }
FastAPI는 일부 SSE 모범 사례를 기본으로 구현합니다.
- 메시지가 없을 때는 15초마다 **"keep alive" `ping` 주석**을 보내 일부 프록시가 연결을 종료하지 않도록 합니다. [HTML 사양: Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes)에서 권장합니다.
- 스트림이 **캐시되지 않도록** `Cache-Control: no-cache` 헤더를 설정합니다.
- Nginx 같은 일부 프록시에서 **버퍼링을 방지**하기 위해 특수 헤더 `X-Accel-Buffering: no`를 설정합니다.
여러분이 따로 할 일은 없습니다. 기본값으로 동작합니다. 🤓

View File

@ -0,0 +1,111 @@
# JSON Lines 스트리밍 { #stream-json-lines }
연속된 데이터를 "**스트림**"으로 보내고 싶다면 **JSON Lines**를 사용할 수 있습니다.
/// info
FastAPI 0.134.0에 추가되었습니다.
///
## 스트림이란 { #what-is-a-stream }
데이터를 "**스트리밍**"한다는 것은 애플리케이션이 전체 항목 시퀀스가 모두 준비될 때까지 기다리지 않고 클라이언트로 데이터 항목을 보내기 시작한다는 뜻입니다.
즉, 첫 번째 항목을 보내면 클라이언트는 그것을 받아 처리하기 시작하고, 그동안 애플리케이션은 다음 항목을 계속 생성할 수 있습니다.
```mermaid
sequenceDiagram
participant App
participant Client
App->>App: Produce Item 1
App->>Client: Send Item 1
App->>App: Produce Item 2
Client->>Client: Process Item 1
App->>Client: Send Item 2
App->>App: Produce Item 3
Client->>Client: Process Item 2
App->>Client: Send Item 3
Client->>Client: Process Item 3
Note over App: Keeps producing...
Note over Client: Keeps consuming...
```
데이터를 계속 보내는 무한 스트림일 수도 있습니다.
## JSON Lines { #json-lines }
이런 경우에는 한 줄에 하나의 JSON 객체를 보내는 형식인 "**JSON Lines**"를 사용하는 것이 일반적입니다.
응답의 콘텐츠 타입은 `application/json` 대신 `application/jsonl`이고, 본문은 다음과 같습니다:
```json
{"name": "Plumbus", "description": "A multi-purpose household device."}
{"name": "Portal Gun", "description": "A portal opening device."}
{"name": "Meeseeks Box", "description": "A box that summons a Meeseeks."}
```
JSON 배열(Python의 list에 해당)과 매우 비슷하지만, 항목들을 `[]`로 감싸고 항목 사이에 `,`를 넣는 대신, 줄마다 하나의 JSON 객체가 있고, 새 줄 문자로 구분됩니다.
/// info
핵심은 애플리케이션이 각 줄을 차례로 생성하는 동안, 클라이언트는 이전 줄을 소비할 수 있다는 점입니다.
///
/// note | 기술 세부사항
각 JSON 객체는 새 줄로 구분되므로, 내용에 실제 줄바꿈 문자를 포함할 수는 없습니다. 하지만 JSON 표준의 일부인 이스케이프된 줄바꿈(`\n`)은 포함할 수 있습니다.
보통은 신경 쓸 필요가 없습니다. 자동으로 처리되니 계속 읽어 주세요. 🤓
///
## 사용 예 { #use-cases }
이 방법을 사용해 **AI LLM** 서비스, **로그** 또는 **telemetry**에서 오는 데이터, 혹은 **JSON** 항목으로 구조화할 수 있는 다른 유형의 데이터를 스트리밍할 수 있습니다.
/// tip
비디오나 오디오처럼 바이너리 데이터를 스트리밍하려면 고급 가이드를 확인하세요: [스트림 데이터](../advanced/stream-data.md).
///
## FastAPI로 JSON Lines 스트리밍 { #stream-json-lines-with-fastapi }
FastAPI에서 JSON Lines를 스트리밍하려면, *경로 처리 함수*에서 `return`을 사용하는 대신 `yield`로 각 항목을 차례로 생성하면 됩니다.
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[24] *}
보내려는 각 JSON 항목의 타입이 `Item`(Pydantic 모델)이고 함수가 async라면, 반환 타입을 `AsyncIterable[Item]`로 선언할 수 있습니다:
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[9:11,22] *}
반환 타입을 선언하면 FastAPI가 이를 사용해 데이터를 **검증**하고, OpenAPI에 **문서화**하고, **필터링**하고, Pydantic으로 **직렬화**합니다.
/// tip
Pydantic이 **Rust** 측에서 직렬화하므로, 반환 타입을 선언하지 않았을 때보다 훨씬 높은 **성능**을 얻게 됩니다.
///
### 비동기 아님 *경로 처리 함수* { #non-async-path-operation-functions }
일반 `def` 함수(`async` 없이)도 사용할 수 있으며, 동일하게 `yield`를 사용할 수 있습니다.
FastAPI가 이벤트 루프를 막지 않도록 올바르게 실행되게 보장합니다.
이 경우 함수가 async가 아니므로, 올바른 반환 타입은 `Iterable[Item]`입니다:
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[27:30] hl[28] *}
### 반환 타입 생략 { #no-return-type }
반환 타입을 생략할 수도 있습니다. 그러면 FastAPI가 [`jsonable_encoder`](./encoder.md)를 사용해 데이터를 JSON으로 직렬화 가능한 형태로 변환한 뒤 JSON Lines로 전송합니다.
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[33:36] hl[34] *}
## 서버 전송 이벤트(SSE) { #server-sent-events-sse }
FastAPI는 Server-Sent Events(SSE)도 일급으로 지원합니다. 매우 비슷하지만 몇 가지 추가 세부사항이 있습니다. 다음 장에서 자세히 알아보세요: [Server-Sent Events (SSE)](server-sent-events.md). 🤓