Visual Studio Code에서 FastAPI 튜토리얼
FastAPI는 Python으로 API를 구축하기 위한 현대적이고 고성능인 웹 프레임워크입니다. 자동 유효성 검사, 직렬화, API 문서화와 같은 기능을 제공하면서 빠르고 효율적으로 API를 구축할 수 있도록 설계되어 웹 서비스 및 마이크로서비스 구축에 인기 있는 선택이 되고 있습니다.
이 FastAPI 튜토리얼에서는 FastAPI를 사용하여 식료품 목록 앱을 만들 것입니다. 튜토리얼이 끝나면 Visual Studio Code 터미널, 편집기 및 디버거에서 FastAPI를 작업하는 방법을 이해하게 될 것입니다. 이 튜토리얼은 FastAPI 심층 분석이 아닙니다. 이를 위해서는 공식 FastAPI 문서를 참조하십시오.
Python을 처음 사용하는 경우 언어 및 VS Code의 Python 지원에 익숙해지기 위해 Python 튜토리얼부터 시작하는 것이 좋습니다. 이 튜토리얼은 이미 Python에 익숙하고 VS Code에서 FastAPI를 사용하는 방법을 배우고 싶은 분들에게 더 적합합니다.
이 FastAPI 튜토리얼의 완성된 코드 프로젝트는 GitHub에서 찾을 수 있습니다: python-sample-vscode-fastapi-tutorial.
문제가 있는 경우 답변을 검색하거나 Python 확장 토론 Q&A에서 질문할 수 있습니다.
프로젝트 설정
이 튜토리얼에 대한 프로젝트를 설정하는 데는 여러 가지 방법이 있습니다. GitHub Codespaces와 로컬 머신에서 VS Code에서 설정하는 방법을 다룰 것입니다.
GitHub Codespaces
이 튜토리얼에서 개발하기 위해 프로젝트를 GitHub Codespaces에 설정할 수 있습니다. 여기에서는 원격 코딩, 디버깅 및 앱 실행이 가능합니다. Codespace는 클라우드에서 호스팅되는 완전히 구성된 개발 환경을 제공하여 로컬 설정이 필요 없습니다. 이 환경에는 프로젝트의 종속성, 도구 및 확장 프로그램이 포함되어 일관되고 재현 가능한 개발 경험을 보장합니다. 실시간 편집, 통합 버전 관리, 디버깅 및 테스트 도구에 대한 쉬운 액세스를 제공하여 프로젝트의 보안 및 안정성을 유지하면서 협업을 간소화합니다.
참고: 모든 GitHub.com 계정에는 무료 또는 Pro 요금제에 포함된 GitHub Codespaces의 월별 무료 사용 할당량이 있습니다. 자세한 내용은 GitHub Codespaces 청구 정보를 참조하십시오.
이 튜토리얼에 대한 codespace를 설정하려면 이 프로젝트의 GitHub 리포지토리로 이동하십시오. 이 codespace에는 FastAPI 개발을 신속하게 시작하는 데 필요한 모든 구성과 종속성이 포함되어 있습니다.
이 튜토리얼에서는 dictionarybased 브랜치를 선택하십시오.

그런 다음 Code > Codespaces > Create Codespace on <dictionarybased> 브랜치를 선택하여 프로젝트에 대한 codespace를 생성하고 엽니다.
완료되면 아래의 데이터베이스 교체 섹션으로 계속 진행할 수 있습니다.
로컬 머신에서 VS Code
VS Code에서 이 튜토리얼을 성공적으로 완료하려면 먼저 Python 개발 환경을 설정해야 합니다. 특히 이 튜토리얼에는 다음이 필요합니다.
- Python 3 (설치되지 않은 경우 설치 안내 참조)
- VS Code용 Python 확장 프로그램 (확장 프로그램 설치에 대한 자세한 내용은 확장 프로그램 마켓플레이스를 참조하십시오).
이 섹션에서는 VS Code에서 작업 영역으로 열 폴더를 만들고, Python 가상 환경을 설정하고, 프로젝트 종속성을 설치합니다.
-
파일 시스템에서 이 튜토리얼을 위한 프로젝트 폴더를 생성합니다. 예를 들어
groceries-plugin입니다. -
이 새 폴더를 VS Code에서 엽니다 (File > Open Folder…).
-
작업 영역 신뢰 프롬프트가 표시되면 Yes, I trust the authors를 선택하여 작업 영역이 필요한 리소스 및 확장에 액세스하도록 허용합니다. 작업 영역 신뢰에 대한 자세한 내용은 문서에서 확인할 수 있습니다.
이제 애플리케이션을 설치하려는 종속성을 나열하는 requirements.txt 파일을 만들어 보겠습니다. requirements.txt 파일은 Python 개발에서 일반적인 관행으로, 프로젝트가 의존하는 라이브러리와 해당 버전을 지정하는 데 사용됩니다. 이 파일은 프로젝트를 작업하는 누구나 유사한 개발 환경을 재현할 수 있도록 하여 일관성을 유지하는 데 편리한 구성 요소가 됩니다.
앱을 생성하기 위해 FastAPI, 서버로 작동할 uvicorn, 데이터 저장 및 Redis 데이터베이스와 상호 작용하기 위해 Redis 및 type-redis를 설치합니다.
-
VS Code에서 새 파일을 만듭니다 (File > New Text File 또는 ⌘N (Windows, Linux Ctrl+N)).
-
여기에 다음 내용을 추가합니다.
fastapi redis types-redis uvicorn -
파일을 저장하고 (⌘S (Windows, Linux Ctrl+S))
requirements.txt로 이름을 지정합니다. -
명령 팔레트를 열고 ( ⇧⌘P (Windows, Linux Ctrl+Shift+P)) Python: Create Environment 명령을 실행하여 가상 환경을 만듭니다.
참고: 이 단계는 완료하는 데 몇 분이 걸릴 수 있습니다.
-
환경 유형을 묻는 메시지가 표시되면 Venv를 선택합니다.

