비동기(Asynchronous)란?
이해를 돕기 위해 약간은 비현실적인 예를 들어보겠습니다. 여러분들은 10대의 세탁기를 돌리고, 10대의 커피포트에 물을 끓여야 합니다. 이 일을 하기 위한 방법은 아래와 같이 두 가지 방법이 있습니다.
첫번째 방법
- 1번 세탁기를 돌린다.
- 1번 세탁기가 완료될 때까지 기다린다.
- 1번 세탁기에서 빨래를 수거한다.
- 2번 세탁기를 돌린다.
- 2번 세탁기가 완료될 때까지 기다린다.
- 2번 세탁기에서 빨래를 수거한다.
- ... (위의 과정 반복)
- 10번 세탁기를 돌린다.
- 10번 세탁기가 완료될 때까지 기다린다.
- 10번 세탁기에서 빨래를 수거한다.
- 1번 커피포트에 물을 끓인다.
- 1번 커피포트의 물이 끓기를 기다린다.
- 1번 커피포트의 물로 녹차를 탄다.
- 2번 커피포트의 물을 끓인다.
- 2번 커피포트의 물이 끓기를 기다린다.
- 2번 커피포트의 물로 녹차를 탄다.
- ... (위의 과정 반복)
- 10번 커피포트의 물을 끓인다.
- 10번 커피포트의 물이 끓기를 기다린다.
- 10번 커피포트의 물로 녹차를 탄다.
두번째 방법
- 1번 세탁기를 돌린다.
- 1번 세탁기가 완료되길 기다리지 않고 2번 세탁기를 돌린다.
- ... (위의 과정 반복)
- 9번 세탁기가 완료되길 기다리지 않고 10번 세탁기를 돌린다.
- 10번 세탁기가 완료되길 기다리지 않고 1번 커피포트에 물을 끓인다.
- 1번 커피포트의 물이 끓길 기다리지 않고 2번 커피포트에 물을 끓인다.
- ... (위의 과정 반복)
- 10번 커피포트에 물을 끓인다.
- 각 작업이 완료되는 순서대로 처리한다. (빨래 수거/녹차 타기)
여러분들은 위의 두 가지 방법 중 어떤 방법을 택하시겠습니까? 당연히 두 번째 방법을 택하실 겁니다.
두 번째 방법으로 일을 처리하는 것을 비동기적 처리라 하고, 첫 번째 방법으로 일을 처리하는 것을 동기적 처리라고 합니다. 비동기적 처리 방식과 동기적 처리 방식의 가장 큰 차이는 기다리는 시간의 존재 여부입니다. 비동기 처리 방식에서는 기다리는 시간을 매우 싫어합니다. 아무것도 하지 않고 기다리는 시간이 발생하면 바로 다른 작업을 시작합니다. (물론 더 할 작업이 없다면 기다리는 시간이 발생할 수밖에 없습니다.) 반면, 동기적 처리 방식에서는 하나의 작업을 시작하면 그 작업이 끝날 때까지 다른 작업을 시작하지 않습니다. 따라서 기다리는 시간이 길면 길수록 엄청난 시간을 낭비하게 됩니다.
프로그래밍에서도 이 개념이 똑같이 적용됩니다. 응답을 기다려야 하는 일이 발생했을 때 기다리지 않고 바로 다른 작업을 하는 것이 비동기적 프로그래밍, 응답이 올 때까지 기다린 이후에 다른 작업을 하는 것을 동기적 프로그래밍이라고 합니다.
멀티쓰레드 vs 비동기
이는 멀티쓰레드 와 비슷하다고 생각하실 수도 있지만, 쓰레드 비동기 처리에는 큰 차이가 있습니다. 위의 예시를 조금 바꿔보겠습니다. 이번에는 10명의 사람에게 각각 한대의 세탁기를 맡게 해서 일을 시킬 수도 있습니다. (커피포트는 생략하겠습니다.) 하지만, 이들은 동시에 일을 할 수는 없습니다. (파이썬의 GIL 때문입니다. 궁금하시면 여기를 확인해주세요!) 이들이 일을 하기 위해서는 다음과 같은 과정을 거칩니다.
- 사람 1은 1번 세탁기를 돌립니다.
- 사람 1은 사람 2에게 일을 하라고 전화를 합니다. 사람 1은 하던 일을 멈춥니다.
- 사람 2는 사람 1의 전화를 받고, 2번 세탁기를 돌립니다.
- 사람 2는 사람 3에게 일을 하라고 전화를 합니다. 사람 2는 하던 일을 멈춥니다.
- ...
- 사람 10은 사람 9의 전화를 받고 10번 세탁기를 돌립니다.
- 사람 10은 사람 1에게 일을 하라고 전화를 합니다. 사람 10은 하던 일을 멈춥니다.
- 사람 1은 사람 10의 전화를 받고 일을 하러 갑니다. 그런데 1번 세탁기가 완료되지 않았습니다.
- 사람 1은 사람 2에게 일을 하라고 전화를 합니다. 사람 1은 하던 일을 멈춥니다.
- 사람 2는 사람 1의 전화를 받고 일을 하러 갑니다. 그런데 2번 세탁기가 완료되지 않았습니다.
- 사람 2는 사람 2에게 일을 하라고 전화를 합니다. 사람 2는 하던 일을 멈춥니다.
- ... (위의 과정 반복)
- 5번 세탁기가 가장 먼저 완료되었습니다. (가정입니다.)
- 하지만 현재 일의 통제권을 가진 사람은 사람 1입니다.
- 사람 1은 사람 2에게, 사람 2는 사람 3에게, ... 사람 4는 사람 5에게 전화를 하면서 통제권을 넘깁니다.
- 사람 5가 빨래를 수거합니다.
- ... (위의 과정 반복)
- 모든 빨래가 수거되었습니다.
2번 세탁기를 돌리기 위해 1번 세탁기가 다 되길 기다리지 않아도 돼서 첫 번째 방법보다는 빠르게 일을 끝낼 수 있을 것 같습니다. 하지만, 비동기 방식에 비해서는 여전히 비효율적인 점이 눈에 보입니다
- 다른 사람에게 일을 넘기기 위해 걸리는 시간(전화 시간)이 낭비됩니다.
- 작업이 끝나지 않았음에도 일을 확인해야 합니다. 즉, 쓸데없는 리소스 낭비가 있습니다.
- 작업이 끝나더라도 해당 사람이 통제권을 가질 때까지 처리할 수 없습니다.
따라서, 일을 시키고(요청하고) 기다려야 하는 경우에는 비동기적인 방식이 다른 방식들에 비해 더 나은 효율을 가질 수 있습니다. 프로그래밍에서는 특히 데이터를 요청하고 응답을 기다리는 네트워크 IO
에서 큰 성능 향상을 기대할 수 있습니다.
파이썬에서 비동기 프로그래밍 시작하기
2편에서는 실제 파이썬 코드로 비동기를 구현해보겠습니다.
'개발 > 파이썬' 카테고리의 다른 글
파이썬과 비동기 프로그래밍 #3, 파이썬에서 비동기 프로그래밍 활용하기 (14) | 2019.03.01 |
---|---|
파이썬과 비동기 프로그래밍 #2, 파이썬에서 비동기 프로그래밍 시작하기 (0) | 2019.03.01 |
파이썬의 컨텍스트 매니저 (Context Manager) 에 대해 알아봅시다. (4) | 2019.03.01 |
파이썬 단위 테스트 모듈 unittest에 대해 알아보자 (0) | 2019.02.24 |
ANACONDA 자주쓰는 명령어 정리 (0) | 2019.02.17 |