Python

Python 비동기 프로그래밍

thebasics 2024. 11. 25. 17:00

목차

  1. 비동기 프로그래밍이란?
  2. asyncio 및 비동기 함수
    • asyncio 모듈 소개
    • 비동기 함수 정의 및 호출
    • await 키워드와 비동기 작업
  3. 동시성 처리
    • 태스크와 이벤트 루프
    • 동시성 작업 실행
  4. 예시 코드
  5. 결론
  6. 관련 자료 및 추가 학습 자료

1. 비동기 프로그래밍이란?

비동기 프로그래밍은 작업이 완료될 때까지 프로그램이 기다리지 않고 다른 작업을 수행할 수 있도록 하는 프로그래밍 방식입니다. 이는 특히 I/O 바운드 작업(예: 파일 읽기/쓰기, 네트워크 요청)에서 유용하며, 프로그램이 대기 시간 동안 다른 작업을 수행하여 효율성을 높일 수 있습니다. Python에서는 asyncio 모듈을 사용하여 비동기 프로그래밍을 구현할 수 있습니다.


2. asyncio 및 비동기 함수

asyncio 모듈 소개

asyncio는 Python의 표준 라이브러리로, 비동기 프로그래밍을 쉽게 구현할 수 있도록 도와줍니다. asyncio는 이벤트 루프를 사용하여 코루틴(비동기 함수)을 실행하고, 네트워크, 파일 I/O, 시간 지연 등의 비동기 작업을 관리합니다.

비동기 함수 정의 및 호출

비동기 함수는 async def 구문을 사용하여 정의되며, 이러한 함수는 await 키워드를 사용하여 다른 비동기 작업을 호출할 수 있습니다.

  • 예시: 비동기 함수 정의:

    import asyncio
    
    async def fetch_data():
        print("Start fetching data...")
        await asyncio.sleep(2)  # 비동기적으로 2초 동안 대기
        print("Data fetched")
        return {"data": 123}
    
    async def main():
        data = await fetch_data()
        print(data)
    
    # 이벤트 루프 실행
    asyncio.run(main())
    • async def를 사용하여 비동기 함수를 정의하고, await를 사용하여 비동기 작업을 대기합니다. asyncio.run()은 이벤트 루프를 실행하고 비동기 함수를 호출합니다.

await 키워드와 비동기 작업

await 키워드는 비동기 작업을 일시 중단하고, 작업이 완료될 때까지 대기하는 데 사용됩니다. awaitasync로 정의된 함수 내에서만 사용할 수 있습니다. 이를 통해 코드의 실행을 일시 중단하고 다른 작업을 실행할 수 있습니다.

  • 예시: await 키워드 사용:

    async def compute():
        print("Computing...")
        await asyncio.sleep(1)
        print("Done computing")
    
    async def main():
        await compute()
        print("Main function complete")
    
    asyncio.run(main())
    • await는 비동기 작업을 기다리는 동안 이벤트 루프가 다른 작업을 처리할 수 있게 합니다.

3. 동시성 처리

태스크와 이벤트 루프

이벤트 루프는 비동기 코드를 실행하는 핵심 요소로, 태스크를 관리하고 실행하는 역할을 합니다. asyncio에서 태스크는 비동기 함수를 이벤트 루프에서 실행하는 단위를 의미합니다. asyncio.create_task()를 사용하여 비동기 함수를 태스크로 생성할 수 있습니다.

  • 예시: 태스크 생성 및 실행:

    async def task1():
        await asyncio.sleep(1)
        print("Task 1 complete")
    
    async def task2():
        await asyncio.sleep(2)
        print("Task 2 complete")
    
    async def main():
        task1_obj = asyncio.create_task(task1())
        task2_obj = asyncio.create_task(task2())
    
        await task1_obj
        await task2_obj
    
    asyncio.run(main())
    • asyncio.create_task()는 비동기 함수를 태스크로 실행하며, 이벤트 루프는 이 태스크들을 동시에 실행합니다.

동시성 작업 실행

비동기 프로그래밍의 주요 이점 중 하나는 여러 작업을 동시에 실행하여 프로그램의 효율성을 향상시키는 것입니다. asyncio.gather()를 사용하면 여러 비동기 작업을 동시에 실행할 수 있습니다.

  • 예시: 동시성 작업 실행:

    async def fetch_data1():
        await asyncio.sleep(1)
        return "Data 1"
    
    async def fetch_data2():
        await asyncio.sleep(2)
        return "Data 2"
    
    async def main():
        results = await asyncio.gather(fetch_data1(), fetch_data2())
        print(results)
    
    asyncio.run(main())
    • asyncio.gather()는 여러 비동기 함수를 동시에 실행하고, 모든 작업이 완료될 때까지 대기합니다. 결과는 리스트로 반환됩니다.

4. 예시 코드

네트워크 요청을 비동기적으로 처리하는 예시

import asyncio
import aiohttp

async def fetch_url(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        urls = [
            'https://example.com',
            'https://httpbin.org/get',
            'https://jsonplaceholder.typicode.com/posts/1'
        ]
        tasks = [fetch_url(session, url) for url in urls]
        results = await asyncio.gather(*tasks)
        for result in results:
            print(result)

asyncio.run(main())
  • 이 코드는 aiohttp를 사용하여 여러 URL에서 비동기적으로 데이터를 가져옵니다. 각 요청은 동시에 실행되어 전체 실행 시간이 단축됩니다.

비동기 파일 읽기와 쓰기

import asyncio

async def write_to_file(file_name, data):
    await asyncio.sleep(1)  # 비동기 작업 시뮬레이션
    with open(file_name, 'w') as f:
        f.write(data)

async def read_from_file(file_name):
    await asyncio.sleep(1)  # 비동기 작업 시뮬레이션
    with open(file_name, 'r') as f:
        return f.read()

async def main():
    await write_to_file('example.txt', 'Hello, Async World!')
    content = await read_from_file('example.txt')
    print(content)

asyncio.run(main())
  • 이 코드는 파일에 데이터를 비동기적으로 쓰고, 다시 읽어오는 예시입니다.

5. 결론

비동기 프로그래밍은 비동기 작업을 효율적으로 처리하여 프로그램의 성능을 향상시키는 강력한 방법입니다. Python의 asyncio 모듈은 비동기 프로그래밍을 구현하는 데 필요한 기능을 제공합니다.

  • asyncawait 키워드를 사용하여 비동기 함수를 정의하고 호출할 수 있으며, asyncio.run()과 이벤트 루프를 통해 이 함수들을 실행할 수 있습니다.
  • 또한 asyncio.create_task()asyncio.gather()를 통해 여러 작업을 동시에 실행하여 프로그램의 효율성을 극대화할 수 있습니다.

비동기 프로그래밍은 네트워크 요청, 파일 I/O, 시간 지연이 있는 작업과 같은 I/O 바운드 작업에 특히 유용하며, 이러한 작업을 효율적으로 처리하여 프로그램의 응답성과 성능을 향상시킬 수 있습니다.


6. 관련 자료 및 추가 학습 자료


이 글에서는 Python의 asyncio 모듈을 사용하여 비동기 프로그래밍을 구현하는 방법을 살펴보았습니다. 비동기 작업을 효율적으로 처리하여 프로그램의 성능을 향상시키는 방법을 이해하고, 실제 프로젝트에서 이를 활용해 보세요.

반응형