[Python] Asyncio 비동기 처리

Jimin_Note·2022년 7월 30일
0

[Python]

목록 보기
30/34
post-thumbnail

def 키워드로 선언하는 모든 함수는 파이썬에서 기본적으로 동기 방식으로 동작한다고 생각하자

def do_sync():
    pass

기존 def 키워드 앞에 async 키워드까지 붙이면 이 함수는 비동기 처리되며, 이러한 비동기 함수를 파이썬에서는 코루틴(coroutine)이라고 한다.

async def do_async():
    pass

이러한 비동기 함수는 일반 동기 함수가 호출하듯이 호출하면 coroutine 객체가 리턴

do_async() 

#<coroutine object do_async at 0x1038de710>

따라서 비동기 함수는 일반적으로 async로 선언된 다른 비동기 함수 내에서 await 키워드를 붙여서 호출해야 한다

async def main_async():
    await do_async()

자바스크립트에서 async로 선언된 비동기 함수를 호출할 때 await 키워드를 붙이지 않으면 Promise 객체를 리턴하는 것과 같음

asyncio.run(main_async())

실습

외부 API는 1명의 사용자 데이터를 조회하는데 1초가 걸리고, 한 번에 여러 사용자의 데이터를 조회할 수 없다.
각각 3명, 2명, 1명의 사용자 정보를 조회하는 요청 3개가 동시에 애플리케이션에 들어옵니다.

  • 동기 프로그래밍
import time

def find_users_sync(n):
    for i in range(1, n + 1):
        print(f'{n}명 중 {i}번 째 사용자 조회 중 ...')
        time.sleep(1)
    print(f'> 총 {n} 명 사용자 동기 조회 완료!')

def process_sync():
    start = time.time()
    find_users_sync(3)
    find_users_sync(2)
    find_users_sync(1)
    end = time.time()
    print(f'>>> 동기 처리 총 소요 시간: {end - start}')

if __name__ == '__main__':
    process_sync()

이 함수를 호출해보면 find_users_sync 함수가 총 6초 동안 3번 순차적으로 실행됨을 알 수 있습니다.

3명 중 1번 째 사용자 조회 중 ...
3명 중 2번 째 사용자 조회 중 ...
3명 중 3번 째 사용자 조회 중 ...
>3 명 사용자 동기 조회 완료!

2명 중 1번 째 사용자 조회 중 ...
2명 중 2번 째 사용자 조회 중 ...
>2 명 사용자 동기 조회 완료!

1명 중 1번 째 사용자 조회 중 ...
>1 명 사용자 동기 조회 완료!

>>>동기 처리 총 소요 시간: 6.020448923110962

<소요시간>
첫 번째 요청이 처리되는데는 3초, 두 번째 요청은 5초(3 + 2), 세 번째 요청은 6초(3 + 2 + 1)

  • 비동기 프로그래밍

time.sleep 함수는 기다리는 동안 CPU를 그냥 놀리는 반면에, asyncio.sleep 함수는 CPU가 놀지 않고 다른 처리를 할 수 있도록 한다. 여기서 주의할 점은 asyncio.sleep 자체도 비동기 함수이기 때문에 호출할 때 반드시 await 키워드를 붙여야 한다는 것!

import time
import asyncio

async def find_users_async(n):
    for i in range(1, n + 1):
        print(f'{n}명 중 {i}번 째 사용자 조회 중 ...')
        await asyncio.sleep(1)
    print(f'> 총 {n} 명 사용자 비동기 조회 완료!')

async def process_async():
    start = time.time()
    await asyncio.wait([
        find_users_async(3),
        find_users_async(2),
        find_users_async(1),
    ])
    end = time.time()
    print(f'>>> 비동기 처리 총 소요 시간: {end - start}')

if __name__ == '__main__':
    asyncio.run(process_async())

비동기 처리되도록 재작성된 코드를 실행해보면 호출 순서와 무방하게 실행 시간이 짧은 수록 먼저 처리된다.
게다가 총 소요 시간도 6초에서 3초로 단축

1명 중 1번 째 사용자 조회 중 ...
2명 중 1번 째 사용자 조회 중 ...
3명 중 1번 째 사용자 조회 중 ...
>1 명 사용자 비동기 조회 완료!

2명 중 2번 째 사용자 조회 중 ...
3명 중 2번 째 사용자 조회 중 ...
>2 명 사용자 비동기 조회 완료!

3명 중 3번 째 사용자 조회 중 ...
>3 명 사용자 비동기 조회 완료!

>>> 비동기 처리 총 소요 시간: 3.0041661262512207

기본적으로 비동기 처리는 정확히 실행 순서가 보장되지 않기 때문에, 약간 실행 순서가 다를 수 있지만 여기서 중요한 점은 CPU를 놀리지 않고 불필요한 지연없이 3개의 요청에 대한 응답 가능

profile
Hello. I'm jimin:)

0개의 댓글