[FastAPI] 동기와 비동기, 코루틴 개념 정리

2024. 3. 3. 23:41·Minding's Programming/FastAPI
728x90
반응형

FastAPI를 본격적으로 사용해보기에 앞서 알아보아야 할 개념인 동기와 비동기의 차이, 그리고 코루틴 함수에 대해서 공부해보았다.

 

동기와 비동기

- 동기(sync)

'코드가 동기적으로 동작한다'라는 말의 뜻은 '코드가 반드시 작성된 순서로 실행된다.'라는 뜻과 동일하다고 생각하면 된다. A,B,C의 순서로 코드가 작성되어 있다면, A 함수가 실행되고 끝나면 B가 실행되는 플로우로 진행된다.

import time


def delivery(name, mealtime):
    print(f"{name}에게 배달완료!")
    time.sleep(mealtime)  # n초 대기
    print(f"{name} 식사완료, {mealtime}시간 소요...")
    print(f"{name} 그릇 수거 완료")


def main():
    delivery("A", 3)
    delivery("B", 3)
    delivery("C", 4)


if __name__ == "__main__":
    start = time.time()  # 시작 시간(해당 시점 현재시간)
    main()
    end = time.time()  # 끝난 시간(현재시간)
    print(end - start)

 

- 비동기(async)

위와 반대로 '코드가 반드시 작성된 순서로 실행되는 것이 아니다.'라는 뜻이다. 함수 A가 실행되는 동안 B가 실행되었다가 종료될 수도 있다. 함수가 동시에 시작되지만, 각 함수의 처리 상황에 따라 종료 시점이 달라질 수 있다.

import time
import asyncio


async def delivery(name, mealtime):
    print(f"{name}에게 배달완료!")
    await asyncio.sleep(mealtime)  # n초 대기
    print(f"{name} 식사완료, {mealtime}시간 소요...")
    print(f"{name} 그릇 수거 완료")


async def main():
    await asyncio.gather(
        delivery("A", 5),
        delivery("B", 3),
        delivery("C", 4),
    )


if __name__ == "__main__":
    start = time.time()  # 시작 시간(해당 시점 현재시간)
    asyncio.run(main())
    end = time.time()  # 끝난 시간(현재시간)
    print(end - start)

 

위 설명만 읽으면, 비동기 함수로 코드를 작성하는 것이 무조건 좋을 것이라고 생각할 수도 있다. 하지만 비동기 함수를 사용할 때에도 사용 목적과 코드 흐름의 상황을 잘 파악해야 한다. 예를 들어 수학 계산식을 작동 시키는 간단한 함수라면, 굳이 비동기함수를 작성할 필요가 없다. 오히려 유지보수만 어려워지는 결과를 내기도 한다. 각 상황과 목적에 따라 비동기함수 사용여부를 잘 파악해야 한다.

 

 

파이썬 코루틴

- 메인 루틴: 프로그램이 진행되는 플로우 그 자체라고 할 수 있다. 코드 상의 "if __name__ == __main__" 이 부분이라고 할 수 있다.

- 서브 루틴: 메인 루틴에 포함되거나 각 함수에 포함되는 함수 그 자체들이다.

 

그렇다면 코루틴은 무엇일까?

- 코루틴의 특징

  • 다양한 진입점과 다양한 탈출점이 있다. (일반 루틴의 경우 하나의 진입점(호출)과 하나의 탈출점(return)만 있음)
  • ex) 짜장면 배달/수거 시스템 - A에게 짜장면을 배달 후 식사하는 동안 B에게 배달 후 다시 A의 그릇을 수거하러 감 = A 함수 진입 -> 탈출 -> B 함수 진입 -> 탈출 -> A 함수 진입(그릇 수거하는 부분으로 중간 진입)

 

위와 같은 코루틴을 사용하기 위해서는 asyncio라는 라이브러리를 사용해주어야 하며, 비동기 코루틴 함수를 지정할 때에는 함수 선언 앞에 async라고 붙여주어야 한다.

 

import asyncio
import time

async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)

async def main():
    print(f"started at {time.strftime('%X')}")

    await say_after(1, 'hello')
    await say_after(2, 'world')

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())


>>>
started at 17:13:52
hello
world
finished at 17:13:55

위 코드는 await 이라는 표현식을 통해 코루틴 함수를 실행했다. 실행결과는 비동기 함수를 사용하지 않았을 때와 똑같을 것이다.

 

하지만 여러 개의 코루틴을 함수에 지정 예약하여(task1 등에 저장) 동시에 실행하는 asyncio.create_task() 함수를 사용한다면 차이가 생긴다.