-
그런 다음 컴퓨터에 설치된 최신 버전의 Python을 선택합니다.

-
드롭다운 목록에서
requirements.txt파일을 선택하여 종속성이 자동으로 설치되도록 하고, 그런 다음 OK를 선택합니다.
가상 환경이 생성되고, 종속성이 자동으로 설치되며, Python 확장 프로그램에서 사용할 작업 영역에 대한 환경이 선택됩니다. VS Code 오른쪽 하단을 확인하여 선택되었는지 확인할 수 있습니다.

참고: 상태 표시줄에서 새로 생성된 환경 정보를 찾을 수 없는 경우 Python 인터프리터 표시기를 클릭하거나 (명령 팔레트에서 Python: Select Interpreter 명령 실행) 가상 환경을 수동으로 선택할 수 있습니다.
코딩 시작
애플리케이션을 만들어 보겠습니다!
-
File > New File…을 사용하여 새 Python 파일을 만들고 Python File을 선택합니다.
-
groceries-plugin폴더에main.py로 저장합니다 (⇧⌘S (Windows, Linux Ctrl+Shift+S)). -
main.py에 다음 코드를 추가하고 파일을 저장합니다.from fastapi import FastAPI app = FastAPI() @app.get("/") def root(): return {"message": "Hello World"} -
디버거를 시작하여 (F5) 코드를 실행합니다.
-
드롭다운 메뉴에서 목록에서 FastAPI 구성 옵션을 선택합니다.

이것은 디버거를 통해 애플리케이션 서버를 시작하기 위해 uvicorn을 호출하는 디버그 구성을 자동으로 생성하고, 소스 코드를 단계별로 검사하여 동작을 검사할 수 있도록 합니다. 터미널에 다음과 같은 내용이 표시됩니다.

팁: 기본 포트가 이미 사용 중인 경우 디버거를 중지하고 명령 팔레트 (⇧⌘P (Windows, Linux Ctrl+Shift+P))를 열고 Debug: Add Configuration을 검색한 다음 Python Debugger를 선택한 다음 FastAPI를 선택합니다. 이렇게 하면
.vscode/launch.json에 사용자 지정 구성 파일이 생성되며, 이를 편집할 수 있습니다. 사용자 지정 포트를 설정하려면"args":[]에 다음을 추가합니다:"--port=5000". 파일을 저장하고 디버거를 다시 시작합니다 (F5). -
터미널에 있는
http://127.0.0.1:8000/URL을 Ctrl+Click하면 기본 브라우저로 해당 주소가 열립니다.
축하합니다! FastAPI 앱이 실행되었습니다!
-
디버그 도구 모음의 Stop 버튼을 사용하거나 (⇧F5 (Windows, Linux Shift+F5)) 디버거를 중지합니다.
식료품 목록 항목에 대한 모델 생성
이제 FastAPI 앱이 작동하므로, FastAPI와 완벽하게 통합되는 데이터 유효성 검사 및 파싱 라이브러리인 Pydantic을 사용하여 식료품 목록 항목을 정의할 수 있습니다. Pydantic을 사용하면 Python 클래스와 타입 힌트를 사용하여 데이터 모델을 정의할 수 있습니다. 이를 통해 API 요청에서 들어오는 데이터( "페이로드"라고 함)의 자동 유효성 검사 및 파싱이 가능합니다.
식료품 목록 항목에 대한 모델을 만들어 보겠습니다. ItemPayload 모델을 사용하여 식료품 목록에 추가할 항목의 데이터 구조를 정의합니다. 이 모델에는 item_id, item_name, quantity의 세 가지 필드가 있습니다.
-
File > New File…을 사용하여 새 Python 파일을 만들고 Python File을 선택합니다.
-
파일에 다음 줄을 추가한 다음
groceries-plugin폴더에models.py로 저장합니다 (⇧⌘S (Windows, Linux Ctrl+Shift+S)).from typing import Optional from pydantic import BaseModel class ItemPayload(BaseModel): item_id: Optional[int] item_name: str quantity: int
VS Code에서 Python의 기본 언어 서버인 Pylance는 Pydantic 모델 및 FastAPI 작업을 수행하는 데 유용한 타입 힌트 기능을 지원합니다. 이는 Pylance가 Python의 정적 타입 검사기인 Pyright를 기반으로 구축되었기 때문입니다. Pyright는 코드에서 타입 오류를 감지하여 버그를 방지하고 코드 품질을 개선할 수 있습니다.
아래 세 단계는 선택 사항이지만, FastAPI는 코드 가독성과 유효성 검사를 개선하기 위해 타입 힌트를 광범위하게 사용하므로 Pylance의 타입 검사 기능을 활용하여 오류를 조기에 발견할 수 있습니다.
-
설정 편집기를 엽니다 (⌘, (Windows, Linux Ctrl+,)).
-
"python type checking mode"를 검색하고
basic으로 설정하여 기본적인 타입 검사를 수행합니다. Pylance는 이제 간단한 타입 관련 오류를 잡기 위해 진단 및 경고를 표시합니다. 또는strict로 설정하여 더 고급 타입 검사 규칙을 적용할 수 있습니다.
-
다음으로 "Python inlay type hints"를 검색하고 Variable Types 및 Function Return Types에 대한 인라인 힌트를 활성화합니다.

