본문 바로가기
Language/Javascript

블로킹(Blocking)/논블로킹(Non-Blocking), 동기(Sync)/비동기(Async) 구분하기

by joooing 2021. 6. 10.
반응형

보통 동기 = 블로킹을 같은 개념으로, 비동기 = 논블로킹을 같은 개념으로 헷갈리는 경우가 많다. 하지만 두 개념은 각각을 구분짓는 기준이 전혀 다르다. 블로킹/논블로킹은 한 작업이 처리되는 동안 다른 작업도 처리될 수 있는지에 대한 이야기이고, 동기/비동기는 작업들이 시간을 맞춰서 실행되는지 아닌지에 대한 이야기이다. 이렇게만 들어서는 아직 무슨이야기인지 헷갈리는게 당연하다. 하나씩 무슨 말인지 예시와 함께 살펴보자!

 

1. 블로킹(blocking) vs 논블로킹(non-blocking)

우리가 어떤 프로그램을 만들었다고 해보자. 아마 어떤 코드를 작성해서 만들었을 것이고, 이 코드는 수많은 함수들이 순서대로 나열되어있는 모습일 것이다. 이렇게 한 프로그램은 여러개의 함수들로 이루어져 있다.

 

어떤 함수 안에 여러개의 함수들이 있다고 가정해보자. 아마 이런 모습일 것이다. (설명의 편의를 위해 부모함수와 자식함수 A, B라고 부르도록 하겠다)

 

function 부모함수() {
  A();
  B();
  ...
}

 

설명 전, 먼저 알아야할 개념들이 있는데 제어권, 결과값이라는 말이다. 사실 우리가 이미 다 아는 말인데 어렵게 표현했을 뿐이다. 내 방식대로 간단히 요약하면 이렇다.

 

제어권 = 함수 내용을 실행시킬 수 있는 권리 (행동의 자유)
결과값 = 함수의 리턴값

 

제어권은 말 그대로 '권한'이다. A 함수의 내용이 아래와 같다고 했을 때, A에게 제어권이 있어야 함수 안에 있는 작업들이 실행될 수 있다. 결과값우리가 보통 말하는 함수의 리턴값이다. 여기서 결과값은 3이 될 것이라고 쉽게 예상할 수 있다. 그런데 여기서 주의할 점이 하나 더 있다. 꼭 결과값은 3이 아니어도 된다는 것이다. 만약 A가 아직 계산을 끝마치지 못했는데, 갑자기 결과값을 요구한다면 '아직 계산못함'을 임시 결과값으로 내보낼 수도 있다.

 

function A() {
  let a = 1;
  let b = 2;
  let sum = a + b;
  return sum;
}

 

이제 다시 블로킹, 논블로킹에 대해서도 이야기해보자. 여기서 블로킹다른 함수를 호출할 때, 제어권도 아예 함께 넘겨주고 작업이 끝난 후에 돌려받는 방식이다. 위의 예시에선 부모함수가 A를 실행시킬 때 제어권을 아예 넘겨주게 되어서, 본인은 다른 일을 하지 못하고 A의 작업이 끝날때까지 마냥 기다리는 것이다. 그러다 A의 작업이 끝나면 제어권을 돌려받고 다음함수인 B를 실행시킨다.

 

논블로킹도 마찬가지로 호출할 때 제어권을 넘겨주기는 하지만, 바로 돌려받는다. A의 작업이 안끝나도 바로 제어권을 돌려받고 부모함수는 B작업을 시작하는 것이다. 호출된 A는 알아서 실행되도록 놔둔다. 그러면 이 A는 작업을 마치고 값을 어떻게 리턴해야할까..? 이와 관련해서는 조금 후 동기, 비동기에 대해 설명하면서 이야기하도록 하겠다.

 

일단 지금까지 설명한 내용을 바탕으로 정리해보면 블로킹과 논블로킹의 차이점은 이렇다.

 

