Programming/프로그래밍 이론

[프로그래밍 이론] Blocking vs Non-blocking / Sync vs Async

빠른손 2022. 7. 2. 08:43
728x90

백엔드 개발자 채용공고를 확인하고 이력서를 넣어서 서류에 합격해 면접을 보게 되었습니다.

기본 인성관련 질문과 더불어 기술적인 프로그래밍 이론 또한 학습한 후, 면접 당일 면접 장소로 향했습니다.

면접 당일 마주한 내용 중 전혀 들어보지 못한 개념에 대해 질문을 받아 당황했고

"그 부분에 대해선 제가 지식이 부족합니다. 앞으로 학습할 수 있도록 하겠습니다."

라고 답변할 수밖에 없었습니다.

 

그 질문이 바로 오늘 이야기할 주제인

Blocking vs Non-blocking(블로킹 vs 논블로킹)과 Sync vs Async(동기 vs 비동기)

에 관련한 내용이었습니다. 앞에 사설이 길었으므로 아래 설명은 간단하게 해보겠습니다.

 

먼저 4가지 키워드를 하나씩 쪼개서 어떤 내용인지 살펴보겠습니다.

 

✅Blocking

Blocking(블로킹)은 작업을 제어할 수 있는 권한에 초점을 맞춰서 생각하면 편합니다.

어떤 작업을 진행(제어)하던 중인 주체 A와, 다른 또 하나의 주체 B가 작업을 실행하면 B의 작업이 끝날 때까지 대기했다가 B의 작업이 종료되고나서야 A의 작업을 다시 재개(제어)하는 것을 말합니다.

 

Non-Blocking

Non-Blocking(논블로킹)은 앞서 설명드린 블로킹과는 반대되는 개념으로, 다른 주체의 작업에 개의치 않고 자신의 작업 제어권을 가질 수 있는 것을 말합니다.

 

Sync(Synchronous)

프로그램에서 두 가지 이상의 메소드나 어플리케이션(편의상 메소드라고만 부르겠습니다.)이 서로 같은 시간에 시작하고 끝나거나 또는 하나의 메소드가 먼저 시작하고 끝났을 때, 바로 그 결과값을 이어받아 시작하는 것이 동기에 해당합니다.

 

그림으로 예를 들면 아래와 같이 두 가지 형태로 나타날 수 있습니다.

서로 다른 메소드의 실행과 종료가 같은 경우

 

선실행한 메소드의 종료 시점에 다른 메소드가 그 결과값을 이어받아 바로 실행하는 경우

 

Async(Asynchronous)

비동기의 경우 앞서 설명드린 Sync와는 반대되는 개념으로 프로그램에서 두 가지 이상의 메소드가 서로에게 관여하지 않으며 말그대로 비동기적으로 실행되고 종료되는 것을 의미합니다.

 

그림으로 예를 들면 아래와 같은 형태가 될 수 있겠네요.

 

다음으로 각 키워드를 조합했을 때는 어떤 결과가 나타나는지 살펴보겠습니다.

 

✅Blocking + Sync(Synchronous)

앞서 확인한 Blocking은 다른 주체의 작업이 끝날때까지 기다렸다가 비로소 작업이 끝난 후에야 제 작업을 진행하는 것을 의미한다고 했고, Sync는 서로 같은 시간에 시작 및 종료하거나 어떤 한 어플리케이션, 메소드의 종료 시점에 맞춰 다른 메소드가 시작하는 걸 의미한다고 했습니다.

 

Java에서의 예시를 살펴보겠습니다.

public void methodA() {
    String myMsg = methodB();
    System.out.println(myMsg);
};

public String methodB() {
    String msg = "Hello";
};

메소드 A는 메소드 B가 실행되고 결과값을 리턴해줘야만 실행되는 코드라고 가정합니다. 이것은 동기(Sync) 방식입니다.

우선 메소드 B가 실행되기 위해 제어권을 가져오게 됩니다. 메소드 B가 작업을 마친 뒤 결과값을 리턴하고 제어권을 메소드 A에게 전달합니다. 이것은 Blocking에 해당됩니다.

 

✅Non-Blocking + Sync(Synchronous)

이번엔 파이썬에서의 예시를 살펴보겠습니다.

device = IO.open()
ready = False
while not ready:
    print("There is no data to read!")

    # 다른 작업을 처리할 수 있음

    # while 문 내부의 다른 작업을 다 처리하면 데이터가 도착했는지 확인한다.
    ready = IO.poll(device, IO.INPUT, 5) 
data = device.read()
print(data)

위 코드에서 알 수 있듯, while문이 진행되는 동안 자신의 작업을 처리(Non-Blocking)하면서, 결과가 리턴되면 while문을 빠져나와 device.read()를 실행(동기, Sync)하게 됩니다.

 

✅Non-Blocking + Async(Asynchronous)

위 조합의 대표적인 예는 JavaScript에서 API에게 요청을 보내고, 다른 작업을 진행하다가 콜백을 통해 추가적인 작업을 처리할 때 사용하는 것을 예로 들 수 있습니다.

fetch('url', option) .then((response) => { 
    return response.json(); 
}) 
.then((data) => {
    doSomething(data); 
});

 

✅Blocking + Async(Asynchronous)

이 조합은 왠만하면 개발자의 실수때문에 일어나는 조합이라고 합니다. 그만큼 효율이 좋지 않고 굳이 이 방식을 채택해야할 이유가 없기 때문입니다. 개발자가 Non-Blocking + Async를 조합해 사용하려다 실수로 Blocking + Async로 만들어버리는 경우가 있다고 합니다. 😂

 

대표적인 예시가 Node.js 와 MySQL로 구성한 프로젝트입니다.

Node.js로 구성한 프로그램이 callback 처리를 하며 비동기로 실행하고 있는데 DB를 MySQL로 채택하면 DB 작업 호출 시, MySQL에서 제공하는 드라이버를 호출하게 되는데, 이 때의 드라이버가 Blocking방식이라고 합니다.

 

[참고자료]

https://www.youtube.com/watch?v=oEIoqGd-Sns 

https://velog.io/@codemcd/Sync-VS-Async-Blocking-VS-Non-Blocking-sak6d01fhx#21-blocking

https://studyandwrite.tistory.com/486?category=1004636

728x90