경로 생성
이제 식료품 목록 항목을 저장할 곳이 필요합니다. 단순화를 위해 빈 사전을 사용하여 시작해 보겠습니다.
-
먼저 샘플에 필요한 모든 패키지를 가져오겠습니다.
main.py파일을 열고 첫 번째 import 줄을 다음 줄로 바꿉니다.from fastapi import FastAPI, HTTPException from models import ItemPayload -
이제
app = FastAPI()바로 아래에 다음 줄을 추가합니다.grocery_list: dict[int, ItemPayload] = {}이렇게 하면 항목 ID를
int로, 값을ItemPayload유형으로 받는 새 빈 사전을 생성합니다.이제 FastAPI 애플리케이션에 경로를 정의하겠습니다. 웹 애플리케이션의 맥락에서 경로는 특정 URL을 처리하는 코드에 매핑되는 경로와 같습니다. 이러한 경로는 애플리케이션 내의 다양한 기능에 대한 진입점 역할을 합니다. 웹 브라우저 또는 다른 프로그램과 같은 클라이언트가 특정 URL로 애플리케이션에 요청을 보내면 FastAPI는 URL에 따라 적절한 함수(경로 처리기 또는 뷰 함수라고도 함)로 해당 요청을 라우팅하고, 해당 함수는 요청을 처리하고 응답을 생성합니다.
개별 항목을 추가하고 검색하는 경로를 정의하고, 식료품 목록의 모든 항목을 반환하는 경로를 정의해 보겠습니다.
-
main.py파일 끝에 다음 경로를 추가합니다.# Route to add a item @app.post("/items/{item_name}/{quantity}") def add_item(item_name: str, quantity: int): if quantity <= 0: raise HTTPException(status_code=400, detail="Quantity must be greater than 0.") # if item already exists, we'll just add the quantity. # get all item names items_ids = {item.item_name: item.item_id if item.item_id is not None else 0 for item in grocery_list.values()} if item_name in items_ids.keys(): # get index of item_name in item_ids, which is the item_id item_id = items_ids[item_name] grocery_list[item_id].quantity += quantity # otherwise, create a new item else: # generate an ID for the item based on the highest ID in the grocery_list item_id = max(grocery_list.keys()) + 1 if grocery_list else 0 grocery_list[item_id] = ItemPayload( item_id=item_id, item_name=item_name, quantity=quantity ) return {"item": grocery_list[item_id]}이전 섹션에서 타입 힌트를 활성화한 경우 Pylance가 함수 반환 유형 및
item_ids와item_id의 유형에 대한 인라인 힌트를 추가하는 것을 볼 수 있습니다. 선택적으로 각 제안을 두 번 클릭하여 코드에 삽입할 수 있습니다.
이제 이 경로가 예상대로 작동하는지 확인해 보겠습니다. 가장 빠른 방법은 VS Code의 디버거와 FastAPI의
/docs엔드포인트를 모두 사용하는 것입니다./docs엔드포인트는 사용 가능한 모든 API 경로에 대한 정보를 제공하며 API와 상호 작용하여 매개변수 및 응답을 탐색할 수 있습니다. 이 문서는 FastAPI 애플리케이션에 정의된 메타데이터 및 타입 힌트를 기반으로 동적으로 생성됩니다. -
if quantity <= 0문 옆에 왼쪽 여백을 클릭하거나 (F9) 줄 번호 위에서 중단점을 추가합니다. 디버거는 해당 줄이 실행되기 전에 중지되므로 코드를 한 줄씩 검사할 수 있습니다.
-
디버거를 시작하고 (F5) 브라우저에서
http://127.0.0.1:8000/docs로 이동합니다.앱에서 사용 가능한 두 엔드포인트인
/items및 루트(/)가 있는 Swagger 인터페이스가 있어야 합니다.
-
/items경로 옆의 아래쪽 화살표를 선택하여 확장한 다음 오른쪽에 나타나는 Try it out 버튼을 선택합니다.
-
item_name필드에 문자열을,quantity에 숫자를 전달하여 식료품 목록 항목을 추가합니다. 예를 들어item_name에 apple,quantity에 2를 제공할 수 있습니다. -
Execute를 선택합니다.