블로킹(blocking)

  • 요청자(부모함수)는 요청한 작업이 끝날 때까지 다른 작업을 하지 않고 마냥 기다림
  • 다른 함수를 호출할 때, 제어권도 아예 함께 넘겨주고 그 작업이 끝난 후에야 돌려받기 때문
  • (제어권이 없는 상태라 아무것도 못함)
  • 요청받은함수는 모든 실행을 마치고 최종 return 값을 돌려줌

논블로킹(non-blocking)

  • 요청자는 요청한 작업이 수행되는 동안 다른 작업을 할 수 있음
  • 다른 함수를 호출할 때, 제어권을 넘겨주기는 하지만 바로 돌려받음
  • (제어권을 돌려받은 호출자는 다른 작업을 바로 수행 가능)

 

일상 생활에 비유를 해보자면, 내가 요청하고 상대방이 요청받는 경우라고 가정했을 때, 블로킹은 요청해놓고 아무것도안하고 그것만 주구장창 기다리는 것이고, 논블로킹은 요청해놓고 다른 할 일을 하고있는 방식이라 할 수 있다. 그러면 다음으로는 동기, 비동기에 대해 알아보자!

 

 

2. 동기(Synchronous) vs 비동기(Asynchronous)

블로킹/논블로킹을 구분짓는 기준은 '요청받은 함수가 제어권을 언제 돌려주는지' 였다. 이번에 이야기할 동기/비동기는 작업을 실행하는 여러개의 함수들이 '시간을 맞춰서 실행되느냐'에 따라 구분된다고 할 수 있다. 먼저 함수들이 시간을 맞춰 실행되는 동기 방식부터 살펴보자.

 

동기(Sync)

일단 '시간을 맞춘다'는 말은 무슨 뜻일까? 쉽게 말해 함수가 두 개 이상 존재할 때, 이 함수들이 작업을 동시에 시작하거나, 끝나는 타이밍을 맞추거나, 하나가 끝나고 다른 하나를 차례로 실행하는 것을 시간을 맞춘다고 한다. 함수들끼리 어느정도 작업 시간에 대한 규칙(?)을 정해놓는 방식이라고 표현할 수 있을 것 같다.

 

이런 규칙을 정하고 지킬 수 있는 이유는, 요청자가 요청한 일들이 완료되었는지를 계속 확인하기 때문이다. 요청하는 함수는 요청을 보내놓고, 요청을 처리하는 함수들이 작업을 마쳤는지 계속해서 물어본다. 요청자는 완료가 되었다는 응답을 받으면, 그때 다른 함수의 실행을 시작하거나 하는 것이다.

동기는 또 다른 관점에서는, 제어권과 결과값을 동시에 반환하는 것을 말하기도 한다. 아까 봤던 예시를 그림으로 표현한 것인데, 여기서 호출된 A는 작업을 마치고 자신을 호출한 부모함수에게 결과값(3)을 알려주면서, 동시에 제어권도 함께 돌려준다.

 

 

비동기(Async)

비동기는 동기적이지 않은 방식을 말한다. 다시말해 두 함수는 서로가 언제 시작하고, 언제 일을 마치는지 전혀 신경쓰지 않는 것이다. (개인플레이..) 이 경우에는 요청자는 작업을 요청해놓고 계속 완료되었는지 확인하는게 아니라, 알아서 알려주겠거니 하고 있는다. 다시말해 요청을 받은 함수가 완료되었는지 여부를 알아서 알려주는 방식이다. 이렇게 작업을 시작하고 끝내는 시간을 아는 것은 호출된 함수 본인뿐이기 때문에, 여러 함수들이 시작되고 끝나는 시간은 맞춰지지 않을 수 있게 된다. 혹은 결과값과 제어권이 다른 시점에 따로따로 반환되는 것도 비동기라고 할 수 있다.

