무릇 모든 개발자들, 아니 비단 개발자가 아니라 할지라도 컴퓨터 관련 산업계 종사자들이라면 오다 가다 한 번씩은 꼭 들어보고, 또 익혔음직한 내용이겠습니다. 이름하야, 동기(Synchronous)와 비동기(Asynchronous), 그리고 블럭(Blocking)과 넌블럭(Non-blocking)


IBM Article

이 주제로 조금만 구글링해보면 바로 찾아볼 수 있는 이미지로 시작해보겠습니다.

figure

바로 그 전설의 레전드..


이는 지금으로부터 13년 전(!)인 2006년 8월 29일 당시 IBM DeveloperWorks Library에 article로 게재된 글 Boost application performance using asynchronous I/O에서 사용된 도표입니다. 당시로서는 Linux kernel에 꽤나 최근 feature였던 AIO(Asynchronous I/O)를 소개하고, 또 권장하는 글이었습니다.

오늘날을 사는 대개의 우리는 Block & Synchronous 케이스, 그리고 Non-block & Asynchronous 케이스는 너무 많이 접해봐서, 실무 이전에 이미 학습 단계에서부터도 전형적인 케이스로서 두 메서드를 서로 비교하면서까지 배워봐서 전혀 낯설지 않습니다만, 이게 또 Blocking이 곧 Synchronous와 같고 Non-blocking이 곧 Asynchronous와 같은 개념으로 잘못 이해할 수 있어 한 번쯤은 짚어보는 것도 의미 있으리라 판단했습니다.

우스갯소리이지만, 13년 전에는 무려 one of new standard features였던 AIO가 지금의 우리에겐 너무 익숙해져버렸고, 항상 쓰는 개념이 되어있어 오히려 반대로 기존의 다른 메서드는 알지도 못하고, 적용해본 적도 없는 경우도 더러 봤습니다. 이를 테면, 각 랭귀지마다 람다식이 표준으로 적용되던 때 신세계를 경험했던 저와는 달리 람다식이 아닌 표현으로는 함수를 구현도 못하는 세대라든지, jQuery는 들어본 적도 없지만 React는 해봤다든지 하는 식의 것들 말입니다. 물론, 이 경우에는 예가 조금 다르지만서도! 기술의 흐름을 바라보노라면, 그저 경이로울 따름입니다! 😝


문자 그대로 느껴보기

이런 저런 검색해보시면 좋은 글들이 참 많아서 깊이 있는 내용 그대로를 퍼나르는 식의 포스트로는 저자로서도, 그리고 독자분들에게도 의미가 없을 것 같아 제가 이해한 방식을 잠깐 소개드려볼까 합니다.

Blocking, Non-blocking, Synchronous, Asynchronous뿐 아니라 모든 개념들은 그들이 최초에 그 이름으로서 정의되던 순간, 즉 비정형적 사고가 언어라는 도구에 의해 정형화(framing)되는 그 순간, 그리고 여러 세대에 거쳐 불리우며 유지 또는 변모되어 온 시간 속에 매우 견고한 논리를 띠고 의미를 발한다고 생각합니다. 다시 말해서, Blocking의 개념 본질은 곧, Blocking이라는 단어의 의미 본질에서 찾아볼 수 있다는 것인데요.

저는 이런 식의 사고법을 때때로 즐기는 편인데, 예로, 우리가 아주 흔하게 사용하는 외래어 비즈니스(Business)의 국어사전 정의를 살펴보면 다음과 같은데요,

비즈니스
[같은 말] 사업(어떤 일을 일정한 목적과 계획을 가지고 짜임새 있게 지속적으로 경영함). ‘사업’으로 순화.

짜임새 있게 지속적으로 경영함. 바쁘다는 형용사인 Busy가 nounification suffix인 -ness를 통해 명사화된 단어인 Business. 바쁨. 순수한 바쁨 그 자체. 결국 짜임새 있게 지속적으로 경영하는 활동인 ‘사업’은 바쁘지 않을 수 없고, 바쁘지 않아선 안 되는 것이죠.


Blocking / Non-blocking

그런 의미에서 Blocking은 다음과 같습니다.

blocking

