프로그래밍/Python

[python] `await` 키워드의 의미와 역할

채윤아빠 2024. 11. 1. 13:24

await 키워드는 Python의 비동기 프로그래밍에서 핵심적인 역할을 하며, 코루틴 기반 코드에서 다음과 같은 중요한 의미와 기능을 가집니다.

기본 개념

await는 코루틴 함수 내에서만 사용할 수 있으며, 비동기 작업이 완료될 때까지 현재 코루틴의 실행을 일시 중단합니다. 이 때 중요한 점은 전체 프로그램이나 스레드가 블로킹되는 것이 아니라, 현재 코루틴만 일시 중단된다는 것입니다.

주요 기능

비동기 작업 대기

async def send_message(self, message: Message):
    await self.send_queue.put(message)

위 코드에서 await self.send_queue.put(message)는 메시지가 큐에 추가될 때까지 기다립니다. 큐가 가득 찼을 경우 이 작업은 시간이 걸릴 수 있지만, await를 사용함으로써 이 대기 시간 동안 다른 코루틴이 실행될 수 있게 합니다.

제어권 양도
await는 이벤트 루프에 제어권을 일시적으로 반환합니다. 이를 통해 이벤트 루프는 다른 준비된 코루틴을 실행할 수 있게 됩니다. 이것이 비동기 프로그래밍의 핵심 메커니즘입니다.

결과값 반환

message = await self.receive_queue.get()

await는 비동기 작업이 완료되면 그 결과값을 반환합니다. 위 예제에서는 큐에서 메시지를 가져와 message 변수에 할당합니다.

예제별 await 사용 설명

네트워크 I/O 작업

data = await reader.read(4096)

네트워크에서 데이터를 읽는 작업은 시간이 걸릴 수 있습니다. await를 사용하면 데이터가 도착할 때까지 다른 작업을 수행할 수 있습니다.

큐 작업

source_message = await self.source_to_target_queue.get()

큐에서 항목을 가져오는 작업은 큐가 비어있을 경우 블로킹될 수 있습니다. await를 사용하면 항목이 도착할 때까지 다른 코루틴이 실행될 수 있습니다.

서버 시작

self.server = await asyncio.start_server(
    self._handle_client, self.host, self.port
)

서버를 시작하는 작업은 네트워크 바인딩 등의 I/O 작업을 포함합니다. await를 사용하여 이 작업이 완료될 때까지 기다립니다.

연결 종료

await writer.wait_closed()

연결이 완전히 종료될 때까지 기다립니다. 이는 모든 데이터가 전송되고 소켓이 정상적으로 닫힐 때까지 기다리는 것입니다.

await가 없다면 어떻게 될까?

만약 await 없이 비동기 함수를 호출하는 경우

# 잘못된 예
self.send_queue.put(message)  # await 없음

이 경우 put() 메서드는 코루틴 객체를 반환하지만, 실제로 실행되지 않습니다. 이는 "coroutine was never awaited" 경고를 발생시키고, 메시지는 실제로 큐에 추가되지 않습니다.

중첩된 await 호출

async def handle_message(self, message):
    processed_message = await self.process_message(message)
    await self.send_response(processed_message)

위 코드에서는 process_message가 완료된 후에만 send_response가 실행됩니다. 두 작업 모두 비동기적이지만, 순차적으로 실행됩니다.

병렬 실행을 위한 await

여러 비동기 작업을 병렬로 실행하려면 asyncio.gatherasyncio.create_task와 함께 사용합니다.

async def process_multiple_messages(self, messages):
    tasks = [self.process_message(msg) for msg in messages]
    results = await asyncio.gather(*tasks)
    return results

이 경우 모든 메시지 처리가 동시에 시작되고, await asyncio.gather(*tasks)는 모든 작업이 완료될 때까지 기다립니다.

맺는말

await 키워드는 다음과 같은 특성을 갖습니다.

  1. 비동기 작업이 완료될 때까지 현재 코루틴을 일시 중단합니다.
  2. 이벤트 루프에 제어권을 반환하여 다른 코루틴이 실행될 수 있게 합니다.
  3. 비동기 작업의 결과를 반환합니다.
  4. I/O 바운드 작업에서 효율적인 리소스 사용을 가능하게 합니다.
  5. 비동기 코드를 동기 코드처럼 선형적으로 작성할 수 있게 해줍니다.

이러한 특성 덕분에 await는 비동기 프로그래밍에서 코드의 가독성을 높이고, 효율적인 리소스 사용을 가능하게 하는 핵심 요소입니다.

728x90
반응형