몇 가지 주요 키워드 단어 비스무리한 거 정리했다
파이썬 웹 서버로 ASGI 웹앱(FastAPI 등)을 실행한다고 한다
웹 서버 게이트웨이 인터페이스의 준말이다
HTTP 요청/응답만 다루는 동기 표준이다
Flask, Django가 여기에 맞춰져 있다고 하며 보통 Gunicorn/uwsgi/Waitress 같은 WSGI 서버로 띄운다
그냥 평범한 코드처럼 차례대로 처리하는 거 말하는 거 같다
비동기(Asynchro) 서버 게이트웨이 인터페이스의 준말이다
최신 비동기 표준으로
HTTP + WebSocket + (서버 시작/종료 이벤트 등) 을 함께 다룰 수 있게 확장됐다고 한다
FastAPI/Starlette, Django(3.x+)의 ASGI 모드가 여기에 맞고, 보통 Uvicorn/Hypercorn/Daphne 같은 ASGI 서버를 쓴단다
루프 돌면서 여러 요청 처리하는 느낌이다
요청 처리 방식 차이
WSGI : 각 요청이 스레드 프로세스 단위로 처리되는게 일반적
def app(environ, start_response):
start_response("200 OK", [("Content-Type", "text/plain")])
return [b"hello"]
ASGI : 하나의 이벤트 루프에서 다수의 요청을 동시에 처리. 웹소켓도 동일한 인터페이스로 핸들링
async def app(scope, receive, send):
if scope["type"] == "http":
await send({"type": "http.response.start", "status": 200, "headers": []})
await send({"type": "http.response.body", "body": b"hello"})
무엇을 언제 쓰냐?
ASGI가 유리한 경우
웹소켓/서버이벤트 등 실시간 기능
외부 I/O 많이 기다리는 서비스(다양한 API/Mongo DB 등)에서 효율 증가
FastAPI, Starlette, Django Channels 등 사용
WSGI로 충분한 경우
단순 CRUD, 동기 ORM/라이브러리 중심
기존 Flask/Django 프로젝트 그대로 운영
ASGI에서 블로킹 I/O 그냥 쓰면 이벤트 루프가 멈추니 await 가능한 비동기 드라이버 쓰거나 별도 작업 스레드에서 실행시키는 등 다른 방법 필요하다
ASGI가 CPU 작업 자동으로 빨라지게 해주는 건 아니기에 멀티프로세스/작업큐로 분리하는게 정석이라고 한다
프론트엔드 개발 서버로 HMR(저장->화면 즉시 갱신)이 빠르다
배포용 서버가 아닌 개발 편의를 위한 임시 서버다
배포할땐 vite build로 정적 파일 만든 뒤 Nginix 등 제공한다
드라이버는 애플리케이션이 DB와 대화(네트워크 프로토콜) 하도록 도와주는 라이브러리다
동기 : DB 호출이 끝날 떄까지 요청이 멈춰 있다
비동기 : DB 응답을 기다리는 동안 같은 프로세서가 다른 요청 처리 가능 -> I/O 많은 웹서버에서 동시성 처리 효율이 좋다고 한다
파이썬에서는
pymongomotor입력/출력 데이터 모델과 검증 해주는 라이브러리다
title은 빈 문자열이면 안되며 길이는 100자 이하여야 하고… 등을 자동 검사 해준다
Cross-Origin Resource Sharing: 브라우저 보안 정책
다른 출처(포트/도메인) 에서 API 호출 시 서버가 허용 목록을 열어줘야 한다
프론트, 백엔트 포트 다르거나 하면 사용한다
MongoDB에 문서 찾고/넣고/고치고/지우는 명령들을 말한다
# 목록
cursor = db.posts.find().skip(0).limit(20).sort("_id", -1)
posts = [doc async for doc in cursor]
# 생성
res = await db.posts.insert_one({"title": "hi", "body": "..."})
# 단건 조회
doc = await db.posts.find_one({"_id": ObjectId(pid)})
# 업데이트
upd = await db.posts.find_one_and_update(
{"_id": ObjectId(pid)}, {"$set": {"title": "new"}}, return_document=True
)
# 삭제
await db.posts.delete_one({"_id": ObjectId(pid)})