3P by neo 3달전 | favorite | 댓글과 토론
  • Asyncio는 Python에서 I/O 바운드 프로그램을 다루는 좋은 방법이며, 기본적으로 Python Generator 위에 좋은 레이어를 제공함
  • Generator는 코드를 메모리 효율적으로 만들어 주며, yield 키워드를 사용해 함수를 일시 중지하고 재개할 수 있음
  • yield from을 사용하면 generator가 sub-generator나 iterable 객체를 호출할 수 있어 generator 체인을 만들 수 있음

이벤트 루프

  • Asyncio의 핵심은 현재 task를 실행하고 관리하는 event loop임
  • Event loop는 task 목록을 반복하면서 next(task)로 각 task를 실행함
  • Task는 I/O 작업 중에 yield를 사용해 실행을 일시 중지하고 제어권을 event loop에 넘김

슬리핑

  • yield from을 사용해 task에 sub-generator를 추가할 수 있음
  • Sleep generator를 추가하면 지정된 시간까지 task 실행을 일시 중지할 수 있음
  • Sleep이 while 루프를 빠져나가면 StopIteration 예외가 발생해 task 함수의 yield from이 다음 코드 줄로 계속 진행됨

Yield에서 Await로

  • __await__ 던더 메서드와 async 키워드를 사용해 yield에서 await로 전환할 수 있음
  • await 키워드는 클래스 인스턴스의 __await__ 메서드를 호출하거나 코루틴(async 함수로 생성된 객체)에서 사용 가능
  • await 키워드는 yield from의 동의어로 볼 수 있으며 약간의 추가 유효성 검사 규칙이 있음
  • 자체 Task 클래스를 만들어 __await__ 메서드를 구현하고, create_task 함수로 생성한 task를 이벤트 루프에 추가함
  • 이벤트 루프 관리자는 task를 실행하고, StopIteration 예외 발생 시 task를 완료 처리함
  • Sleep 함수도 async 호환되도록 수정해야 함

AsyncIO와 Await

  • 위 코드에서 "jacobio"를 "asyncio"로 교체하면 asyncio 패키지를 완전히 사용하게 됨
  • Asyncio는 더 많은 작업을 수행하지만, 기본 generator에서 asyncio의 핵심 부분을 처음부터 재현할 수 있음
  • 실제 asyncio 패키지에서는 asyncio.gather() 등의 함수를 사용해 여러 task를 처리할 수 있음

GN⁺의 의견

  • 이 글은 asyncio의 작동 원리를 generator를 사용해 쉽게 설명하고 있어, asyncio를 처음 접하는 개발자들에게 큰 도움이 될 것 같음
  • Asyncio는 고성능 I/O 처리에 최적화된 라이브러리로, 이 글을 통해 그 내부 구조를 이해하면 실제 프로젝트에서 더 효과적으로 활용할 수 있을 것임
  • 다만 실제 asyncio는 훨씬 더 복잡한 구조를 가지고 있어, 실무에서 사용하기 위해서는 공식 문서 등을 통해 더 깊이 있는 학습이 필요할 것으로 보임
  • Asyncio와 유사한 기능을 제공하는 다른 라이브러리로는 Trio, Curio 등이 있는데, 이들과의 차이점을 비교해 보는 것도 흥미로울 것 같음
  • Asyncio를 도입할 때는 기존 동기 코드와의 호환성, 에러 처리, 테스트 등 고려해야 할 사항이 많으므로, 충분한 검토와 준비가 필요할 것으로 보임