1 minute read

동기(Synchronous)는 작업을 순서대로 실행하며, 현재 작업이 끝날 때까지 다음 작업이 기다리는 방식이라면 비동기(Asynchronous)는 어떤 작업을 시작한 뒤, 그 작업이 완료될 때까지 기다리지 않고 다른 작업을 수행할 수 있는 처리 방식이다.

1. 동기와 비동기

동기 방식

동기 방식은 작업을 순서대로 실행하며, 현재 작업이 끝날 때까지 다음 작업이 기다리는 방식.

다음과 같은 코드는 동기 방식으로 동작한다.

import time

def task_a():
	print("A 작업 시작")
	time.sleep(3)
	print("A 작업 완료")
	
def task_b():
	print("B 작업 시작")
	time.sleep(1)
	print("B 작업 완료")
	
task_a()
task_b()

실행 결과:

A 작업 시작
(3초 대기)
A 작업 완료
B 작업 시작
(1초 대기)
B 작업 완료

전체 실행 시간은 4초가 된다.

비동기 방식

비동기 방식은 작업을 시작한 뒤, 해당 작업의 완료를 기다리는 동안 다른 작업을 수행할 수 있는 방식.

Python 에서는 asyncio 를 사용해서 비동기 처리를 할 수 있다.

import asyncio

async def task_a(): # 비동기 함수로 선언
    print("A 작업 시작")
    await asyncio.sleep(3) # 비동기 작업의 결과를 기다리면서 실행 제어를 넘김
    print("A 작업 완료")

async def task_b(): # 비동기 함수로 선언
    print("B 작업 시작")
    await asyncio.sleep(1) # 비동기 작업의 결과를 기다리면서 실행 제어를 넘김
    print("B 작업 완료")

async def main():
    await asyncio.gather( # 여러 비동기 작업을 동시 실행
        task_a(),
        task_b()
    )

asyncio.run(main())

실행 결과:

A 작업 시작
B 작업 시작
(1초 대기)
B 작업 완료
(2초 대기)
A 작업 완료

전체 실행 시간은 3초가 된다.

2. 비동기를 사용하는 이유

비동기 작업 방식이 유용한 상황은 작업이 완료되기까지 대기 시간이 긴 경우이다. 다양한 애플리케이션에서 대기 시간이 발생하는 작업에 대해서 유용하게 사용할 수 있다.

작업 대기 상황
HTTP 요청 서버의 응답을 기다리는 상황
데이터베이스 조회 DB의 응답을 기다리는 상황
파일 읽기 디스크에서 데이터를 읽는 상황
네트워크 통신 다른 시스템과 통신을 기다리는 상황

예를 들어, 웹 서버가 1,000명의 사용자로부터 HTTP 요청을 받는다고 한다면, 동기 방식에서는 첫 번째 요청을 처리하는 시간 동안 다음 요청이 대기를 해야 해서 응답이 오래 걸릴 수 밖에 없지만 비동기 방식에서는 첫 번째 요청을 처리하는 동안 두 번째, 세 번째 요청을 처리할 수 있는 장점이 있다. 보통 네트워크 I/O가 많이 발생하는 애플리케이션에서 비동기는 성능 측면에서 큰 장점을 제공한다.

3. 비동기와 멀티스레드, 멀티프로세스의 차이

비동기의 동작 방식을 보면 병렬처럼 보이지만 실제로는 다른 개념이다.

구분 개념
동기 작업 완료를 기다린 후 다음 작업을 진행
비동기 작업 완료를 기다리는 동안 다른 작업 진행
멀티스레드 여러 스레드에서 작업 실행
멀티프로세스 여러 프로세스에서 작업 실행

비동기는 작업을 기다리는 방식에 대한 개념으로 멀티스레드와는 구분해서 생각해야 한다. 실제로는 작업을 번갈아 처리할 수 있는 개념으로 작업이 병렬로 처리되는 개념과 다르다.