Python
[Python] async/await로 배우는 비동기 프로그래밍
dud9902
2025. 1. 11. 15:51
자바크스립트에서 사용했었던 async/await을 파이썬에서는 어떻게 사용하는지 알아보게 되었다.
여러 글들을 읽고 간략하게 정리해보았다.
더 많은 내용을 알고 싶으면 검색해서 다분들의 글을 보면 될 것 같다.. (더 자세하세 설명 잘 되어있음)
동기/비동기란?
- 동기(synchronous): 작업이 끝날 때까지 기다린 후 다음 코드를 실행하는 방식. 순서를 보장하며 결과를 즉시 확인 가능.
- 비동기(asynchronous): 작업이 끝나지 않아도 다음 코드를 실행하는 방식. 병렬 처리가 가능하며, 시간을 효율적으로 사용할 수 있음.
async/await란?
- async/await는 Python 3.5 이상에서 사용할 수 있는 비동기 처리를 위한 키워드이다.
- 비동기 코드를 작성할 때 async/await를 사용하면 코드의 가독성이 좋아지고, 동기 코드처럼 직관적으로 작성할 수 있다.
- Python에서는 asyncio 라이브러리를 활용해 비동기 작업을 효과적으로 관리할 수 있다.
동기 함수
- 동기 함수는 순차적으로 실행되며, 하나의 작업이 완료된 후에야 다음 작업이 시작된다.
- def 키워드로 선언된 모든 함수는 기본적으로 동기 함수이다.
def do_sync():
return "This is a synchronous function"
비동기 함수
- 비동기 함수는 기존 def 키워드 앞에 async 키워드를 붙여 정의하며, 이를 **코루틴(coroutine)**이라고 한다.
- 비동기 함수는 호출 즉시 실행되지 않고, 대신 코루틴 객체를 반환한다.
async def do_async():
return "This is an asynchronous function"
- 이러한 비동기 함수는 일반 동기 함수가 호출하듯이 호출하면 코루틴 객체가 리턴된다.
coroutine = do_async() # <coroutine object do_async at 0x1038de710>
- 비동기 함수를 실행하려면 반드시 await 키워드를 사용하거나, 비동기 이벤트 루프에서 실행해야 한다.
async def main():
result = await do_async() # await로 비동기 함수 실행
print(result)
# 동기 환경에서는 asyncio.run()을 사용
asyncio.run(main())
await의 역할
- await 키워드는 비동기 함수나 코루틴의 실행을 일시 중단하고, 다른 작업을 처리할 수 있도록 제어권을 이벤트 루프에 양도한다.
- await는 반드시 async로 선언된 함수 내에서만 사용할 수 있다.
추가 고려사항
- asyncio.run은 동기 환경에서 비동기 함수를 실행하기 위한 표준 방법이다. 이는 비동기 루프를 생성하고 관리한다.
- 비동기 함수는 I/O 바운드 작업(예: 파일 읽기/쓰기, 네트워크 요청)에서 특히 유용하다. CPU 바운드 작업에는 적합하지 않을 수 있다.
asyncio의 동작을 활용한 예시
import asyncio
async def do_async():
print("Starting async task...")
await asyncio.sleep(2) # 2초 대기
print("Async task finished!")
return "Result from do_async"
async def another_task():
print("Starting another task...")
await asyncio.sleep(1) # 1초 대기
print("Another task finished!")
return "Result from another_task"
async def main():
task1 = asyncio.create_task(do_async())
task2 = asyncio.create_task(another_task())
print("Both tasks started!")
result1 = await task1
result2 = await task2
print(f"Task1 result: {result1}")
print(f"Task2 result: {result2}")
asyncio.run(main())
출력 결과
Both tasks started!
Starting async task...
Starting another task...
Another task finished!
Async task finished!
Task1 result: Result from do_async
Task2 result: Result from another_task