Blocking I/O와 Non-Blocking I/O, Sync와 Async

이건희·2024년 3월 23일

요번에 책을 읽으면서 Blocking I/O와 Non-Blocking I/O에 대해서 궁금증이 생겨 자세한 내용을 찾아보게 되었다. 예전에 Node.js가 Non-Blocking I/O라는 말을 들었는데 그땐 정확히 이해하지 못한채 넘어갔던 것 같다. 이번 기회에 확실히 하고자 한번 찾아보았다.

I/O란?

우선적으로 I/O란 말을 프로그래밍을 하다보면 자주 접할 것이다. I/O란 Input, Output을 의미하는 말로, 대부분 키보드 입력, 모니터 출력 이런식으로 단순하게 생각하지만 사실 프로세서와 메모리, 확장 슬롯, 마더보드에서 일어나는 데이터 전송도 I/O라고 일컬어지고, 네트워크를 통해 데이터를 송수신 하는 것도 I/O라고 칭한다.

또한 I/O는 CPU 연산 속도에 비해 매우 느리다. 따라서 이를 어떻게 관리하느냐에 따라 어플리케이션의 성능이 좌지우지 된다.


Blocking I/O

그러면 Blocking I/O란 무엇일까?

I/O 작업이 진행 되는 동안 프로세스가 작업을 중단한 채 I/O가 끝날때까지 대기하는 방식을 의미한다

한번 그림을 보자.

위 그림과 같이 어플리케이션이 커널(Kernel)에 시스템 콜(System Call)을 하고 입출력 처리가 완료 될때까지 대기한다. 즉, 제어권을 넘겨준다.

여기서 System Call이란 어플리케이션이 커널의 기능을 사용하기 위해 커널에 요청하는 것을 의미한다.

  • 만일 단일 스레드라면, 입출력이 완료 될때까지 멈춰 있는다.

  • 멀티 스레드 환경에서 I/O 작업으로 실행 중인 스레드가 멈추게 되면 CPU는 문맥 교환(Context Switching)을 통해 다른 스레드에게 CPU 자원을 할당 시킨다. 이 과정에서 문맥 교환이 잦으므로 오버헤드가 발생하여 성능이 떨어지게 된다.


Non-Blocking I/O

직감적으로 Non-Blocking I/O는 위에서 살펴본 Blocking I/O의 반대라는 것을 예상할 수 있다. Non-Blocking I/O는 I/O 작업이 끝나지 않아도 제어권을 다시 돌려 받는다.

제어권을 돌려 받은 프로그램은 일정 주기마다 I/O 작업이 완료 됐는지 확인을 하는데, 이를 Polling 이라고 한다.

스레드는 중단 없이 계속 실행되기 때문에 문맥 교환이 필요하지 않다.

Non-Blocking과 Blocking의 차이는 다른 주체가 작업할 때 물리적으로 자신의 제어권이 있는지가 기준이다.


Synchronous(동기)

Blocking, Non-Blocking I/O를 살펴보다 보면 자연스럽게 Sync, Async에 대한 개념도 나온다. 이들이 무슨 차이가 있는지 알아보자.

Blocking, Non-Blocking I/O는 제어권이 어디에 있느냐가 관건이였다면, Sync와 Async는 작업들의 순서가 보장 되는지, 아닌지가 관건이다.

  • Sync 방식에서는 함수 A의 작업이 끝날 때까지 함수 B는 대기하고, A가 끝나야 B가 실행된다. 마찬가지로 C도 같은 방식으로 동작한다.

  • 즉, 작업을 수행할 때 해당 작업의 완료 여부를 신경쓴다.

  • 이는 Blocking 방식과 유사하지만 작업 순서가 보장된다는 것에서의 관점의 차이가 있다.


Asynchronous(비동기)

  • Async 방식은 A 함수의 완료 여부와 상관 없이, B 함수가 동작한다. C도 마찬가지이다.

  • 작업 완료 여부를 신경쓰지 않으므로, 동시적으로 실행될 수 있다.


총정리

내가 이해한 바로는 Sync와 Blocking, Async와 Non-Blocking은 거의 비슷한 내용이지만 얼마나 포괄적이냐의 차이 같다.

Blocking과 Non-Blocking은 특정 작업에 대해 어떻게 처리할 것인지의 차이이다. 예를 들면, 식당에서 음식을 주문한다 하면, 음식을 주문하고 음식을 받는 것을 어떻게 처리할 것인지이다.

  • Blocking: 음식을 주문하고 음식이 나올때까지 기다린다.

  • Non-Blocking: 음식을 주문하고 나올때까지 친구와 수다를 떨다 음식을 받는다.

Sync와 Async는 음식을 주문하고, 식사를 하는 과정을 어떻게 처리할 것인지이다.

  • Sync: 음식을 주문하고 기다리다가 음식이 나오면 식사를 한다.

  • Async: 음식을 주문하고 다른 일을 하고 있다가 직원이 알려주면 음식을 받아 식사를 한다.

좀 모호할 수 있지만, 정리 하자면,

  • 블로킹은 '한 작업의 내부에서 어떻게 처리할 것인가'에 초점을 맞추고,

  • 동기는 '여러 작업들 사이의 진행 순서'에 관한 방식을 의미한다.


이미지 출처: https://velog.io/@hotdari90/Async-Sync-Blocking-Non-Blocking

profile
백엔드 개발자가 되겠어요

0개의 댓글