티스토리 뷰

들어가는 말

동기(sync)와 비동기(async), 블로킹(blocking)과 논블로킹(non-blocking)

사전적인 의미를 학습과 암기에 의해 알고 있다.

그리고 매번(아니 매년) 다시 볼 때마다 뭘 잘못 이해했었는지, 이번에는 제대로 이해했다고 착각한다, 시간이 지나면 원상복귀다.
그렇다 모르는 거다.

 

변명이 길었다.

지금까지는?

처음 접한 건 웹 개발을 막 시작할 때쯤 ibm developerworks에 올라온 아티클에서 2 by 2 테이블과 해석본들이었다.

아쉽게도 원문은 이제 보이지 않지만, 사진이나 그림은 구글링 해보면 충분히 많이 나온다.

 

동기 sync: 작업이 끝날 때까지 기다리고 응답을 받음
비동기 async: 작업이 끝나면 따로 응답을 받음
블로킹 blocking: 함수가 완료되면 응답
논블로킹 nonblocking: 함수가 완료되지 않아도 응답

 

동기-비동기와 블로킹-논블로킹은 다른 맥락이다.

헷갈리는 이유 == 이해했다고 착각하는 이유

상당히 많은 것을 빼먹고 있다.

글마다 미묘하게 느낌 같은 느낌으로 정의가 다르다.

애당초 이해한 사항에서는 많은 것이 누락되어 있다.

정의들을 수집해보면 이해할 수 있을지도 모르겠다

 

지금까지는 이해했다고 넘어갔을 때 다음과 같은 질문에서는 혼란에 빠졌다.

어디서는 동기-비동기고 어디서는 블로킹-논블로킹인데?

왜 서블릿으로 구현하는(서블릿에서 호출하는) controller 메서드에 CompletableFuture를 달아놓고 논블로킹이라고 하거나 혹은 비동기라고 하는 건데

netty는 논블로킹 아니야? reactor는 비동기(reactive)이고? 왜 어디는 동기-비동기고 어디는 블로킹-논블로킹이라는 용어가 사용되는 건데?

reactor에서는 non-blocking io를 내세우면서 mono와 flux에서는 asynchronous를 내세우는데 대체 무슨 차이인 건가

 

다시 한번 정리해보자

동기-비동기 (synchronouse, asynchronous)

정의: 동기-비동기는 실행 결과에 누가 관심을 갖고 책임지느냐이다.  동기에서는 로직을 호출한 쪽이 결과에 관심이 있다.  비동기에서는 처리를 대행해 줄 일꾼에게 결과에 관심을 가지라고 위임한다.

동기방식에서는 멈춰서 기다리고 있던, 딴일 하다가 주기적으로 확인하던 호출 한쪽에서 계속 결과에 관심을 가지면 동기다

 

비동기는 로직을 호출한 쪽에서는 결과에 관심이 없다.

대신 나 대신 누군가 결과 좀 어떻게 해달라고 시킨다.

js에서의 callback, Promise, java에서의 Future, CompletableFuture, reactive 등등

 

아니다 뭔가 이상하다 Future는 분명 다른 것 같다.

Future는 명시적으로 get 메서드를 호출하여, Future를 생성한 쪽에서 결과에 관심을 갖는다.

 

그럼 정의가 틀린 건가? 다른 정의를 찾아보자

 

정의: 동기-비동기는 작업 흐름에 관한 이야기다. 현재 프로세스에서 작업을 실행시킨 후 그 작업이 끝날 때까지 다른걸 안 하고 기다리고 있으면 sync, 그렇지 않다면 async

블라인드에 달린 댓글이다.

지금까지 봤던 코드나 로직들을 기억하면 와 닿는 정의다.

async라는 성격으로 불리는 코드들은 이런 형태의 작업 흐름이었다.

java Future는 이 정의대로라면 다른 걸 하다가 다시 결과를 기다리는 거긴 하니까... 동기인지 비동기인지 잘 모르겠다.

ibm developerworks 정의의 흐름대로라면 CompletableFuture는 동기처럼 보이지만, Future는 비동기로 보인다.

그런데 Future도 async라고 한다 (www.baeldung.com/java-future)

 

또 다른 정의를 또 찾아보자

정의: 동기는 호출한 함수가 내가 원하는 값을 바로 반환, 비동기는 호출한 함수가 내가 원하는 값을 콜백으로 반환하거나, 특정한 객체로 래핑 하여 반환

블라인드에 달린 댓글이다.

지금까지 봤던 코드나 로직들을 기억하면 가장 와 닿는 정의다.

다만 sync, async라는 흐름의 뉘앙스를 가진 단어가 정의에 일치하는지 납득이 잘 안 간다.

 

