Python의 이벤트 루프(event loop)는 비동기 프로그래밍의 핵심 메커니즘으로, 비동기 작업들이 순차적으로 실행되도록 관리하는 구조입니다. 이벤트 루프는 하나의 작업이 끝나기를 기다리지 않고, 다른 작업을 수행하며 효율적으로 실행 시간을 관리합니다. 이 메커니즘은 특히 네트워크 요청, 파일 입출력 같은 I/O 바운드 작업에서 성능을 높이기 위해 유용합니다. Python의 asyncio 모듈이 이벤트 루프의 주요 기능을 제공하며, 이를 통해 비동기 작업을 생성하고 관리할 수 있습니다.
이벤트 루프 이해하기
Python의 이벤트 루프는 비동기 작업을 처리하고 콜백 함수, 네트워크 소켓, 파일 입출력 같은 이벤트들을 감시하며 적절한 시점에 해당 작업을 수행합니다. asyncio의 get_event_loop() 메서드를 통해 이벤트 루프를 가져올 수 있으며, 이 루프에 코루틴이나 Task를 등록하여 실행합니다. 이벤트 루프가 모든 작업을 완료할 때까지 루프는 계속 실행됩니다.
아래는 이벤트 루프의 기본 구조를 보여주는 예제를 통해 그 동작 방식을 설명합니다.
예제: 다중 API 요청 처리하기
import asyncio
import time
async def fetch_data(api_url):
print(f"Fetching data from {api_url}")
await asyncio.sleep(2) # API 응답 대기 시뮬레이션
print(f"Received data from {api_url}")
return f"Data from {api_url}"
async def main():
start_time = time.time()
# 비동기 작업 생성
task1 = asyncio.create_task(fetch_data("https://api.example.com/data1"))
task2 = asyncio.create_task(fetch_data("https://api.example.com/data2"))
task3 = asyncio.create_task(fetch_data("https://api.example.com/data3"))
# 모든 작업 완료 대기
results = await asyncio.gather(task1, task2, task3)
end_time = time.time()
print(f"Total time taken: {end_time - start_time:.2f} seconds")
print("Results:", results)
# 이벤트 루프 가져오기
loop = asyncio.get_event_loop()
# 이벤트 루프 실행
loop.run_until_complete(main())
# 이벤트 루프 닫기
loop.close()
1. 코루틴 정의: fetch_data는 API URL을 받아 데이터를 가져오는 코루틴이며, await asyncio.sleep(2)로 네트워크 지연을 시뮬레이션합니다.
2. Task 생성: asyncio.create_task를 사용하여 각 fetch_data 코루틴을 개별 Task로 이벤트 루프에 등록합니다. 이렇게 하면 각 작업이 동시에 실행되기 시작합니다.
3. gather로 동시 실행 관리: asyncio.gather는 여러 Task를 동시에 실행하고, 모든 Task가 완료될 때까지 대기합니다. 여기서 각 Task의 실행 순서는 이벤트 루프가 관리하므로, 효율적으로 자원을 사용하게 됩니다.
4. 실행 시간 확인: 여러 API 요청을 동시 처리하여 총 실행 시간이 단일 요청보다 짧게 유지됩니다.
5. 이벤트 루프 제어:
• asyncio.get_event_loop()로 현재 이벤트 루프를 가져옵니다.
• loop.run_until_complete(main())로 main() 코루틴을 실행하고, 모든 비동기 작업이 완료될 때까지 이벤트 루프가 돌아가게 합니다.
• 작업 완료 후 loop.close()로 이벤트 루프를 닫아 자원을 정리합니다.
get_event_loop와 run_until_complete 는 asyncio.run() 을 사용하여 간단히 처리할 수 있습니다.
# 이벤트 루프 가져오기 -> 실행 -> 닫기
#loop = asyncio.get_event_loop()
#loop.run_until_complete(main())
#loop.close()
# 이벤트 루프 실행 - run() 하나로 처리
asyncio.run(main())
이벤트 루프는 Python에서 효율적으로 비동기 작업을 관리하는 핵심 도구입니다. 특히 I/O 바운드 작업에서 동시성을 극대화해 프로그램의 성능을 높이는 데 유용합니다.
다음 블로그에서는 비동기 지원이 되지 않는 작업을 비동기적으로 처리해 주는 event_loop의 run_in_executor 메서드에 대해서 알아보도록 하겠습니다.