비동기 프로그래밍은 파이썬 3.5 버전부터 async 및 await 키워드 도입으로 시작되었습니다. 처음에는 비동기 작업에 asyncio와 코루틴 기반 생성기와 같은 라이브러리를 사용했으며, 이는 이해하고 유지하기 어려웠습니다. async/await 문법의 등장으로 비동기 코드는 더욱 명확하고 읽기 쉬워졌으며, 익숙한 동기 스타일에 가까워졌습니다.
async/await 이전에는 비동기성이 콜백 및 생성기를 통해 구현되었습니다(예: tornado 라이브러리나 오래된 asyncio API를 사용). 이러한 코드는 디버깅 및 유지 관리가 어려웠습니다.
동기 코드에서 많은 동시 I/O 작업(네트워크 요청, 파일 입출력)을 처리할 때의 주요 문제는 주요 스레드가 차단되는 것입니다. 이는 성능 저하와 자원을 효율적으로 사용할 수 없는 문제를 일으킵니다.
async/await를 사용한 비동기 프로그래밍은 하나의 스레드 내에서 많은 입출력 작업을 병렬로 수행할 수 있게 하며, 차단을 피할 수 있습니다. 이때 문법은 일반 함수와 비슷해 읽기 쉽고 디버깅하기 쉬워집니다.
import asyncio async def fetch_data(delay): print(f"{delay}초 지연 후 데이터 가져오기 시작") await asyncio.sleep(delay) print(f"{delay}초 지연 후 데이터 가져오기 완료") return delay async def main(): results = await asyncio.gather( fetch_data(1), fetch_data(2), fetch_data(3) ) print("결과:", results) asyncio.run(main())
async def로 정의된 함수는 일반 함수처럼 호출될 수 있습니까?
아니오. 이러한 함수를 호출하면 코루틴 객체가 반환되며, 이는 이벤트 루프에 전달되기 전까지 실행되지 않습니다(예: await 또는 asyncio.run()을 통해).
def foo(): return 42 async def bar(): return 42 print(foo()) # 42 print(bar()) # <coroutine object bar at ...>
비동기 함수 밖에서 await를 사용할 수 있습니까?
아니오. await 키워드는 반드시 async def로 선언된 함수 내에서만 사용되어야 합니다. 이러한 함수 외부에서 await를 사용하면 SyntaxError가 발생합니다.
# 오류! await asyncio.sleep(1) # SyntaxError: 'await' outside async function
I/O와 관련 없는 작업(예: 계산)에 비동기성이 적용됩니까?
아니오. 비동기성은 입력 및 출력 작업에만 효과적입니다. 계산 작업에는 여전히 multiprocessing이나 threading이 필요하며, 그렇지 않으면 이벤트 루프가 차단됩니다.
장점:
단점:
부정적인 사례: 젊은 개발자들이 async/await를 사용하여 애플리케이션을 가속화하려 했지만, 비동기적으로 계산만 하고 네트워크 요청이 없었습니다. 애플리케이션은 속도가 빠르지 않았습니다. 장점: 문법에 익숙해짐. 단점: 이득 없음, 코드가 복잡해짐.
긍정적인 사례: 수천 개의 API 요청을 비동기적으로 처리했습니다. 서버는 리소스 증가 없이 더 많은 클라이언트를 처리할 수 있었습니다. 장점: 성능이 크게 향상되었고, 아키텍처도 더 간단해졌습니다. 단점: 신입 개발자에게 진입 장벽이 높아졌습니다.