이전 내용
[FastAPI] 미들웨어(middleware) - 3: GZip
이전 내용 [FastAPI] 미들웨어(middleware) - 2: CORS이전 내용 [FastAPI] 미들웨어(middleware) - 1: TrustedHostMiddleware이전 내용 [FastAPI] 캐싱(caching)이전 내용 [FastAPI] 파일 업로드이전 내용 [FastAPI] 비동기 처리 (as
puppy-foot-it.tistory.com

1. 비동기 프로그래밍 활용
FastAPI는 비동기 프로그래밍을 지원하는 매우 빠르고 효율적인 웹 프레임워크다. 그러나 애플리케이션의 규모가 커지거나 트래픽이 증가하면 성능 저하가 발생할 수 있다.
FastAPI의 가장 큰 장점 중 하나는 비동기 프로그래밍을 지원한다는 점이다. 비동기 프로그래밍을 통해 동시에 여러 작업을 처리할 수 있으며, 특히 I/O 바운드 작업에서 성능을 크게 향상시킬 수 있다.
비동기 프로그래밍은 특히 RESTful API를 구현할 때 유용하다. 그러나 비동기 코드는 디버깅이 복잡할 수 있고, 예외 처리를 잘해야 한다.
- async/await 구문 사용: 비동기 작업을 정의할 때 async와 await 키워드를 사용.
- 제대로된 예외 처리 필요: try / except 블록을 사용한 네트워크 문제나 타임아웃 처리
- 비동기 작업의 개수 조절: 비동기 작업을 너무 많이 실행하면 시스템에 부하를 줄 수 있으므로 작업의 개수를 적절히 조절하는 것이 중요.
- 비동기 라이브러리 활용: 데이터베이스, HTTP 요청 등 I/O 작업에는 비동기 라이브러리 사용. 예: httpx, asyncpg와 같은 라이브러리를 활용하여 비동기 HTTP 클라이언트와 PostgreSQL 데이터베이스를 사용할 수 있다.
from fastapi import FastAPI
import httpx
app = FastAPI()
@app.get("/async-endpoint")
async def async_endpoint():
async with httpx.AsyncClient() as client:
response = await client.get("https://example.com")
return {"data": response.json()}
- FastAPI 모듈과 비동기 HTTP 클라이언트 라이브러리인 httpx를 임포트.
- app = FastAPI(): FastAPI 애플리케이션 인스턴스 생성.
- /async-endpoint라는 경로에 대한 GET 요청을 처리하는 비동기 함수 정의. 이 경로의 요청이 들어오면 해당 함수가 실행됨.
- async with httpx.AsyncClient() as client: 구문을 통해 비동기 HTTP 클라이언트를 생성하고, 클라이언트를 사용하여 외부 API에 GET 요청을 보냄.
- await client.get("[https://example.com](https://example.com)")를 사용하여 요청의 결과를 기다림. 비동기 함수 내에서 await를 사용할 수 있다.
- 응답(JSON 형식)을 반환. { "data": response.json() } 형태로 JSON 데이터를 클라이언트에 전달.
2. 캐싱 활용
캐싱은 자주 사용하는 데이터에 대한 접근 속도를 높이기 위해 사용된다. 데이터나 계산 결과가 자주 변경되지 않는 경우, 캐싱 기술을 이용하여 애플리케이션의 성능을 향상시킬 수 있다. 캐싱은 불필요한 데이터 재계산이나 재요청을 줄임으로써 응답 속도를 개선하고, 서버 부하를 감소시키는 효과적인 방법이다.
그러나. 캐싱은 잘못 관리되면 오래된 정보를 제공하거나 데이터 일관성 문제를 일으킬 수 있어 캐싱 전략이 계획 및 구현되는 것이 필요하다.
FastAPI에서는 다양한 캐싱 전략을 활용할 수 있다.
- HTTP 헤더 사용: FastAPI에서는 내장된 캐싱을 지원하지 않으므로, HTTP 헤더를 설정해 캐싱 동작을 제어한다.
- 데이터 유효성: 캐싱된 데이터가 오래된 경우, 그 데이터는 더 이상 정확하지 않을 수 있으므로, 데이터의 신선도를 유지하기 위해 적절한 만료 시간(expire time) 설정
- 스케일링: 서비스가 성장하고 트래픽이 증가할 경우, 단일 인스턴스의 메모리 기반 캐싱에는 한계가 있으므로 분산 캐싱 시스템 (예. Redis)을 고려
- 캐시 무효화: 중요한 데이터가 변경되었을 때 관련된 캐시를 무효화하는 전략 필요. (일반적으로 캐시 키는 특정 패턴을 따라 생성되며, 데이터가 변경될 때 해당 키와 관련된 캐시를 삭제 또는 업데이트 해야 한다.)
from fastapi import FastAPI
from fastapi.responses import JSONResponse
app = FastAPI()
@app.get("/cached-response")
def cached_response():
content = {"message": "This is a response that can be cached."}
headers = {
"Cache-Control" : "public, max-age=60",
}
return JSONResponse(content=content, headers=headers)
- @app.get("cached-response") 데코레이터: /cached-response 경로로 GET 요청을 받으면 JSON 형식의 메시지를 반환하도록 설정
- Cache-Control 헤더: 응답이 최대 60초 (max-age) 동안 캐시될 수 있도록 설정
3. 데이터베이스 커넥션 풀링
데이터베이스 커넥션 풀링은 데이터베이스와의 연결을 효율적으로 관리하여 성능을 향상시키는 기법으로, 데이터베이스에 필요할 때마다 새로운 커넥션을 열고 닫는 게 아니라, 미리 여러 개의 커넥션을 열어두고 필요할 때 이를 재활용하는 방식이다. 따라서 많은 수의 요청이 동시에 들어올 때 새로운 연결을 생성하는 데 드는 오버헤드를 줄일 수 있고, 시스템 리소스를 절약하고 응답 시간을 줄일 수 있다.
- DB Connection Pool 사용: FastAPI와 함께 사용할 수 있는 ORM 및 데이터베이스 라이브러리에서 커넥션 풀링을 지원. 예: SQLAlchemy에서는 create_engine과 함께 pool_size와 같은 매개변수를 설정하여 커넥션 풀을 구성할 수 있다.
- 커넥션 재사용: pool_size와 max_overflow 설정으로 미리 생성된 커넥션 재사용 가능. ▶ 새로운 커넥션을 매번 열고 닫는 오버헤드 감소
- 타임아웃 관리: pool_timeout 옵션을 통해 커넥션을 얻기 위한 대기 시간 관리. ▶ 시스템이 과부하 상태일 때 불필요한 대기 시간 감소
- 커넥션 재활용: pool_recycle 옵션을 통해 일정 시간 동안 사용되지 않은 커넥션을 자동으로 닫아 리소스를 효율적으로 관리.
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "postgresql://user:password@localhost/dbname"
engine = create_engine(DATABASE_URL, pool_size=20, max_overflow=0)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
@app.get("/data")
def get_data():
db = SessionLocal()
# 데이터베이스 쿼리 로직
db.close()
- SQLAlchemy의 create_engine과 sessionmaker를 임포트. SQLAlchemy는 Python SQL Toolkit.
- PostgreSQL 데이터베이스에 연결하기 위한 URL을 정의. 실제 데이터베이스 정보 입력 필요.
- create_engine을 호출하여 데이터베이스 엔진 생성. pool_size=20은 커넥션 풀에서 최대 20개의 커넥션을 유지하도록 설정. max_overflow=0은 추가적인 커넥션을 더 이상 만들지 않겠다는 의미.
- sessionmaker를 사용하여 데이터베이스 세션을 생성하는 클래스 정의. 이 클래스는 세션을 효율적으로 생성하여 데이터베이스 작업을 수행할 수 있게 한다. autocommit=False와 autoflush=False는 트랜잭션 처리를 제어하기 위한 설정.
- /data라는 경로에 대한 GET 요청을 처리하는 함수 정의.
- 이 함수 내부에서 SessionLocal()을 호출하여 데이터베이스 세션 생성.
- 데이터베이스 작업이 끝난 후 세션 종료.
★ create_engine() 함수 관련 옵션
- url: 데이터베이스에 연결하기 위한 URL로, 데이터베이스의 유형, 사용자 이름, 비밀번호, 호스트명, 포트, 데이터베이스 이름을 포함.
- echo: SQLAlchemy가 실행하는 모든 SQL 명령어를 콘솔에 출력 여부 설정. 디버깅에 유용하게 사용된다. (True 또는 False)
- pool_size: 커넥션 풀에 유지할 수 있는 커넥션의 최대 수를 설정. 기본값은 5.
- max_overflow: pool_size를 초과하여 생성할 수 있는 추가 커넥션의 수 설정. 기본값은 10.
- pool_timeout: 풀에서 사용 가능한 커넥션을 기다리는 최대 시간을 초 단위로 설정. 기본값은 30초.
- pool_recycle: 주어진 시간(초) 후에 활성 커넥션을 재활용하는 설정. 데이터베이스 서버의 타임아웃을 피하는 데 도움.
- connect_args: 데이터베이스 연결 시 사용할 추가 인자 설정. 다양한 데이터베이스 드라이버에 따라 다르게 설정될 수 있다.
- execution_options: 세션에서의 SQL 명령어 실행 시 추가적인 옵션을 설정할 수 있다. 예: autocommit 설정.
- future: SQLAlchemy 2.0에서 새 기능을 사용할지를 설정하는 옵션으로, 기본값은 False이며 True로 설정하면 SQLAlchemy 2.0의 새로운 API가 활성화.
4. 기타 방안
4.1. 정적 파일 제공
FastAPI에서는 StaticFiles 미들웨어를 사용하여 정적 파일을 제공할 수 있다. 정적 파일을 CDN(Content Delivery Network)에서 제공하거나 서버와 분리하여 성능을 향상시킬 수 있다.
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
app = FastAPI()
# 정적 파일 제공을 위해 /static 경로를 설정.
app.mount("/static", StaticFiles(directory="static"), name="static")
@app.get("/")
def read_root():
return {"message": "Welcome to the FastAPI application! Access static files at /static"}
- FastAPI와 StaticFiles 임포트.
- FastAPI 애플리케이션 인스턴스 생성.
- /static 경로를 설정하여 static 디렉토리의 파일들 제공.
- 루트 경로에 대한 간단한 GET 요청 메서드 정의.
4.2. API Gateway 활용
API Gateway는 요청을 효율적으로 분배하고, 인증, 로깅 등 다양한 기능을 처리할 수 있다. AWS API Gateway, Nginx와 같은 해결책을 사용하여 FastAPI 애플리케이션의 성능을 높일 수 있다.
4.3. Load Balancing
로드 밸런서를 사용하여 여러 FastAPI 서버 인스턴스에 요청을 분산시키는 방법도 있다. 이를 통해 수평 확장과 관련된 성능 향상을 기대할 수 있다.
server {
listen 80;
server_name your_domain.com;
location / {
proxy_pass http://localhost:8000; # FastAPI 앱의 URL
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;
}
}
- listen 80: HTTP 요청을 80 포트에서 수신.
- server_name: 요청을 처리할 도메인 명 지정.
- location /: 들어오는 요청을 처리하는 위치 블록 설정.
- proxy_pass: FastAPI 애플리케이션이 실행 중인 서버로 요청 전달.
4.4. ASGI 서버 최적화
Uvicorn과 같은 ASGI 서버의 설정을 최적화하면 FastAPI의 응답 시간을 단축시킬 수 있다. 워커 수, 포트 수 등 서버 설정을 조정하여 성능을 향상시킬 수 있다.
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
- --host: 명시된 IP 주소에서 수신하도록 설정.
- --port: 애플리케이션이 사용할 포트를 설정.
- --workers: 동시에 여러 개의 워커 프로세스를 실행하여 성능 향상.
[참고]
가장 빠른 풀스택을 위한 플라스크 & FastAPI
다음 내용
'[파이썬 Projects] > <파이썬 웹개발>' 카테고리의 다른 글
[파이썬] FastAPI - 메모 앱 프로젝트 2: CRUD 구현 (0) | 2025.05.09 |
---|---|
[파이썬] FastAPI - 메모 앱 프로젝트 1: 초기 설정, DB 연동 (0) | 2025.05.09 |
[파이썬] FastAPI - 미들웨어(middleware) - 3: GZip (0) | 2025.05.08 |
[파이썬] FastAPI - 미들웨어(middleware) - 2: CORS (0) | 2025.05.08 |
[파이썬] FastAPI - 미들웨어(middleware) - 1: TrustedHostMiddleware (0) | 2025.05.08 |