이번에도 내가 요청하고, 상대방이 요청받는 경우라고 비유를 해보면, 동기요청작업이 끝났는지 내가 계속 물어보고 그 시간에 맞춰서 다른 작업을 수행하는 방식이고, 비동기작업을 해달라는 요청만 해놓고 더이상 신경쓰지 않고 있다가, 상대방이 끝나면 끝났다고 말해주는 방식이라 할 수 있다.

 

 

블로킹/논블로킹, 동기/비동기 요약

블로킹/논블로킹 = 요청받는 함수가 제어권(함수실행권)을 언제 넘겨주느냐의 차이

 

블로킹 : 요청받는 함수가 작업을 모두 마치고 나서야 요청자에게 제어권을 넘겨줌 (그동안 요청자는 아무것도 하지않고 기다림)

논블로킹 : 요청받은 함수가 요청자에게 제어권을 바로 넘겨줌 (그동안 요청자는 다른 일을 할 수 있음)

 

동기/비동기 = 요청받은 함수가 작업을 완료했는지를 누가 체크하느냐의 차이

 

동기 : 요청자가 요청받은 함수의 작업이 완료되었는지 계속 확인 (여러 함수들이 시간을 맞춰 실행됨)

비동기 : 요청자는 요청후 신경X, 요청받은 함수가 작업을 마치면 알려줌 (함수들의 작업 시작/종료 시간이 맞지 않을수도)

 

 

블로킹/논블로킹, 동기/비동기 조합

지금까지 배운 개념들로 아래 표처럼 총 네 가지의 조합을 만들어낼 수 있다. 하지만 아직도 개념들이 애매하게 느껴지면, 바로 이해하기 힘들 수도 있을 것 같아 예시를 가지고 조금 더 이 조합들에 대해 설명하고자 한다. 개발자로 일하는 나와 나에게 일을 부탁하는 선배의 이야기를 예시로 들어보도록 하겠다..!

 

 

블로킹 + 동기

요청받은 함수의 작업이 끝나야 제어권 돌려받음 + 요청자는 결과가 나올때까지 계속 확인

 

선배 : 이것좀 부탁해요~

나 : 네 바로 끝나니까 기다려주세요

선배 : (아무것도 안하고 기다림, 언제끝나는지 궁)

나 : (타닥타닥..)

선배 : (지켜보는중)

선배 : 오 끝났네요!

 

블로킹 + 비동기

요청받은 함수의 작업이 끝나야 제어권 돌려받음 + 결과는 요청받은 함수가 알려줌

 

선배 : 이것좀 부탁해요~

나 : 네 바로 끝나니까 기다려주세요

선배 : (아무것도 안하고 기다림, 언제끝나는지 관심없음)

나 : (타닥타닥..)

나 : 끝났어요!

 

논블로킹 + 동기

제어권은 바로 돌려줌 + 요청자는 결과가 나올때까지 계속 확인

 

선배 : 이것좀 부탁해요~

나 : 넵 (타닥타닥..)

선배 : (할거 하다가) 다하셨나요?

나 : 잠시만요

선배 : (할거 하다가) 다하셨나요?

나 : 네 여기요~

 

논블로킹 + 비동기

제어권은 바로 돌려줌 + 결과는 요청받은 함수가 알아서 알려줌

 

선배 : 이것좀 부탁해요~

나 : 넵 다하고 말씀드릴게요! (타닥타닥..)

선배 : (할일 하는 중)

나 : 끝났어요 여기요!

 

 

마무리

지금까지 블로킹, 논블로킹과 동기, 비동기의 차이점과 각각을 조합했을 경우에 대해 알아보았다. 동기와 비동기같은 경우는 시점과 관련된 개념이라 실제 코드에서 경계를 구분하기가 애매할 것 같기도 하다. 그래도 동기와 블로킹, 비동기와 논블로킹의 개념을 혼용해서 써왔던 것 같은데 글로 정리하면서 어느정도 구분이 지어진 것 같다. 이번에는 개념적인 차이점을 중심으로 공부했는데, 실제 코드나 작동되는 예시들도 좀 더 찾아보려고 한다.

 

참고

반응형

댓글