동기/비동기 & 블로킹/논블록킹

동기/비동기

  • 요청한 작업에 대해 완료여부를 신경 써서 작업을 순차적으로 수행할지 여부에 대한 관점

  • 전체적인 작업에 대한 순차적인 흐름 유무

    • 처리해야 할 작업들을 어떠한 '흐름'으로 처리 할 것인가에 대한 관점

  • 리턴 값을 확인유무로 구분

블로킹/논블로킹

  • 현재 작업이 block되는지 여부에 따라 다른 작업을 수행할 수 있을지에 대한 관점

  • 전체적인 작업의 흐름 자체를 막는지에 대한 여부

    • 처리되어야 하는 (하나의) 작업이, 전체적인 작업 '흐름'을 막느냐 안막느냐에 대한 관점

  • 제어권의 주체를 넘기는지의 여부로 구분

동기(Synchronous) / 비동기(Asynchronous)

동기(Synchronous)

  • 개념

    • 작업 시간을 맞춰 함께 실행한다

    • 요청한 작업의 작업에 대해 완료 여부를 따져 순차대로 처리하는 것

    • 함수A에서 호출된 함수B의 작업 완료 후 리턴 값을 기다리거나, 완료가 되지 않고 리턴 받더라도 작업 관리 여부를 계속 확인

  • 작업 순서

    • 요청한 작업에 대해 순서가 지켜지는 것

비동기(Asynchronous)

  • 개념

    • 요청한 작업의 작업에 대해 완료 여부를 따지지 않고 자신의 다음 작업을 그대로 수행하는 것

      • 동시처리를 통한 시스템 전반적 성능향상

    • 함수 A에서 호출되는 함수 B의 작업 완료에 관계 여부, 리턴 여부를 신경 쓰지 않고 동작

  • 작업 순서

    • 요청한 작업에 대해 순서가 지켜지지 않을 수 있는 것

Blocking / Non-Blocking

다른 요청 작업을 처리하기 위해 현재 작업에 대한 block여부를 나타내는 프로세스 실행 방식

블로킹(Blocking)

개념

  • 자신의 작업을 진행하다가 다른 주체의 작업이 시작되면 다른 작업이 끝날때 까지 기다렸다가 자신의 작업을 실행하는 것

  • 호출된 함수(B)가 자신의 작업이 종료될 때까지 제어권을 갖고 있는 것

    • 호출된 함수(B)의 작업이 종료될 때까지 호출하는 함수(A)는 다른 작업을 진행할 수 없음

논블로킹(Non-Blocking)

개념

  • 다른 주체의 작업에 관련 없이 자신의 작업을 하는 것

  • 논블로킹은 호출된 함수(B)가 자신의 작업이 종료되지 않았더라도 함수의 제어권을 자신을 호출하는 함수(A)로 바로 넘겨주는 것

비동기와 논블로킹의 개념 차이

비동기와 논블로킹

비동기는 출력 순서와 관련된 개념이고, 논블로킹은 병령 실행과 관련된 개념이다.

비동기 논블로킹

  • 개념

    • 다른 작업의 결과를 기다리지 않고(비동기), 병렬적으로 실행되는 방식(논블로킹)

  • 구현 기술

    • 비동기 논블로킹 시, 다른 작업의 완료 여부나 결과에 대한 후처리를 위해 이용되는 방식

    • 콜백 함수

      • 비동기 작업이 완료되면 호출되는 함수의 의미로, 비동기 함수의 매개변수로 함수 객체를 넘기는 기법

      • 콜백 지옥 발생: 콜백 함수가 중첩되어 코드의 깊이가 깊어지는 현상 (코드가 복잡하고 가독성이 떨어지는 문제)

    • Promise 객체

      • 비동기 작업의 최종 완료 또는 실패를 나타내는 Array나 Object처럼 독자적인 객체

      • 비동기 작업이 끝날 때까지 결과를 기다리는 것이 아닌, 결과를 제공하겠다는 약속을 반환하는 의미

      • 콜백함수에서 개선된 비동기 논블로킹 처리 제공

JavaScript의 setTimeout를 '비동기 함수'라고 지칭하여 사용하는 것과 같이 비동기와 논블로킹을 혼동하는 경우가 많다. 하지만 비동기는 출력 순서와 관련된 개념이고 논블로킹이 병렬실행과 관련된 개념으로 혼동하지 말자.