행위자가 취한 행위 자체가, 또는 그 행위로 인해 다른 무엇이 막혀버린, 제한된, 대기하는 상태.
대개의 경우에는 나 이외의 대상으로 하여금 내가 Block 당하겠지만(Blocked), 어찌 되었든 문자 자체로는 나라는 단일 개체 스스로의 상태를 나타냅니다.

  • 호출된 함수가 자신이 할 일을 모두 마칠 때까지 제어권을 계속 가지고서 호출한 함수에게 바로 돌려주지 않으면 Block
  • 호출된 함수가 자신이 할 일을 채 마치지 않았더라도 바로 제어권을 건네주어(return) 호출한 함수가 다른 일을 진행할 수 있도록 해주면 Non-block


Synchronous / Asynchronous

그럼 Synchronous는 어떨까요?

synchronized

동시에 발생하는 것들(always plural, can never be singular).
동시라는 것은 즉, 시(time)라는 단일계(system)에서 같이, 함께 무언가가 이루어지는 두 개 이상의 개체 혹은 이벤트를 의미한다고 볼 수 있겠습니다.

  • 호출된 함수의 수행 결과 및 종료를 호출한 함수가(호출된 함수뿐 아니라 호출한 함수도 함께) 신경 쓰면 Synchronous
  • 호출된 함수의 수행 결과 및 종료를 호출된 함수 혼자 직접 신경 쓰고 처리한다면(as a callback fn.) Asynchronous


Non-blocking & Synchronous

그래서 이런 로직을 생각해볼 수 있는 겁니다. 호출된 함수호출한 함수에게 제어권을 바로 건네주어(return) 호출한 함수가 다른 업무를 볼 수 있었음(Non-blocked)에도 불구하고 여전히 호출된 함수의 업무 결과에만 줄곧 함께(synchronously) 신경쓰느라 제 할 일을 못 하게 되는.. 이래서 신뢰를 바탕으로 권한과 책임을 지워줘야 합니다.

figure


본격 Case Study : 대표님, 개발자 좀 더 뽑아주세요..

Blocking & Synchronous

나 : 대표님, 개발자 좀 더 뽑아주세요..
대표님 : 오케이, 잠깐만 거기 계세요!
나 : …?!!
대표님 : (채용 공고 등록.. 지원자 연락.. 면접 진행.. 연봉 협상..)
나 : (과정 지켜봄.. 궁금함.. 어차피 내 일 하러는 못 가고 계속 서 있음)

Blocking & Asynchronous

나 : 대표님, 개발자 좀 더 뽑아주세요..
대표님 : 오케이, 잠깐만 거기 계세요!
나 : …?!!
대표님 : (채용 공고 등록.. 지원자 연락.. 면접 진행.. 연봉 협상..)
나 : (안 궁금함.. 지나가는 말로 여쭈었는데 붙잡혀버림.. 딴 생각.. 못 가고 계속 서 있음)

Non-blocking & Synchronous

나 : 대표님, 개발자 좀 더 뽑아주세요..
대표님 : 알겠습니다. 가서 볼 일 보세요.
나 : 넵!
대표님 : (채용 공고 등록.. 지원자 연락.. 면접 진행.. 연봉 협상..)
나 : 채용하셨나요?
대표님 : 아직요.
나 : 채용하셨나요?
대표님 : 아직요.
나 : 채용하셨나요?
대표님 : 아직요~!!!!!!

Non-blocking & Asynchronous

나 : 대표님, 개발자 좀 더 뽑아주세요..
대표님 : 알겠습니다. 가서 볼 일 보세요.
나 : 넵!
대표님 : (채용 공고 등록.. 지원자 연락.. 면접 진행.. 연봉 협상..)
나 : (열일중..)
대표님 : 한 분 모시기로 했습니다~!
나 : 😍


if (dev.isBored() || job.sucks()) {
    tryOut('https://musma.github.io/recruit', (err, result) => {
        if(err) console.error('This can never happen though')
        else figureOut(result)
    })
}


References

  • https://developer.ibm.com/articles/l-async/
  • https://tech.peoplefund.co.kr/2017/08/02/non-blocking-asynchronous-concurrency.html
  • https://homoefficio.github.io/2017/02/19/Blocking-NonBlocking-Synchronous-Asynchronous/