Sync/Async, Blocking/Non-Blocking 무슨 차이일까?

maketheworldwise·2022년 3월 3일
8


이 글의 목적

나는 지금까지 동기, 비동기라는 개념에 대해서 너무 쉽게 생각했었다. 하지만 내 생각과는 다르게 더 심오한 내용이 있다는 것을 알고 정리해보자 한다. (애플리케이션에서 스레드가 어떻게 처리되는지 확인할 때 필요한 내용이라고 한다.)

Blocking / Non-Blocking

Blocking과 Non-Blocking은 다른 주체가 작업할 때 자신의 제어권이 있는지 없는지로 구분한다.

Blocking

Blocking은 자신의 작업을 진행하다가 다른 주체의 작업이 시작되면 다른 작업이 끝날 때까지 기다렸다가 자신의 작업을 시작하는 것을 의미한다.

🐶 : 고양이님 서류 전달드리겠습니다.
🐱 : 강아지님 서류 검토 끝날 때까지 기다리세요.

즉, 호출된 함수가 자신이 할 일을 모두 마칠 때까지 제어권을 계속 가지고서 호출한 함수에게 바로 돌려주지 않는 상황을 의미한다.

Non-Blocking

Non-Blocking은 다른 주체의 작업에 관련없이 자신의 작업을 하는 것을 의미한다.

🐶 : 고양이님 서류 전달드리겠습니다.
🐱 : 강아지님 서류 주고 가세요.

즉, 호출된 함수가 자신이 할 일을 모두 마치지 않았더라도 바로 제어권을 건네주어 호출한 함수가 다른 일을 진행할 수 있도록 해주는 상황을 의미한다.

Sync / Async

Sync와 Async는 결과를 돌려주었을 때 순서와 결과에 관심이 있는지 없는지로 판단한다. 즉, 신경을 쓰느냐 안쓰느냐의 차이!

Sync

Sync는 동기라는 뜻으로 작업을 동시에 수행하거나, 동시에 끝나거나, 끝나는 동시에 시작함을 의미한다.

🐶 : 고양이님 서류 전달드리겠습니다.
🐱 : 강아지님 기다리거나 다른 일을 하고 계세요. 강아지님 신경 끌게요~

(...서류 읽는 중)

🐱 : 강아지님 서류 이렇게 하세요
🐶 : 고양이님 바로 처리하겠습니다.

즉, 호출된 함수의 수행 결과 및 종료를 호출한 함수와 함께 신경 쓰는 경우를 의미한다.

Async

Async는 비동기라는 뜻으로 시작과 종료가 일치하지 않고 끝나는 동시에 시작을 하지 않음을 의미한다.

🐶 : 고양이님 서류 전달드리겠습니다.
🐱 : 강아지님 기다리거나 다른 일을 하고 계세요. 강아지님 신경 끌게요~

(...서류 읽는 중)

🐱 : 강아지님 서류 이렇게 하세요
🐶 : 고양이님 나중에 내용을 확인하고 언젠가 처리하겠습니다.

즉, 호출된 함수의 수행 결과 및 종료를 호출된 함수 혼자 직접 쓰고 처리하는 경우를 의미한다.

정리하고 섞어보자

  • Blocking / Non-Blocking : 제어권을 안넘기는지 / 넘기는지
  • Sync / Async: 결과를 돌려줄 때 결과와 순서에 관심이 있는지 / 없는지

이제 이 4개의 개념을 합쳐서 👽 혼종을 만들어보자.

Sync + Blocking / Async + Blocking

우리가 가장 흔히 접하는 혼종이다.

Sync + Non-Blocking

  • Non-Blocking : 제어권을 넘김
  • Sync : 결과를 돌려줄 때 결과와 순서에 관심이 있음

이 두 가지를 합쳐보자. 🤪

호출되는 함수(B)는 결과를 처리하는대로 바로 반환하고, 호출하는 함수(A)는 작업 완료 여부를 신경을 쓰는 형태로 조합이 된다. 신경을 쓰는 방법으로는 기다리거나 물어보는 것 두 가지가 존재하나, Non-Blocking 함수를 호출했기 때문에 물어보는 작업만이 남는다.

따라서 호출되는 함수(B)가 바로 제어권을 돌려주며 호출한 함수(A)는 다른 작업을 수행할 수 있으나, 호출한 함수(A)는 호출되는 함수(B)의 결과를 처리해야하기 때문에 언제 종료되는지 알 수 없는 호출되는 함수(B)의 종료를 반복적으로 물어봐야한다는 의미다.

(호출한 함수(A)가 다른 작업을 수행할 수 있었음에도 불구하고 여전히 호출된 함수(B)의 결과에만 신경쓰기에 제 할 일을 못하게 되는 형태가 된다!! 🤨)

내가 참고한 블로그의 예시가 이해하기 너무 좋게 되어있어서 위의 예시로 변경해보았다.

🐶 : 고양이님 서류처리 부탁드립니다.
🐱 : 강아지님 다른 일을 하고 계세요.
🐶 : 네.
🐱 : (서류 처리 중)
🐶 : 고양이님 서류처리 끝났나요?
🐱 : 강아지님 아직이요.
🐶 : 고양이님 서류처리 끝났나요?
🐱 : 강아지님 아직이요.
🐶 : 고양이님 서류처리 끝났나요?
🐱 : 네.

대표적으로 future.isDone() 코드가 비슷하다고 한다.

Async + Blocking

  • Blocking : 제어권을 넘기지 않음
  • Async : 결과를 돌려줄 때 결과와 순서에 관심이 없음

이 형태는 가장 최악의 조합이지 않을까 싶다. 마찬가지로 이 두 가지를 합쳐보자.

호출한 함수(A)는 호출되는 함수(B)의 작업 결과에 관심이 없음에도 불구하고 호출되는 함수(B)의 결과를 기다리고 있어야 하는 형태다.

🐶 : 고양이님 서류처리 부탁드립니다.
🐱 : 강아지님 처리가 끝날 때까지 기다리세요.
🐶 : 고양이님이 어떤 작업을 하던 저와는 관계없지만 기다릴게요.

이 조합은 큰 이점이 없어 이 방식을 사용할 필요는 없으나 의도치 않게 이 형태로 동작하는 경우가 있다고 한다. 대표적으로 NodeJS와 MySQL의 조합에서 나온다고 한다.

NodeJS에서 콜백 지옥을 해치면서 Async로 전진해도, 결국 DB 작업 호출 시에는 MySQL에서 제공하는 드라이버를 호출하게 되는데, 이 드라이버가 Blocking 방식으로 동작하여 Async+Blocking 구조가 된다고 한다. (Java의 JDBC도 동일하다고 한다.)

전체적으로 확인해보기

우리가 흔히 말하는 동기/비동기는 Sync+Blocking과 Async+Non-Blocking 형태다. 그리고 추가적으로 Sync+Non-Blocking과 Async+Blocking 조합이 존재하는데, 개발할 때는 극히 드물겠지만 애플리케이션 자체에서 의도치 않게 이 두 가지 조합이 나올 경우가 있어서 알아두어야 한다.

조합된 각각의 단어의 의미를 생각해보면 어느정도 틀을 잡고 이해할 수 있다. 제어권을 가지고 있느냐 없느냐결과에 관심이 있느냐 없느냐를 기준으로 접근하여 살펴보면 된다.

이 글의 레퍼런스

profile
세상을 현명하게 이끌어갈 나의 성장 일기 📓

0개의 댓글