ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python Backend] FastAPI를 이해하기 위한 비동기 처리 개념 정리
    WEB 2025. 5. 25. 09:39
    728x90
    [python backend] FastAPI를 이해하기 위한 비동기 처리 개념 정리 

     

     

    그렇다 FastAPI가 빠른 이유는 비동기 지원으로 인한 것 

    그럼 당최 비동기란 뭐고 그거 어떻게 하는 건데? 

     

    * 이전 포스트에서 이어집니다 (https://asidefine.tistory.com/330)

    * 이후 포스트로 이어집니다 (https://asidefine.tistory.com/328) (https://asidefine.tistory.com/334)

     

     

    1. 동기(Synchronous) vs 비동기(Asynchronous)

    동기

    • 작업이 순차적으로 실행됨
    • A 작업이 끝나야만 B 작업이 실행 가능
    • CPU는 일을 하지 않고 대기 중일 수도 있음
     
    def cook():
        boil_water()
        cook_rice()
        serve()
    
    cook()  # 위 작업은 순차적으로 실행됨

     

    비동기

    • 작업 간의 대기가 있을 경우, 그 시간에 다른 작업을 처리함
    • I/O(입출력) 대기 시간 동안 CPU가 다른 작업 처리 가능
    • 사용자 경험(UX) 개선에 도움됨

     

    async def cook():
        await boil_water()
        await cook_rice()
        await serve()

     

    2. 동시성(Concurrency) vs 병렬성(Parallelism)

     

    동시성

    • 한 번에 하나의 작업만 처리하지만 여러 작업을 짧은 시간 간격으로 번갈아 수행
    • 멀티태스킹처럼 보이지만 실제로는 빠른 스위칭
    • 코루틴이나 스레드를 이용해 구현 가능

     

    병렬성

    • 여러 작업을 동시에 실행함
    • 멀티코어 CPU 환경에서 여러 프로세스가 각기 다른 코어에서 동시 실행
    • CPU 바운드 작업에서 효과적
        동시성 병렬성
      사용 자원 하나의 CPU (단일코어) 여러 CPU (멀티코어)
      구현 방법 코루틴, 스레드 멀티프로세스
      적합한 작업 I/O 바운드 CPU 바운드
       

     

    3. 파이썬 비동기 프로그래밍 핵심: 코루틴과 async/await

     

    코루틴이란?

    • 일반 함수처럼 생겼지만 중간에 멈췄다가 다시 실행할 수 있음
    • async def로 정의된 함수는 코루틴 객체 반환
    • 코루틴 객체는 await 키워드로 실행
       
       
    async def say_hello():
        print("Hello")
        await asyncio.sleep(1)
        print("World")
    
    asyncio.run(say_hello())

     

    await의 역할

    • 다른 비동기 작업이 끝날 때까지 기다림
    • 동기적으로 보면 멈춘 것 같지만, 실제로는 그동안 다른 코루틴이 실행됨

     

    4. asyncio: 파이썬 비동기 실행의 핵심 모듈

    asyncio가 필요한 이유

    • 코루틴은 단독으로 실행되지 않음
    • 이벤트 루프를 통해 실행 스케줄링이 필요
    • asyncio가 이 역할을 담당

     

    주요 함수 및 메커니즘

    • asyncio.run(coro): 메인 루프 실행
    • asyncio.create_task(coro): 작업 등록 (백그라운드 실행)
    • asyncio.gather(*coros): 여러 코루틴을 병렬로 실행 
       
    import asyncio
    
    async def job(name, delay):
        print(f"{name} 시작")
        await asyncio.sleep(delay)
        print(f"{name} 종료")
    
    async def main():
        await asyncio.gather(
            job("A", 2),
            job("B", 1),
            job("C", 3)
        )
    
    asyncio.run(main())
    • 실행 순서
      • A, B, C 순차 시작
      • 각각 await로 멈추는 동안 다른 작업 실행
      • 전체 실행 시간은 가장 오래 걸리는 작업 시간만큼

     

    5. FastAPI에서 async 활용하기
    • FastAPI란?
      • Python 기반 비동기 웹 프레임워크
      • async def 함수 기반으로 경량 HTTP 서버를 빠르게 구성 가능
      • Pydantic을 이용한 데이터 검증, 자동 문서화(OpenAPI 지원) 포함
    • 동기/비동기 핸들러 비교
    from fastapi import FastAPI
    import asyncio
    
    app = FastAPI()
    
    @app.get("/sync")
    def sync_route():
        import time
        time.sleep(1)
        return {"message": "sync"}
    
    @app.get("/async")
    async def async_route():
        await asyncio.sleep(1)
        return {"message": "async"}
    • /sync: sleep 동안 서버는 블로킹됨
    • /async: sleep 중 다른 요청을 처리 가능

     

    • 언제 async로 작성해야 할까?
      • 외부 API 요청
      • 파일, 데이터베이스, 네트워크 I/O
      • 사용자 요청이 많을 때 병렬 처리 필요할 경우

     

    6. uvicorn: FastAPI를 실행하는 ASGI 서버
    • FastAPI는 API를 정의하는 웹 애플리케이션 프레임워크라면, Uvicorn은 이 FastAPI 앱을 실행시키는 웹 서버(ASGI 서버)다 
      FastAPI Uvicorn
    종류 웹 프레임워크 ASGI 서버 (웹 서버)
    역할 라우팅, 요청 처리, API 로직 정의 클라이언트 요청을 받고 FastAPI에 전달, 응답 반환
    예시 /hello 요청 시 어떤 함수를 실행할지 정의 클라이언트로부터 HTTP 요청을 받아 FastAPI에게 전달
    실행 방법 코드로 정의만 함 (FastAPI() 인스턴스 생성) uvicorn main:app 명령어로 실행
    비유 "앱의 본체 (뇌와 몸)" "앱을 외부에 노출시키는 입구 (입과 귀)"
    ❓ 웹 서버가 뭔데 ?

    - 인터넷을 통해서 브라우저의 요청을 받아, 요청한 웹페이지, API Responsse, 파일 등을 반환해주는 소프트웨어
    - 정적 웹 서버 : Nginx, Apache
    - 동적 웹 서버 (Python용) : Uvicorn (ASGI), Gunicorn (WSGI)

     

    • WSGI vs ASGI이란 ? 
      • WSGI(Flask, Django):
        • Web Server Gateway Interface
        • 동기만 지원
      • ASGI(FastAPI):
        • Asynchronous Server Gateway Interface
        • 비동기 지원 → 고성능 I/O 처리 가능

     

    •  uvicorn이란?
      • ASGI 서버로, FastAPI 같은 비동기 프레임워크 실행을 담당
      • 기본적으로 비동기 코드를 빠르게 실행하고 요청을 비동기적으로 처리함
    • 실행 명령 
    uvicorn main:app --reload
    # main: 파일 이름 (main.py)
    # app: FastAPI 객체
    # uvicorn main:app --reload

     

    • uvicorn 내부 동작 
      • 실제로도 비동기를 위해서 asyncio를 사용해서 비동기 함수 실행 시킴 - 이를 통해 별도의 Thread 생성 없이 동시성 구현
    #https://github.com/encode/uvicorn/blob/master/uvicorn/server.py#L51
    class Server:
        ...
        def run(self, sockets: list[socket.socket] | None = None) -> None:
            self.config.setup_event_loop()
            return asyncio.run(self.serve(sockets=sockets))

     

     

     


    • 마무리 정리: 전체 개념 흐름
    1. 동기 vs 비동기
      → 작업 흐름과 기다림의 차이
    2. 동시성 vs 병렬성
      → 하나의 CPU로도 동시처리 가능 (코루틴), 병렬은 멀티코어 필요
    3. async/await 문법
      → 파이썬에서 비동기 코드를 작성하는 공식적인 방법
    4. asyncio
      → 코루틴을 실행 및 관리하는 이벤트 루프 제공
    5. FastAPI
      → async 기반으로 고성능 웹 서버 구성 가능
    6. uvicorn
      → FastAPI를 실행시키는 고성능 ASGI 서버

     

     

    Reference. 

     

    728x90
Designed by Tistory.