제어권

  • 동기/비동기, 블로킹/논블로킹의 명확한 구분을 위해 나온 개념

  • 함수의 코드나 프로세스의 실행 흐름을 제어할 수 있는 권리

  • 블로킹과 논블로킹의 구분

    • 호출된 함수(collee)가 호출한 함수(coller)에게 제어권을 바로 주느냐 안주느냐로 구분

    • 제어권이 넘어가면 해당 스레드는 블로킹 됨

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

✔️ Sync Blocking (동기 + 블로킹)

개념

  • 다른 작업이 진행되는 동안 자신의 작업을 처리하지 않고 (Blocking), 다른 작업의 완료 여부를 바로 받아 순차적으로 처리하는 (Sync) 방식

    • 동기: 함수 A는 호출한 함수 B의 리턴 값을 필요로 함

    • 블로킹: 함수 A는 호출한 함수 B에게 제어권을 주고 함수 B에게 제어권을 돌려받을 때까지 실행을 멈추고 기다림

특징

  • 다른 작업의 결과가 자신의 작업에 영향을 주는 경우 활용

  • 코드가 순차적으로 실행 됨

  • 일반적으로 작업이 간단하거나 작업량이 적은 경우 사용

  • 코드가 순서대로 실행

    • A 실행 후 결과 값 반환 → B 실행 후 결과 값 반환 → C 실행 후 결과 값 반환

예시

  • 파일을 읽어 내용을 처리하는 로직

    • 파일을 먼저 읽어야 그다음 작업 처리 가능

  • C나 JAVA의 코드 실행 후 커맨드에서 입력을 받는 경우

    • 사용자로부터 입력 → 해당 입력값으로 내부 처리 → 결과값 콘솔 출력

    • 제어권을 시스템에서 사용자로 넘김

✔️ Async Non-Blocking (비동기 + 논블로킹)

개념

  • 다른 작업이 진행되는 동안에도 자신의 작업을 처리하고(Non Blocking), 다른 작업의 결과를 바로 처리하지 않아 작업 순서가 지켜지지 않는(Async)방식

    • 비동기: 함수 A는 호출한 함수 B의 리턴 값을 신경 쓰지 않으며, 함수 A와 함수 B는 서로 연관성이 없음

    • 논블로킹: 함수 A는 호출한 함수 B에게 제어권을 주지 않고 계속 실행

특징

  • 다른 작업의 결과가 자신의 작업에 영향을 주지 않는 경우 활용 가능

  • 작업량이 많거나 시간이 오래 걸리는 작업을 처리해야하는 경우 적합

예시

  • 웹 브라우저의 파일 다운로드

    • 웹 브라우저가 파일 다운로드를 비동기적으로 처리하고 콜백함수를 통해 다운로드 완료되면 알려주는 방식으로 구현

    • 웹 브라우저는 웹 사이트에서 파일 다운로드 시, 파일의 전송이 완료될 때까지 다른 작업을 기다리는 것이 아닌 다른 활동 가능(ex.웹서핑, 다른 창 열기)

✔️ Sync Non-Blocking (동기 + 논블로킹)

개념

  • 다른 작업이 진행되는 동안에도 자신의 작업을 처리하고(Non Blocking), 다른 작업의 결과를 바로 처리하여 작업을 순차대로 수행하는(Sync) 방식

    • 동기: 함수 A는 호출한 함수 B의 리턴 값을 중간중간 계속 확인

    • 논블로킹: 함수 A는 호출한 함수 B에게 제어권을 주지 않고 계속 실행