-
VS Code를 다시 열고 디버거가 이전에 설정한 중단점에서 중지된 것을 확인합니다.

왼쪽에는 이 시점에서 정의된 모든 로컬 및 전역 변수가 **Run and Debug** 보기의 **Variables** 창에 표시됩니다. 우리 예시에서는
item_name이 'apple'로,quantity가 2로 locals 변수 보기 아래에 설정되어 있으며, globals 변수 보기 아래에는 빈grocery_list사전이 있습니다.
이제 VS Code의 디버그 콘솔을 사용하여 탐색해 보겠습니다.
-
quantity <= 0문을 선택하고 편집기에서 마우스 오른쪽 버튼을 클릭한 다음 Evaluate in Debug Console을 선택합니다.
이렇게 하면 디버그 콘솔이 열리고 선택한 식이 실행됩니다. 우리 예시에서 예상대로 식은
False로 평가됩니다.디버그 콘솔은 식을 빠르게 테스트하고 중단점 시점의 코드 상태를 더 잘 이해하는 강력한 도구가 될 수 있습니다. 함수 호출 또는 변수 인쇄와 같이 임의의 코드를 실행하는 데 사용할 수도 있습니다. VS Code에서 Python 디버깅에 대한 자세한 내용은 Python 튜토리얼에서 확인할 수 있습니다.
이제 디버그 보기 도구 모음에서 Continue를 선택하거나 (F5) 코드를 계속 실행할 수 있습니다.
마지막으로 애플리케이션의 나머지 경로를 추가하여 모든 항목 또는 특정 항목을 나열하고 식료품 목록에서 제거할 수 있도록 합니다. 디버거를 실행 상태로 둘 수 있습니다. 다음 단계에서 만드는 변경 사항을 저장하면 애플리케이션이 자동으로 다시 로드됩니다.
-
main.py의 내용을 다음 코드로 바꾸십시오.from fastapi import FastAPI, HTTPException from models import ItemPayload app = FastAPI() grocery_list: dict[int, ItemPayload] = {} # Route to add an item @app.post("/items/{item_name}/{quantity}") def add_item(item_name: str, quantity: int) -> dict[str, ItemPayload]: if quantity <= 0: raise HTTPException(status_code=400, detail="Quantity must be greater than 0.") # if item already exists, we'll just add the quantity. # get all item names items_ids: dict[str, int] = { item.item_name: item.item_id if item.item_id is not None else 0 for item in grocery_list.values() } if item_name in items_ids.keys(): # get index of item_name in item_ids, which is the item_id item_id: int = items_ids[item_name] grocery_list[item_id].quantity += quantity # otherwise, create a new item else: # generate an ID for the item based on the highest ID in the grocery_list item_id: int = max(grocery_list.keys()) + 1 if grocery_list else 0 grocery_list[item_id] = ItemPayload( item_id=item_id, item_name=item_name, quantity=quantity ) return {"item": grocery_list[item_id]} # Route to list a specific item by ID @app.get("/items/{item_id}") def list_item(item_id: int) -> dict[str, ItemPayload]: if item_id not in grocery_list: raise HTTPException(status_code=404, detail="Item not found.") return {"item": grocery_list[item_id]} # Route to list all items @app.get("/items") def list_items() -> dict[str, dict[int, ItemPayload]]: return {"items": grocery_list} # Route to delete a specific item by ID @app.delete("/items/{item_id}") def delete_item(item_id: int) -> dict[str, str]: if item_id not in grocery_list: raise HTTPException(status_code=404, detail="Item not found.") del grocery_list[item_id] return {"result": "Item deleted."} # Route to remove some quantity of a specific item by ID @app.delete("/items/{item_id}/{quantity}") def remove_quantity(item_id: int, quantity: int) -> dict[str, str]: if item_id not in grocery_list: raise HTTPException(status_code=404, detail="Item not found.") # if quantity to be removed is higher or equal to item's quantity, delete the item if grocery_list[item_id].quantity <= quantity: del grocery_list[item_id] return {"result": "Item deleted."} else: grocery_list[item_id].quantity -= quantity return {"result": f"{quantity} items removed."} -
파일을 저장하고 (⌘S (Windows, Linux Ctrl+S)) 애플리케이션이 자동으로 다시 로드됩니다.
이제 /docs 페이지를 다시 열고 디버거와 디버그 콘솔을 사용하여 코드 실행을 더 잘 이해하면서 새 경로를 테스트할 수 있습니다. 완료되면 디버거를 중지할 수 있습니다 (⇧F5 (Windows, Linux Shift+F5)). 또한 4단계에서 추가한 중단점을 클릭하여 제거할 수도 있습니다.
축하합니다! 이제 식료품 목록에 항목을 추가, 나열, 삭제하는 경로가 있는 작동하는 FastAPI 애플리케이션이 있습니다.
데이터 저장소 설정
이 시점에서 기본 기능이 있는 애플리케이션의 작동하는 버전을 이미 가지고 있습니다. 이 섹션에서는 데이터 지속성을 위한 데이터 저장소 설정을 안내하지만, 이미 배운 내용에 만족한다면 건너뛸 수 있습니다.
지금까지 데이터를 사전에 저장하고 있었지만, 애플리케이션이 다시 시작되면 모든 데이터가 손실되므로 이상적이지 않습니다.
데이터를 지속시키기 위해 오픈 소스 인메모리 데이터 구조 저장소인 Redis를 사용할 것입니다. Redis는 속도와 다재다능함 때문에 웹 애플리케이션, 실시간 분석 시스템, 캐싱 계층, 이 튜토리얼 등 광범위한 애플리케이션에서 데이터 저장 시스템으로 자주 사용됩니다.
기존 템플릿으로 GitHub Codespaces에서 이미 작업 중이라면 데이터베이스 교체 섹션으로 바로 건너뛸 수 있습니다.
Windows를 사용하는 경우 Docker 컨테이너 또는 GitHub Codespace를 설정하여 Redis를 사용할 수 있습니다. 이 튜토리얼에서는 Docker 컨테이너를 사용하지만, GitHub Codespace 설정 방법에 대한 지침은 위 섹션을 참조할 수 있습니다.
그렇지 않고 Linux 또는 macOS 머신을 사용하는 경우 웹사이트의 지침을 따라 Redis를 설치한 다음 데이터베이스 교체 섹션으로 건너뛸 수 있습니다.
Windows에서 Docker 컨테이너 설정
VS Code의 Dev Containers 확장은 프로젝트, 종속성 및 모든 필요한 도구를 하나의 깔끔한 컨테이너로 통합하는 간소화된 접근 방식을 제공하여 완전한 개발 환경을 만듭니다. 이 확장을 사용하면 컨테이너 안에서 (또는 컨테이너로 마운트된) 프로젝트를 VS Code에서 열 수 있으며, 여기에서 모든 기능을 사용할 수 있습니다.
아래 단계의 경우 컴퓨터에 다음 요구 사항이 설치되어 있는지 확인하십시오.
요구 사항
Dev 컨테이너 구성 생성
-
명령 팔레트를 열고 Dev Containers: Add Dev Container Configuration Files…을 실행합니다.
-
Python 3을 선택합니다.