정의: 동기는 함수를 호출할 때 결과를 얻을 때까지는 호출이 아무것도 반환되지 않는다. 비동기는 함수가 작업을 완료할 때까지 기다릴 필요가 없고 콜백 함수 또는 다른 알림 메서드를 사용하여 실행이 완료된 후 값을 가져오도록 notify 한다.

슬슬 지치고 레퍼런스만 늘어난다.

이건 대체 무슨 말인가. 원문을 잘못 이해한 것 같지는 않은데 블로킹-논블로킹 정의하고 일치하는 것처럼 보인다.

여럿 이들이 sync는 blocking 하고 다른 개념이라고 하지 않았는가?

아직 완벽하게 정리가 안 되었지만 blocking non-blocking으로 넘어가자 (넘어가는 이유가 있다.)

 

중간 정리

동기-비동기만 다시 정리하는데 산으로 간 느낌이다.

딱 떨어지는 정의가 없는 것처럼 느껴진다. 사람마다 말이 다르다.

병렬성-동시성 차례일지 블로킹-논블로킹 일지 시스템-애플리케이션 차원일지 io-multiplexing 일지 고민해보자

 

블로킹-논블로킹

정의:  호출되는 함수가 바로 리턴하느냐 마느냐

함수 기준으로 블로킹에서는 호출되는 함수가 완료될 때 값을 리턴한다.

논블로킹에서는 호출되는 함수가 완료되지 않더라도 값을 리턴하지 않는다.

이해하기 쉽다.

 

함수를 시스템 콜이라고 하며, 소켓으로 예를 들면

default 소켓의 함수(listen, connect, accept, recv, send read, write, recvfrom, sentto, close)들은 I/O가 완료될 때까지 응답을 주지 않는다. 프로세스/스레드는 그대로 멈춰있는다.

non-blocking(O_NONBLOCK) 소켓은 I/O가 즉시 처리가 불가능하더라도 시스템 콜이 바로 리턴된다. (결과가 EWOULDBLOCK/EAGAIN으로?) 프로세스/스레드는 다른 일을 할 수 있다.

이상한 느낌은 없다.

정의: 함수 호출 시 제어권 리턴 유무, A -> B 호출 시 B가 바로 제어권을 넘겨 A가 다른 일을 하게 한다면 논블로킹, B가 제어권을 작업을 끝날 때까지 돌려주지 않는다면 블로킹

동일한 정의고 리턴과 제어권이라는 표현의 차이만 있다.

같은 맥락이다.

정의: 블로킹은 cpu에게 제어권을 빼앗기는 것. 기본적으로 모든 연산은 블로킹, 논블로킹은 내 프로세스가 cpu에게 제어권을 빼앗기기는 하지만, 현재 프로세스가 종료당하지 않을 정도의 시간만 점유하는 것

블라인드 댓글이었다.

시스템 콜을 생각하면 이해가 간다.

블로킹 소켓은 I/O가 완료될 때까지 응답을 주지 않을 테고 그럼 프로세스는 멈춰있을 테니 cpu는 제어권을 빼앗아 갈 것이다.

그런데 논블로킹 소켓은 잘 이해가 안 간다.

이 정의를 이해하기에는 놓친(혹은 까먹고 있는...) 부분이 있는 것이다.

 

정의: 함수에 관한 이야기다. 함수를 기다리는 '외부적 요인'이 있을 때 (사용자의 입력이든, 아니면 무한루프를 돌면서 상태 변화를 기다리든) 그걸 기다리고 있으면 블로킹, 기다리지 않고 반환하면 논블로킹

블라인드 댓글이었다.

외부적 요인을 I/O 에 대입하면 명백하다

그런데 무한루프를 돌면서 상태 변화를 기다린다는 것은 무슨 의미인지 와 닿지가 않는다.

 

정의: 블로킹 시스템 콜을 할 경우 애플리케이션(스레드)은 suspended 상태로 빠지며 run queue에서 wait queue로 들어가고 완료되면 응답, 논블로킹 시스템 콜을 할 경우 들어가지 않으며 완료되지 않아도 빠르게 응답

슬라이드 셰어로 본 공룡 책 정의다.

개인적으로 받아들인 정답은 이 정의다.

 

직전에 제어권 관련 정의랑 일치한다.

왜 헷갈리는지 감이 왔다. 두 문맥은 크게 다르지 않았다.

 

sync async, blocking non-blocking을 자꾸 다른 맥락이라고 한정 짓다 보니 다른 개념이라고 생각했다.

일치하는 부분이 있었다.

 

물론 도메인/콘텍스트/레이어에 따라 다르게 표현된다.

일단 OS 레벨에서 시스템 콜에 대한 정의지만 베껴서 적어보자

  Synchronous Blocking Asynchronous Nonblocking
waiting for system call's completion O O    
immediate return     O O
return with data O O   O
waiting a watiting queue   O    

 

중간 정리

동기와 비동기, 블로킹과 논블로킹을 2 by 2 테이블로 나눠서만 생각해야 하며 분리된 개념이라는 게 오산이었다.

 

