티스토리 뷰

1. asyncio가 필요한 이유

* asyncio란? Pytyhon의 내장 모듈(라이브러리)

- python은 위에서 아래로 순차적으로 실행된다(동기)

- 네트워크 요청이나 데이터베이스 쿼리 같은 작업은 실행하는데 시간이 걸리기 때문에 대기 시간을 줄이기 위해 사용

- I/O 작업이 완료될 때까지 기다리는 동안 다른 작업을 수행할 수 있다

-싱글 스레드 환경에서도 병렬적으로 작업을 처리할 수 있다

- 멀티스레딩보다 메모리 사용량이 적고, 코드가 간결해진다

 

2. 이벤트 루프란?

- 비동기 작업(코루틴, I/O 작업 등)을 실행하고 관리하는 역할을 하는 핵심 엔진

- 비동기함수(async def)를 실행하려면 반드시 이벤트 루프가 필요하다

- 이벤트 루프는 비동기 작업을 예약하고 실행하며, 실행이 끝날때까지 관리한다

- 한 번에 하나의 작업만 하는것이 아니라, 대기해야 하는 작업이 있으면 다른 작업을 실행하면서 시간을 효율적으로 사용

 

3. 코루틴이란?

- Coroutine, 비동기적으로 실행되는 함수(async def)

- 일반적인 함수(def)와 다르게, 코루틴은 실행을 중간에 멈출 수 있고(await), 다시 이어서 실행할 수 있다

- 코루틴은 이벤트 루프에 의해 실행되는 작업 단위

- async def를 사용해 만든 함수는 일반적인 함수(def)와 다르게 즉시 실행되지 않고, 코루틴 객체(Coroutine Object)를 반환한다

- 코루틴을 실행하려면 반드시 await 키워드를 사용해야 한다

* await 는 반드시 비동기 함수 안에서만 사용!

import asyncio

def normal_function():
    return "나는 일반 함수!"

async def coroutine_function():
    return "나는 코루틴!"

print(normal_function())   # 나는 일반 함수!
print(coroutine_function())  # <coroutine object coroutine_function at 0x0000016FAE0FF1C0>
print(asyncio.run(coroutine_function())) # 나는 코루틴!

async def main():
    loop = asyncio.get_running_loop()  # 현재 실행 중인 이벤트 루프 가져오기
    result = await coroutine_function()
    print(result)

asyncio.run(main())  # 메인 루프 실행

 

4. asyncio 모듈의 함수와 사용법

함수명 설명
run() 코루틴을 실행하기 위해 새로운 이벤트 루프를 생성하고, 주어진 코루틴을 실행한 뒤 종료
await() 코루틴의 실행을 기다릴 때 사용, 해당 작업이 끝날 때까지 기다린 후 다음 코드가 실행됨
create_task() 여러 개의 비동기 작업을 동시에 실행할 떄 사용
gather() 여러 개의 코루틴을 동시에 실행하고 결과를 반환(리스트)
get_event_loop() 현재 실행중인 이벤트 루프를 가져와 사용(반복적으로 코루틴 실행이 필요할 경우 run대신 사용)
Python 3.10부터 비추천(레거시)
get_running_loop() get_event_loop()대신 사용
import asyncio

async def task_1():
    await asyncio.sleep(2)
    print("Task 1 완료!")

async def task_2():
    await asyncio.sleep(1)
    print("Task 2 완료!")

async def main():
    t1 = asyncio.create_task(task_1())  # 비동기 작업 생성
    t2 = asyncio.create_task(task_2())  # 비동기 작업 생성

    await t1  # task_1이 끝날 때까지 기다림
    await t2  # task_2가 끝날 때까지 기다림

asyncio.run(main())

# Task 2 완료!  (1초 후)
# Task 1 완료!  (2초 후)

# asyncio.create_task()는 두 작업이 동시에 실행되어, 총 2초만 걸림

async def fetch_data(n):
    await asyncio.sleep(n)
    return f"데이터 {n}초 후 도착"

async def main():
    results = await asyncio.gather(fetch_data(2), fetch_data(3), fetch_data(1))
    print(results)

asyncio.run(main())

# ['데이터 2초 후 도착', '데이터 3초 후 도착', '데이터 1초 후 도착']

 

5. asyncio 언제 사용할까?

- 웹 크롤링(여러 웹사이트에서 동시에 데이터를 가져올 때)

- API 요청(여러 개의 API 요청을 동시에 보낼 때)

- 데이터베이스 처리(쿼리를 비동기적으로 실행할 때)

- 채팅 서버, 웹 소켓(실시간 통신이 필요한 경우)

- 파일 입출력(대량의 파일을 처리할 떄)

* CPU 연산이 많은 경우 multiprocessing이 더 적함(비동기 작업은 I/O 중심)

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함