8.16. 마무리

이제 asyncio의 API, 즉 스크립트가 단일 CPU에서 여러 작업을 동시에 실행하는 데 필요한 요소들을 살펴보았습니다:

  • 협력적 스케줄링 – 이 모듈의 나머지 부분이 의존하는 모델입니다. 실행 중인 코루틴은 await 하기 전까지 루프를 독점하며, 전환은 그러한 await 지점에서만 발생합니다.

  • 코루틴과 태스크async def 는 작업 단위를 정의합니다. asyncio.create_task() 는 작업 하나를 동시에 예약하고, 애플리케이션이 나중에 기다리거나 취소하거나 식별할 수 있는 Task 를 반환합니다.

  • 이벤트 루프 – 코루틴과 태스크를 실행하는 엔진입니다. asyncio.run() 은 대부분의 스크립트에 필요한 유일한 진입점이며, Loop 클래스는 그것이 필요한 드문 경우를 위해 나머지를 노출합니다.

  • 조정(Coordination) – 분산 및 수집을 위한 gather(), 마감 시간을 위한 wait_for(), Task.cancelfinally 절 정리 패턴, 태스크 및 gather 호출을 통한 예외 전파, 그리고 루프의 예외 핸들러 후크가 있습니다.

  • 동기화 프리미티브 – 코루틴 간 신호를 위한 Event, await를 사이에 둔 공유 리소스 접근을 직렬화하기 위한 Lock, 그리고 인터럽트 핸들러에서 asyncio 태스크를 깨우기 위한 ThreadSafeFlag 가 있습니다.

  • 커스텀 async 객체 – 애플리케이션 클래스가 asyncio 관용구에 연결될 수 있게 하는 언어 후크입니다. 그 자체가 await 의 대상이 되는 객체를 위한 __await__, async for 를 위한 __aiter__ / __anext__, 그리고 async with 를 위한 __aenter__ / __aexit__ 가 있습니다.

  • 프레임 캡처csi.CSI.snapshot()await 친화적인 코루틴으로 바꿔주는 래퍼로, 캡처 루프가 다른 asyncio 작업과 나란히 실행되게 합니다.

  • 함정 – 빠뜨린 await, 양보가 없는 빡빡한 루프, 삼켜진 취소, await를 사이에 두고 변경되는 공유 상태, 그리고 asyncio 특유의 나머지 함정들입니다.

이것만으로도 카메라 작업, 하드웨어 I/O, 그리고 동시 백그라운드 작업을 같은 루프에서 혼합하는 프로그램을 작성하기에 충분합니다.

8.16.1. 이 레퍼런스를 나중에 활용하기

asyncio 챕터들을 참고 자료로 다루세요. async with 의 형태나 형제 태스크 실패 시 gather() 의 정확한 동작을 다시 찾아보는 것이 의도된 용도입니다. asyncio 레퍼런스 페이지는 “이 호출의 정확한 이름이 무엇인가”가 궁금할 때 모든 함수와 클래스를 한곳에 나열합니다.

이 모듈 위에 구축된 더 풍부한 프리미티브(세마포어, 큐, 배리어, 그리고 애플리케이션 형태의 다양한 헬퍼 모음)에 대해서는 peterhinch/micropython-async 저장소가 커뮤니티가 관리하는 표준 출처입니다.

8.16.2. 다음으로 나아갈 방향

네트워킹 이 다음 주요 주제입니다. asyncio.open_connection(), asyncio.start_server(), 그리고 Stream 클래스는 asyncio 스크립트가 코루틴 내부에서 나머지 네트워크와 통신하는 방법이며, 그 아래에 있는 networksocket 모듈과 함께 동작합니다. await, Task, 취소, 그리고 동기화 프리미티브에 대해 배운 모든 것이 그대로 이어집니다.