동기,비동기,블로킹 IO, 논블로킹 IO

동기와 비동기, 그리고 블로킹 IO/논블로킹 IO를 설명할 때, 이 개념들이 비슷하게 느껴질 수 있다. 이는 생소한 용어로 복잡한 개념을 설명하다 보니 발생하는 혼란이 아닌가 생각된다.

특히 블로킹과 논블로킹을 논할 때 IO를 제외하고 이야기하는 경우도 많다. 예를 들어 "동기 블로킹, 비동기 논블로킹"이라는 표현도 그 예다. IO 없이 설명하려다 보니 동기는 "멈춘다", 블로킹은 "제어권이 넘어간다", 비동기는 "멈추지 않고 이후 작업을 처리한다", 논블로킹은 "제어권을 바로 넘겨받는다"는 식으로 설명되곤 한다. 하지만 이런 설명들은 직관적이지 않으며, 개념의 핵심을 제대로 전달하지 못한다.

동기/비동기와 블로킹 IO/논블로킹 IO의 차이를 이해하기 위해선 관점의 차이를 이해해야 한다. 동기/비동기는 작업(Task) 의 관점에서 본 순서를 의미한다. 동기는 작업들이 순차적으로 처리되는 것이고, 비동기는 코드상으론 순차적으로 표현될 순 있지만 작업들이 순차적으로 처리되지 않을 수 있음을 의미한다. 그리고 병렬로 실행될 수도, 동시성으로 구현될 수도 있다.

반면, 블로킹 IO/논블로킹 IO는 IO를 요청하는 스레드의 관점에서 이해해야 한다. IO 개념 없이 설명하면 "제어권이 넘어간다"거나 "넘겨받는다" 같은 모호한 표현으로 끝날 수밖에 없다. 블로킹 IO는 IO를 요청한 스레드가 작업이 끝날 때까지 대기하는 것이고, 논블로킹 IO는 IO를 요청한 스레드가 대기하지 않고 다른 작업을 계속할 수 있는 것이다. 이렇게 구분하는 이유는 각 개념을 명확하게 이해하기 위해서다.

이렇게 설명을 보면 결국 동기/비동기는 조금 더 개념적인 부분이고, 블로킹 IO/논블로킹 IO는 조금 더 구현적인 부분이다. 그렇기 떄문에 비동기 프로그래밍이라고 부르는 경우는 있지만 논블로킹 프로그래밍이라고 하지 않는 경우도 여기에 있다.

그러면 동기가 구체화되면 블로킹, 비동기가 구체화되면 논블로킹이냐?라는 생각이 들지만 보통은 그렇지만 아닐 수도 있다.

예를 들어, 메인 스레드가 순차적으로 실행되다가 IO 작업을 만나면 별도의 스레드를 생성해 블로킹 IO 작업을 처리하고, 메인 스레드는 흐름을 이어갈 수 있다. 이는 자바 진영에서 스레드 풀을 사용해 비동기 처리를 하는 방식과 유사하다.

반대로 동기도 논블로킹 IO를 통해 구현할 수 있다. 그 예는 코루틴 같은 경우이다. 반면, 비동기 논블로킹 IO는 주로 자바스크립트와 자바의 Netty 같은 라이브러리에서 활용된다. 결론적으로, 동기/비동기와 블로킹 IO/논블로킹 IO는 별개의 개념으로 이해해야 한다. 이 개념을 정확히 알아야 효율적인 IO 처리 방법을 설계할 수 있다.

Last updated