특징

  • 호출된 함수에서 작업을 완료하지 않았더라도 제어권을 바로 반납하여 다른 작업을 진행할 수 있도록 함

    • 호출한 함수(A)는 계속해서 호출된 함수(B)의 작업이 끝났는지 확인

    • (B 작업 미완료 시) 호출된 함수(B) 미완료 회신

      • 이 동안 호출한 함수(A)는 다른 작업 수행 가능

    • 호출된 함수(B)의 작업이 끝났는지 확인

    • (B 작업 완료 시) 호출된 함수(B) 결과 값 반환

  • 자바는 Sync Non-Blocking코드를 표현하기 적합한 언어

    • 스레드 객체를 만들어 요청 작업을 백그라운드에 돌게 함

    • 메인 메서드에서 while문을 통해 스레드가 모두 처리되었는지 끊임없이 확인하고 처리가 완료되면 다음 메인 작업 수행

  • Java 예시

    // Runnable 인터페이스를 구현하는 클래스 정의
    `class MyTask implements Runnable {
        @Override
        public void run() {
            // 비동기로 실행할 작업
            System.out.println("Hello from a thread!");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            // Thread 객체 생성
            Thread thread = new Thread(new MyTask());
    
            // 스레드 실행
            thread.start();
    
            // Non-Blocking이므로 다른 작업 계속 가능
            System.out.println("Main thread is running...");
    
            // Sync를 위해 스레드의 작업 완료 여부 확인
            while (thread.isAlive()) {
                System.out.println("Waiting for the thread to finish...");
            }
            System.out.println("Thread finished!");
            
            System.out.println("Run the next tasks");
        }
    }
    // 결과
    
    Main thread is running...
    Waiting for the thread to finish...
    Waiting for the thread to finish...
    Waiting for the thread to finish...
    Hello from a thread!
    Thread finished!
    Run the next tasks
    • 스레드를 이용해 작업을 병렬적으로 처리하도록 지시

    • Main코드의 while문의 수행으로 요청한 작업의 완료 여부를 계속 확인함

    • 결과적으로 동기 작업으로 작업이 순서대로 수행 됨

  • Javascript 경우 Sync Non-Blocking 코드를 구현하기에 지원하는 메서드에 한계가 있어 완벽히 표현할 수 없음

    • async/await키워드 이용

      • JavaScript에서 비동기 논블로킹 방식을 동기 논블로킹 방식으로 바꿔줌

      • 하지만 async/await는 내부적으로 여전히 비동기 논블로킹 방식으로 동작 함

예시

  • 게임에서 맵 이동 시

    • 맵 데이터 모두 다운(화면엔 로딩 스크린 뜸)

    • 로딩 스크린은 로딩바가 채워지는 프로그램이 수행하고 있는 것

      • 제어권은 여전히 사용자에게 있어 화면에 로드율이 표시되며 끊임없이 맵 데이터가 어느정도 로드 됐는지 조회

      • 자신의 작업을 계속하고 있지만 다른 작업과의 동기를 위해 계속해서 다른 작업이 끝났는지 조회

✔️ Async Blocking (비동기 + 블로킹)

개념

  • 다른 작업이 진행되는 동안 자신의 작업을 멈추고 기다리는(Blocking), 다른 작업의 결과를 바로 처리하지 않아 순서대로 작업을 수행하지 않는(Async)방식

    • 비동기: 함수 A는 호출한 함수 B의 리턴 값을 신경 쓰지 않음

    • 블로킹: 함수 A는 호출한 함수 B에게 제어권을 주고 함수 B에게 제어권을 돌려받을 때까지 실행을 멈추고 기다림

  • 호출된 함수(B)는 함수의 수행 결과를 콜백함수를 통해 전달, 하지만 호출된 함수(B)가 제어권을 가지고 있어 호출된 함수(B)의 작업이 완료되기 전까지 호출한 함수(A)는 다른 작업 진행 불가

특징

  • 거의 사용하지 않음

    • 실무에서 잘 마주하기 쉽지 않아 다룰일이 거의 없음

    • Sync Blocking과 성능 차이가 비슷해 사용하는 경우가 거의 없음

  • 개발자가 비동기 논블록킹으로 처리하려다가 실수하는 경우, 자신도 모르게 블로킹 작업을 실행하는 의도치 않은 경우 사용 됨

  • 따라서 해당 방식을 안티 패턴(anti-pattern)이라 치부하기도 함

예시

  • Node.js + MySQL의 조합

    • Node.js에서 비동기 방식으로 DB에 접근

    • MySQL DB에 접근하기 위한 MySQL드라이버는 블로킹 방식으로 작동 됨

    • JavaScript는 비동기 방식으로 MySQL에 쿼리를 보냄 (Async)

    • MySQL은 쿼리를 처리하면서 JavaScript에게 제어권을 넘겨주지 않음 (Blocking)

    • JavaScript는 다른 작업을 계속 수행할 수 있지만, MySQL의 결과값을 필요로 하기 때문에 MySQL이 쿼리를 완료할 때까지 기다려야 함

    • 결국 Sync Blocking과 작업 수행에 차이가 없음

위 조합은 개발자에게 혼동을 일으키므로 실무에서는 Node.js 서버 프로그래밍 시 async/await로 동기처리를 한다.

Ref

완벽히 이해하는 동기/비동기 & 블로킹/논블로킹 [컴퓨터 과학 - CS]동기와 비동기 / 블로킹 논블로킹 [network] 동기vs비동기, 블로킹vs논블로킹의 차이

Last updated