[WAFFLE] 04-5 Event Loop
Published:
In this post, concepts of event loop will be introduced.
이벤트 루프의 정의
- 이벤트 루프는 비동기 작업을 스케줄링하고 실행하는 중심 역할을 하는 루프 구조입니다.
- 즉, 실행할 작업(태스크, 이벤트, 콜백 등)을 계속 감시하며 준비된 작업이 있으면 처리합니다.
이벤트 루프의 주요 원리
- 작업 등록
- 비동기 작업(코루틴, 콜백 등)을 이벤트 루프에 등록합니다.
- 작업이 준비되면 이벤트 루프가 이를 실행합니다.
- 중단점(await)에서 멈춤
- 비동기 작업은 await 키워드나 I/O 대기 시점에서 실행을 일시 중단합니다.
- 이때 이벤트 루프는 대기하지 않고 다른 작업을 실행합니다.
- 작업 완료 후 재개
- 대기 중인 작업이 완료되면, 이벤트 루프가 해당 작업의 실행을 재개합니다.
이벤트 루프의 동작 과정
이벤트 루프는 아래 단계를 반복적으로 실행합니다.
- 작업 큐(Task Queue)에 작업 등록
- 비동기 작업, 콜백 함수, 타이머 등의 작업이 작업 큐에 들어갑니다.
- 준비된 작업 실행
- 작업 큐에서 준비된 작업을 하나 꺼내 실행합니다.
- 중단점에서 대기
- 작업 실행 중 await이나 I/O 작업이 발생하면, 해당 작업은 중단되고 다시 큐로 반환됩니다.
- 다른 작업 처리
- 이벤트 루프는 중단된 작업 대신 다른 준비된 작업을 실행합니다.
- 작업 완료 후 재개
- 중단된 작업이 완료되면, 해당 작업은 큐로 돌아와 재개됩니다.
이벤트 루프의 실제 동작 예시
다음은 Python의 asyncio를 사용한 간단한 이벤트 루프 예제입니다.
import asyncio
async def task1():
print("Task 1 시작")
await asyncio.sleep(2) # 중단점: 2초 대기
print("Task 1 완료")
async def task2():
print("Task 2 시작")
await asyncio.sleep(1) # 중단점: 1초 대기
print("Task 2 완료")
async def main():
# 이벤트 루프에 작업 등록
await asyncio.gather(task1(), task2()) # 두 작업을 동시에 실행
asyncio.run(main())
Task 1 시작
Task 2 시작
Task 2 완료
Task 1 완료
- task1()과 task2()가 이벤트 루프에 등록됩니다.
- 이벤트 루프가 task1()을 실행하고, await asyncio.sleep(2)에서 중단합니다.
- 중단된 사이에, 이벤트 루프가 task2()를 실행하고, await asyncio.sleep(1)에서 중단합니다.
- 1초 후, task2()가 완료되며 출력.
- 2초 후, task1()이 완료되며 출력.
이벤트 루프의 주요 구성 요소
- 작업 큐 (Task Queue)
- 실행 대기 중인 비동기 작업이 저장됩니다.
- 대기 목록 (Waiting List)
- await 상태에서 대기 중인 작업이 저장됩니다.
- 작업이 완료되면 다시 작업 큐로 이동합니다.
- 콜백 큐 (Callback Queue) -완료된 작업의 결과를 처리하기 위한 콜백 함수가 저장됩니다.
왜 이벤트 루프가 중요한가?
- 효율적인 리소스 사용
- 이벤트 루프는 단일 스레드로 동시성을 지원합니다.
- 스레드나 프로세스를 추가 생성하지 않아도, 여러 작업을 동시에 처리하는 것처럼 보이게 합니다.
- I/O 대기 시간 활용
- I/O 작업 중 발생하는 대기 시간을 활용하여 다른 작업을 처리합니다.
- 이를 통해 높은 처리량을 달성할 수 있습니다.
이벤트 루프의 실제 사례
웹 서버에서의 활용 (FastAPI)
- FastAPI와 같은 비동기 웹 프레임워크는 이벤트 루프를 기반으로 작동합니다.
- 클라이언트 요청이 들어오면 이벤트 루프가 요청을 작업으로 등록합니다.
- 작업이 처리되는 동안 I/O 대기 상태가 발생하면, 이벤트 루프는 다른 요청을 처리합니다.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
await asyncio.sleep(1) # 비동기 대기
return {"message": "Hello, World!"}

Leave a Comment