-
기본 버전을 선택합니다.
-
Redis Server를 추가 기능으로 설치하도록 선택하고 OK를 누른 다음 Keep Defaults를 선택합니다.
선택적으로 컨테이너에 포함될 기능을 설치할 수 있습니다. 이 튜토리얼에서는 Redis에 대한 올바른 dev 컨테이너 설정을 설치하고 추가하는 커뮤니티 기여 기능인 Redis Server를 설치합니다.

이렇게 하면 작업 영역에
.devcontainer폴더와devcontainer.json파일이 생성됩니다. 이 파일에서 일부 편집을 수행하여 컨테이너 설정에 필요한 VS Code 확장 프로그램 설치 및 프로젝트 종속성 설치와 같은 단계가 포함되도록 하겠습니다. -
devcontainer.json파일을 엽니다. -
"features" : { ... }항목 뒤에 쉼표(`,`)를 추가하여 파일에 더 많은 설정을 추가할 수 있습니다.다음으로
devcontainer.json파일의postCreateCommand속성에 필요한 종속성 설치 명령을 추가하여 컨테이너 설정 후 애플리케이션을 실행할 준비가 되도록 합니다. -
아래 내용을 찾아서 주석(
//)을 제거하여 컨테이너가 생성될 때 종속성을 설치할 수 있도록 합니다."postCreateCommand": "pip3 install --user -r requirements.txt",postCreateCommand및 기타 수명 주기 스크립트에 대한 자세한 내용은 Development Containers 사양에서 확인할 수 있습니다.이제
customizations속성을 사용하여 컨테이너에 설치하려는 VS Code 확장을 추가합니다. -
devcontainer.json에 다음 설정을 추가합니다.// Use 'postCreateCommand' to run commands after the container is created. "postCreateCommand": "pip3 install --user -r requirements.txt", // Configure tool-specific properties. "customizations": { "vscode": { "extensions": [ "ms-python.python", //Python extension ID "ms-python.vscode-pylance" //Pylance extension ID ] } } -
파일을 저장합니다.
-
오른쪽 하단에 표시되는 알림에서 Reopen in Container를 선택하거나 명령 팔레트에서 Dev Containers: Reopen in Container 명령을 실행합니다.
참고: 인터넷 속도 및 컴퓨터 성능에 따라 컨테이너 빌드에 몇 분이 걸릴 수 있습니다.
Dev 컨테이너 구성에 대한 자세한 내용은 Dev Containers 문서에서 확인할 수 있습니다.
완료되면 Python 3 및 Redis Server가 설치된 완전 구성된 Linux 기반 작업 영역이 있습니다.
컨테이너 설정이 완료되면 VS Code 왼쪽 하단에 표시기가 표시됩니다.

참고: 확장 프로그램 보기 (⇧⌘X (Windows, Linux Ctrl+Shift+X))를 열고 Python 및 Pylance 확장이 컨테이너에 성공적으로 설치되었는지 검색하여 확인하십시오. 그렇지 않은 경우 Install in Dev Container를 실행하여 설치할 수 있습니다.
선택한 Python 인터프리터 정보는 왼쪽 하단 상태 표시줄에 있으며, devcontainer.json 파일에 지정된 버전과 일치합니다.

참고: 상태 표시줄에 Python 인터프리터 정보가 표시되지 않으면 Python 인터프리터 표시기를 클릭하거나 (명령 팔레트에서 Python: Select Interpreter 명령 실행) 컨테이너 내의 Python 인터프리터를 수동으로 선택할 수 있습니다.
이제 데이터 저장소를 교체할 다음 섹션으로 이동할 준비가 되었습니다.
데이터베이스 교체
식료품 목록 항목을 저장하는 사전이 있지만 Redis 데이터베이스로 바꾸고 싶습니다. 이 튜토리얼에서는 Redis 해시를 사용하여 데이터를 저장할 것입니다. Redis 해시는 여러 키-값 쌍을 저장할 수 있는 데이터 구조입니다.
ID를 모르면 항목을 검색할 수 있는 기존 데이터베이스와 달리 Redis 해시 키를 알아야 값을 검색할 수 있습니다. 이 튜토리얼에서는 항목 이름을 기준으로 항목을 검색하고 ID에 매핑하기 위해 item_name_to_id라는 해시를 만들 것입니다. 또한 ID별로 항목을 검색하고 이름 및 수량에 매핑하기 위해 다른 해시를 만들 것입니다. 각 항목 해시의 이름은 item_id:{item_id}이며 item_name 및 quantity 필드를 두 개 갖습니다.
먼저 사전 대신 Redis 서버에 연결하는 Redis 클라이언트 객체를 사용하여 시작하겠습니다.
-
main.py파일에서 파일 시작 부분의grocery_list: dict[int, ItemPayload] = {}을 다음 줄로 바꾸십시오.redis_client = redis.StrictRedis(host='0.0.0.0', port=6379, db=0, decode_responses=True)Redis가 아직 import되지 않았기 때문에 Pylance에서 오류 메시지가 표시됩니다.
-
편집기에서 "redis"에 커서를 놓고 표시된 전구 아이콘을 클릭하거나 (⌘. (Windows, Linux Ctrl+.)) Add 'import redis'를 선택합니다.

팁: 설정 편집기 (⌘, (Windows, Linux Ctrl+,))에서 Auto Import Completions 설정을 찾아 활성화하여 Pylance가 자동으로 import를 추가하도록 설정할 수 있습니다.
이제 로컬 호스트(`host="0.0.0.0"`)에서 실행 중이고 포트 6379(`port=6379`)에서 수신 대기하는 Redis 서버에 연결하는 Redis 클라이언트 객체가 있습니다.
db매개변수는 사용할 Redis 데이터베이스를 지정합니다. Redis는 여러 데이터베이스를 지원하며, 이 코드에서는 기본 데이터베이스인 0번 데이터베이스를 사용합니다. 또한 응답이 문자열(바이트 대신)로 디코딩되도록decode_responses=True를 전달합니다.첫 번째 경로
add_item에 대한 코드를 더 많이 바꿔보겠습니다. 항목 이름을 찾기 위해 사전의 모든 키를 살펴보는 대신 Redis 해시에서 직접 해당 정보를 가져올 수 있습니다.item_name_to_id해시가 이미 존재하여 항목 이름을 ID에 매핑한다고 가정합니다(걱정하지 마세요. 곧 이 코드를 추가할 것입니다!). 그런 다음 Redis의hget메서드를 호출하여 요청에서 받는 항목 이름의 ID를 가져올 수 있습니다. 이 메서드는 요청된 이름이 해시에 이미 존재하는 경우 항목 ID를 반환하거나 존재하지 않으면None을 반환합니다. -
아래 내용이 있는 줄을 삭제합니다.
items_ids = {item.item_name: item.item_id if item.item_id is not None else 0 for item in grocery_list.values()}다음으로 바꿉니다.
item_id = redis_client.hget("item_name_to_id", item_name)Pylance가 이 변경으로 인해 문제를 제기하는 것을 알 수 있습니다. 이는
hget메서드가str또는None(항목이 존재하지 않는 경우)을 반환하기 때문입니다. 그러나 아직 바꾸지 않은 코드 아래 줄은item_id가int유형일 것으로 예상합니다.item_id심볼의 이름을 바꿔서 이 경고를 해결하겠습니다. -
item_id를item_id_str로 이름을 바꿉니다. -
인라인 힌트가 활성화된 경우 Pylance는
item_id_str옆에 변수 유형 힌트를 표시해야 합니다. 선택적으로 두 번 클릭하여 수락할 수 있습니다.
-
항목이 존재하지 않으면
item_id_str은None입니다. 따라서 다음과 같은 내용이 있는 줄을 삭제할 수 있습니다.if item_name in items_ids.keys():다음으로 바꿉니다.
if item_id_str is not None:이제 항목 ID를 문자열로 가져왔으므로
int로 변환하고 항목의 수량을 업데이트해야 합니다. 현재 Redis 해시는 항목 이름을 ID에만 매핑합니다. 항목 ID를 이름 및 수량에 매핑하려면 ID별 검색을 더 쉽게 하기 위해"item_id:{item_id}"를 해시 이름으로 사용하여 각 항목에 대한 별도의 Redis 해시를 만듭니다. 또한 이러한 해시에item_name및quantity필드를 추가합니다. -
if블록 내의 코드를 삭제합니다.item_id: int = items_ids[item_name] grocery_list[item_id].quantity += quantity다음 내용을 추가하여
item_id를int로 변환하고 Redis의hincrby메서드를 호출하여 항목의 수량을 증가시킵니다. 이 메서드는 요청(quantity)의 주어진 양만큼"quantity"필드의 값을 증가시킵니다.item_id = int(item_id_str) redis_client.hincrby(f"item_id:{item_id}", "quantity", quantity)이제
item_id_str이None인 경우 항목이 존재하지 않을 때의 코드를 바꿔야 합니다. 이 경우 새item_id를 생성하고 항목에 대한 새 Redis 해시를 만든 다음 제공된 항목 이름과 수량을 추가합니다.새
item_id를 생성하기 위해 Redis의incr메서드를 사용하고 `"item_ids"`라는 새 해시를 전달합니다. 이 해시는 마지막으로 생성된 ID를 저장하는 데 사용되므로 새 항목을 만들 때마다 증가시켜 모든 항목에 고유한 ID가 있도록 합니다. -
다음 내용이 있는 줄을 삭제합니다.
item_id: int = max(grocery_list.keys()) + 1 if grocery_list else 0다음으로 바꿉니다.
item_id: int = redis_client.incr("item_ids")이
incr호출이item_ids키와 함께 처음 실행되면 Redis는 키를 생성하고 값을1에 매핑합니다. 그런 다음, 이후에 실행될 때마다 저장된 값을 1씩 증가시킵니다.이제
hset메서드를 사용하고 필드(item_id,item_name,quantity) 및 값(항목의 새로 생성된 ID, 제공된 이름 및 수량)에 대한 매핑을 제공하여 Redis 해시에 항목을 추가합니다. -
다음 내용이 있는 줄을 삭제합니다.
grocery_list[item_id] = ItemPayload( item_id=item_id, item_name=item_name, quantity=quantity )다음으로 바꿉니다.
redis_client.hset( f"item_id:{item_id}", mapping={ "item_id": item_id, "item_name": item_name, "quantity": quantity, })이제 새로 생성된 ID를 항목 이름에 매핑하기 위해 처음에 참조한 해시
item_name_to_id를 설정하기만 하면 됩니다. -
else블록 안에 이 줄을 경로 끝에 추가합니다.redis_client.hset("item_name_to_id", item_name, item_id) -
다음 내용이 있는 줄을 삭제합니다.
return {"item": grocery_list[item_id]}다음으로 바꿉니다.
return {"item": ItemPayload(item_id=item_id, item_name=item_name, quantity=quantity)} -
원하는 경우 다른 경로에 대해서도 비슷한 교체를 시도할 수 있습니다. 그렇지 않으면 파일 전체를 다음 줄로 바꿀 수 있습니다.
import redis from fastapi import FastAPI, HTTPException from models import ItemPayload app = FastAPI() redis_client = redis.StrictRedis(host="0.0.0.0", port=6379, db=0, decode_responses=True) # Route to add an item @app.post("/items/{item_name}/{quantity}") def add_item(item_name: str, quantity: int) -> dict[str, ItemPayload]: if quantity <= 0: raise HTTPException(status_code=400, detail="Quantity must be greater than 0.") # Check if item already exists item_id_str: str | None = redis_client.hget("item_name_to_id", item_name) if item_id_str is not None: item_id = int(item_id_str) redis_client.hincrby(f"item_id:{item_id}", "quantity", quantity) else: # Generate an ID for the item item_id: int = redis_client.incr("item_ids") redis_client.hset( f"item_id:{item_id}", mapping={ "item_id": item_id, "item_name": item_name, "quantity": quantity, }, ) # Create a set so we can search by name too redis_client.hset("item_name_to_id", item_name, item_id) return { "item": ItemPayload(item_id=item_id, item_name=item_name, quantity=quantity) } # Route to list a specific item by ID but using Redis @app.get("/items/{item_id}") def list_item(item_id: int) -> dict[str, dict[str, str]]: if not redis_client.hexists(f"item_id:{item_id}", "item_id"): raise HTTPException(status_code=404, detail="Item not found.") else: return {"item": redis_client.hgetall(f"item_id:{item_id}")} @app.get("/items") def list_items() -> dict[str, list[ItemPayload]]: items: list[ItemPayload] = [] stored_items: dict[str, str] = redis_client.hgetall("item_name_to_id") for name, id_str in stored_items.items(): item_id: int = int(id_str) item_name_str: str | None = redis_client.hget(f"item_id:{item_id}", "item_name") if item_name_str is not None: item_name: str = item_name_str else: continue # skip this item if it has no name item_quantity_str: str | None = redis_client.hget( f"item_id:{item_id}", "quantity" ) if item_quantity_str is not None: item_quantity: int = int(item_quantity_str) else: item_quantity = 0 items.append( ItemPayload(item_id=item_id, item_name=item_name, quantity=item_quantity) ) return {"items": items} # Route to delete a specific item by ID but using Redis @app.delete("/items/{item_id}") def delete_item(item_id: int) -> dict[str, str]: if not redis_client.hexists(f"item_id:{item_id}", "item_id"): raise HTTPException(status_code=404, detail="Item not found.") else: item_name: str | None = redis_client.hget(f"item_id:{item_id}", "item_name") redis_client.hdel("item_name_to_id", f"{item_name}") redis_client.delete(f"item_id:{item_id}") return {"result": "Item deleted."} # Route to remove some quantity of a specific item by ID but using Redis @app.delete("/items/{item_id}/{quantity}") def remove_quantity(item_id: int, quantity: int) -> dict[str, str]: if not redis_client.hexists(f"item_id:{item_id}", "item_id"): raise HTTPException(status_code=404, detail="Item not found.") item_quantity: str | None = redis_client.hget(f"item_id:{item_id}", "quantity") # if quantity to be removed is higher or equal to item's quantity, delete the item if item_quantity is None: existing_quantity: int = 0 else: existing_quantity: int = int(item_quantity) if existing_quantity <= quantity: item_name: str | None = redis_client.hget(f"item_id:{item_id}", "item_name") redis_client.hdel("item_name_to_id", f"{item_name}") redis_client.delete(f"item_id:{item_id}") return {"result": "Item deleted."} else: redis_client.hincrby(f"item_id:{item_id}", "quantity", -quantity) return {"result": f"{quantity} items removed."} -
디버거를 다시 실행하여
/docs경로와 상호 작용하여 이 애플리케이션을 테스트합니다. 완료되면 디버거를 중지할 수 있습니다.
축하합니다! 이제 식료품 목록에 항목을 추가, 나열, 삭제하는 경로가 있는 작동하는 FastAPI 애플리케이션이 있으며 데이터는 Redis 데이터베이스에 지속됩니다.
선택 사항: 데이터베이스 삭제 설정
데이터가 Redis에 의해 지속되므로 테스트 데이터를 지우는 스크립트를 만들고 싶을 수 있습니다. 그렇게 하려면 다음 내용으로 flushdb.py라는 새 파일을 만듭니다.
import redis
redis_client = redis.StrictRedis(host='0.0.0.0', port=6379, db=0, decode_responses=True)
redis_client.flushdb()
그런 다음 데이터베이스를 재설정하려면 VS Code에서 flushdb.py 파일을 열고 편집기 오른쪽 상단의 Run 버튼을 선택하거나 명령 팔레트에서 Python: Run Python File in Terminal 명령을 실행할 수 있습니다.
프로덕션에서 수행하는 경우 데이터 손실로 이어질 수 있으므로 현재 데이터베이스의 모든 키를 삭제하므로 주의해서 수행해야 합니다.
선택 사항: GPT 작업 생성
GitHub Codespaces를 사용하면 GPT Actions를 사용할 때 테스트 목적으로 애플리케이션을 호스팅할 수 있습니다. GPT Actions는 ChatGPT가 기존 API와 상호 작용하여 ChatGPT의 기능을 향상시켜 다양한 작업을 수행할 수 있도록 하는 도구입니다. 아래 라이브 스트림 녹화를 따라 ChatGPT용 식료품 목록 플러그인을 만들 수 있습니다.
참고: 모든 개인 GitHub.com 계정에는 무료 또는 Pro 요금제에 포함된 GitHub Codespaces의 월별 무료 사용 할당량이 있습니다. 자세한 내용은 GitHub Codespaces 청구 정보를 참조하십시오.
다음 단계
이 튜토리얼을 따라와 주셔서 감사합니다! FastAPI와 VS Code에서 사용하는 방법에 대해 새로운 것을 배우셨기를 바랍니다.
이 튜토리얼의 완성된 코드 프로젝트는 GitHub에서 찾을 수 있습니다: python-sample-vscode-fastapi-tutorial.
공식 문서에서 FastAPI에 대해 자세히 알아보세요.
프로덕션 웹사이트에서 앱을 사용해 보려면 Docker 컨테이너를 사용하여 Azure App Service에 Python 앱 배포 튜토리얼 를 확인하십시오.
다음 VS Code Python 기사도 검토할 수 있습니다.