async def main():
    task1 = asyncio.create_task(
        say_after(1, 'hello'))

    task2 = asyncio.create_task(
        say_after(2, 'world'))

    print(f"started at {time.strftime('%X')}")

    # Wait until both tasks are completed (should take
    # around 2 seconds.)
    await task1
    await task2

    print(f"finished at {time.strftime('%X')}")
    
    
>>>
started at 17:14:32
hello
world
finished at 17:14:34

이전 코드보다 1초 더 빠르게 실행이 완료된 모습을 볼 수 있다.

 

 

어웨이터블

하지만 모든 함수가 await 표현식으로 사용되는 것은 아니다. await 표현식에서 사용할 수 있는 '어웨이터블 객체'는 다음과 같다.

  • 코루틴 (async def 함수)
  • 태스크 (위에서 볼 수 있듯 asyncio.create_task()를 통해 코루틴을 예약해 놓은 함수)
  • 퓨처

해당 내용에 대한 자세한 설명은 Python 공식 문서를 통해 더 알아볼 수 있다. (아래 링크)

https://docs.python.org/ko/3/library/asyncio-task.html#coroutines

 

Coroutines and Tasks

This section outlines high-level asyncio APIs to work with coroutines and Tasks. Coroutines, Awaitables, Creating Tasks, Task Cancellation, Task Groups, Sleeping, Running Tasks Concurrently, Eager ...

docs.python.org

 

728x90

'Minding's Programming > FastAPI' 카테고리의 다른 글

[FastAPI/AWS/Uvicorn] AWS에 프로젝트 배포하기  (0) 2024.06.20
[FastAPI] 파이썬 멀티 프로세싱  (0) 2024.04.03
[FastAPI] 파이썬 멀티 스레딩 사용해보기  (0) 2024.04.01
[FastAPI] 동시성과 병렬성 개념 정리  (0) 2024.03.31
[FastAPI] FastAPI 특장, 설치 방법  (0) 2024.01.14
'Minding's Programming/FastAPI' 카테고리의 다른 글
  • [FastAPI] 파이썬 멀티 프로세싱
  • [FastAPI] 파이썬 멀티 스레딩 사용해보기
  • [FastAPI] 동시성과 병렬성 개념 정리
  • [FastAPI] FastAPI 특장, 설치 방법
Minding
Minding
  • Minding
    Today's Minding
    Minding
  • 전체
    오늘
    어제
    • 울고넘는 딥러닝 (278)
      • Minding's Baseball (57)
        • MLB Statcast (29)
        • 머신러닝으로 홈런왕 예측하기 (3)
        • 야구칼럼 (12)
        • 야구 규칙, 용어 (1)
        • 2022-23 질롱 코리아 (8)
        • 류현진 등판경기 (4)
      • Minding's Programming (185)
        • 프로그래머스 코딩테스트 (21)
        • Knowledge (44)
        • Numpy & Pandas (6)
        • Excel (3)
        • Git (1)
        • Pygame (11)
        • CV (3)
        • Tensorflow tutorial (4)
        • Kaggle and Dacon (4)
        • 에러 코드 (8)
        • FastAPI (8)
        • Airflow (29)
        • Crawling (6)
        • Django (14)
        • AWS (18)
        • Spark (5)
      • Minding's Reading (30)
        • 머신러닝 딥러닝에 필요한 기초 수학 with 파이.. (2)
        • 칼만필터는 어렵지 않아 (11)
        • 밑바닥부터 시작하는 딥러닝 (6)
        • 메이저리그 야구 통계학 2e (8)
        • 논문읽기 (2)
        • 빅데이터를 지탱하는 기술 (1)
      • Minding's Life (5)
        • 주식 (4)
        • 각종 소식 (1)
  • 블로그 메뉴

    • 홈
    • Baseball
    • Programming
    • Reading
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    프로그래머스
    파이썬게임개발
    MLB
    칼만필터
    데이터분석
    django python
    pygame
    KBO
    Airflow
    머신러닝
    넘파이
    코딩테스트
    에어플로우
    mlb stats api
    데이터 엔지니어
    FastAPI
    칼만필터는어렵지않아
    야구
    게임개발
    칼만필터는어렵지않아python
    Python
    딥러닝
    질롱코리아
    AWS
    파이게임
    칼만필터는어렵지않아파이썬
    메이저리그
    django
    파이썬
    KalmanFilter
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Minding
[FastAPI] 동기와 비동기, 코루틴 개념 정리
상단으로

티스토리툴바