sync는 blocking와 관련이 있다.

다만 blocking 은 suspended 상태에 빠진다. (그것이 프로세스이던 스레드이던)

async는 non-blocking과 관련이 있다.

다만 async는 데이터를 리턴을 해주지 않아도 상관없다.

다만 sync 가 non-blocking과 연관되거나 async 가 blocking 이랑 연관되는 경우가 있다.

섞이는 상황으로 정리해보자

섞이는 상황

sync 이면서 non-blocking 은 future.isDone을 무한정 호출하는 같은 경우다.

중간중간 다른 일을 하면서 기다릴 수도 있겠지만 future를 생성한 쪽에서 결과가 나올 때까지 계속 반복해서 관심을 갖는다.

그렇게까지 나빠 보이지는 않는다.

 

async 이면서 blocking 은 sync 랑 동일하다.

이게 무슨 말인지 이해하는데 걸렸지만

node.js + mysql을 쓰는 경우, java에서 jdbc를 쓰는 경우라고 한다.

의도치 않게 async blocking 이 되어 버리는 경우라고 한다.

 

조금 근본적인 문제로 돌아가 보자

병렬성 (parallelism) vs 동시성 (concurrency)

병렬성은 여러 개의 워커가 각자 맡은 일들을 하나씩(정확한 표현일지는 모르겠다. 담당해서가 더 맞을 것 같다) 한다는 개념이다.

코어가 많은 서버에서 멀티스레드 기반의 서블릿으로 요청을 하나씩 담당하게 하는 것이 그 예라고 생각한다.

멀리서 보면 여러 일들이 동시에 이뤄지고 있는 것처럼 보이지만 가까이서 보면 하나의 일만 하고 있다.

단편적으로 말하자면 '여럿이 여러 일을 하고 있다'이다.

 

동시성은 워커가 고정된 워커 숫자 이상의 일을 한다는 개념이다.

이는 워커의 수가 하나일 때에도 성립한다.

(물론 콘텍스트 스위칭 비용은 발생할 수도 있지만) 큰 맥락에서 보면 여러 개 일을 동시에 하고 있는 것이다.

(싱글 스레드 이벤트 루프로 동작하는 node.js, redis는 이 맥락이지만, 아직 재고할 단계는 아닌 것 같다.)

 

동시성이 해결하고자 하는 문제는 우리네들 일하는 방식과도 비슷하다.

시간이 걸리는 자료 추출이나 배포 돌려놓고, 멈춰서 기다리지 않고, 개발하거나, 코드리뷰 챙기거나, CS 대응하거나, 메일 읽거나, 문서 작업하거나 성격이 다른 일들을 한다.

 

'멈춰서 기다리지 않고'가 핵심이다.

멈춰서 기다릴 이유가 없다. 블로킹되는 작업이 있으면 멍 때리며 기다리는 게 아니라 다른 작업을 하고 있으면 되고, '작업이 끝났다는 걸 알게 되면' 그때 다시 작업을 하면 되는 거다.

 

'작업이 끝났다는 걸 알게 되면' 은 여러 가지 형태가 있을 수 있다.

가끔 들어가서 확인하던지, 혹은 작업 완료 알람을 메신저로 통보받던지, 어째튼 '멈춰서 기다리지 않고'는 유효하다.

 

병렬성과 동시성은 다른 개념이고 섞일 수도 따로 적용될 수도 있으며, 해결하고자 하는 대상은 다르다.

궁극적으로 지향하는 바는 같다고 본다. 최대한의 퍼포먼스를 내는 것이라고 생각한다.

무슨 짓을 하던 어째튼 몰려드는 트래픽은 받아내야 할 것이 아닌가.

 

논블로킹, 비동기라는 개념이 필요하다.

효율성의 문제이다. 논블로킹, 비동기에서 해결하고자 하는 문제는 동시성이다.

병렬성 만으로는 이 문제를 해결할 수 없다.

스케일 아웃만으로는 한계가 있다. 코어가 많은 장비는 비싸다. (물론 메모리가 더 비싼 것 같기도 한데...)

비싼 리소스들이 멍 때리고 있는 걸 보고 있기에는 너무 아까우며, 서버가 많아질수록 관리하고 배포하는 게 매우 귀찮아진다.

 

나가는 말

그래도 한번 나만의 언어로 정리하니 개운하다.

다만 분량 조절 실패로 여기서 멈춰야겠다.

RL이슈로 WIP 로만 남겨놓기는 숙제가 남은 기분이다.

다음 글은 네트워크 프로그래밍, 서블릿이 될 것 같고 그 다음글에서 reactor로 가야할 것 같다.

 

 

 

레퍼런스

 

 

 

'개발관련 > 이론' 카테고리의 다른 글

클린 아키텍처의 추천사  (0) 2021.05.15
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함