비동기 프로그래밍은 작업을 순차적으로 실행하는 대신, 작업이 완료될 때까지 기다리지 않고 다른 작업을 실행할 수 있는 프로그래밍 방식이다. 이를 통해 프로그램의 성능과 효율성을 향상시킬 수 있다. 이와 반대되는 개념은 동기 프로그래밍인데 동기 프로그래밍은 작업이 순차적으로 실행하며 이전 작업이 완료될 때까지 기다렸다가 다음 작업을 실행하는 방식이다.
나는 팀 내 업무 효율성을 높이기 위해 업비트에서 제공하는 Open API로 다양한 애플리케이션(서버)을 만들어 서빙하고 있다. 이 과정에서 수많은 API 호출이 일어나게 되는데 동기 프로그래밍 방식은 응답 대기 시간으로 인해 응답성이 저하되고 시스템 성능이 저하되는 문제를 야기한다.
예를 들어, 입금할 수 있는 디지털 자산 목록을 받아오는 API와 출금할 수 있는 디지털 자산 목록을 받아오는 API, 그리고 주문할 수 있는 디지털 자산 목록을 받아오는 API를 가지고 현재 거래 가능한 디지털 자산 목록을 반환하는 서비스를 만들었다고 가정해 보자.
일반적인 동기 프로그래밍의 경우, 먼저 입금 가능한 디지털 자산 목록을 조회하는 요청을 보내고 해당 응답을 받을 때까지 기다린다. 그리고 응답을 받으면 두 번째 API를 요청하는 순서로 진행된다. 그러나 첫 번째 API 요청과 응답에 지연이 발생하면, 두 번째 API는 첫 번째 API 응답을 기다리는 동안 대기하게 된다. 이러한 동기 프로그래밍 방식은 응답성 저하와 시스템 성능 저하에 직접적인 영향을 미친다.
이때, 비동기 프로그래밍 방식을 활용하면 다음과 같이 개선해 볼 수 있다.
각각의 API 호출을 비동기적으로 처리하여 하나의 API 요청이 응답을 기다리는 동안에도 다른 API 요청을 동시에 처리한다. 이를 통해 API 호출 간의 응답 대기 시간을 최소화하고 시스템의 응답성을 향상할 수 있다. 이는 멀티 스레드와 같이 병렬 처리가 가능한 시스템으로 구축하면 더욱 효율적인 애플리케이션 운용이 가능하다.
간단한 예시로 동기 프로그래밍과 비동기 프로그래밍을 살펴보자.
동기 프로그래밍 실행 결과
동기 프로그래밍은 Task 1이 시작되고 완료된 후 Task 2가 시작되는 것을 볼 수 있다.
import time
def sync_task(name):
print(f"{name} 작업 시작")
time.sleep(2) # 2초 동안 작업 수행
print(f"{name} 작업 완료")
# 동기적으로 두 작업을 순차적으로 실행
sync_task("Task 1")
sync_task("Task 2")
---
# 실행 결과
Task 1 작업 시작
Task 1 작업 완료
Task 2 작업 시작
Task 2 작업 완료
비동기 프로그래밍 실행 결과
그에 반해 비동기 프로그래밍은 Task 1과 Task 2가 동시에 시작되는 것을 확인할 수 있다.
import time
import asyncio
async def async_task(name):
print(f"{name} 작업 시작")
await asyncio.sleep(2) # 2초 동안 작업 수행
print(f"{name} 작업 완료")
async def main():
# 비동기적으로 두 작업을 동시에 실행
task1 = async_task("Task 1")
task2 = async_task("Task 2")
await asyncio.gather(task1, task2)
asyncio.run(main())
---
# 실행 결과
Task 1 작업 시작
Task 2 작업 시작
Task 1 작업 완료
Task 2 작업 완료