Study

동기와 비동기, 블로킹과 논블로킹의 차이점 및 조합 이해하기

kanado 2025. 2. 5. 17:01

오늘은 개발하다보면 자주 만나는 개념인 동기(Synchronous)와 비동기(Asynchronous), 그리고 블로킹(Blocking)과 논블로킹(Non-blocking)에 대해 깊이 있게 다뤄보려고 한다. 이 개념들은 API 호출이나 I/O 작업을 처리할 때 매우 중요하며, 각각의 특성을 이해하고 올바르게 활용하는 것이 시스템의 성능을 최적화하는 데 결정적인 역할을 하고 있다.

 

블로킹 (Blocking)

블로킹은 특정 작업의 완료를 기다리면서 다른 작업의 실행이 멈추는 상태를 의미한다. 즉, 어떤 작업을 시작하면 그 작업이 완료될 때까지 프로그램의 제어권이 해당 작업에 완전히 넘어가며, 다른 어떤 작업도 수행할 수 없다.

1. 순차적 실행을 보장

2. 동기적 API 호출 시 주로 사용

3. 실행 중인 작업 완료까지 다른 작업은 대기 상태

 

논블로킹 (Non-blocking)

논블로킹은 현재 실행 중인 작업을 완료하지 않고도 다음 작업을 계속해서 실행할 수 있는 방식이다. 작업 실행 시 제어권을 바로 돌려받아, 대기 시간 없이 여러 작업을 병렬로 처리할 수 있다. 이는 프로그램의 반응성과 처리 능력을 향상시킬 수 있다.

1. 비동기적 작업 처리 가능

2. 비동기적 API 호출 시 사용

3. 콜백 함수, 프로미스, async/await를 통한 구현

 

블로킹 vs 논블로킹

 

동기 (Synchronous)

동기 방식은 함수 호출 시 그 결과가 반환될 때까지 기다리는 처리 방식을 말한다. 이 방식에서는 실행 순서가 엄격하게 보장되며, 한 작업이 끝나야 다음 작업을 시작할 수 있다.

1. 실행 순서 보장

2. 동기적 API 호출을 통해 구현

 

비동기 (Asynchronous)

비동기 방식은 특정 함수를 실행하고, 그 결과를 기다리지 않고 바로 다른 작업을 수행할 수 있는 처리 방식이다. 이를 통해 시스템 자원의 사용을 최적화하고, 동시에 여러 작업을 진행할 수 있다.

1. 동시에 여러 작업 가능

2. 콜백 함수, 프로미스, async/await 사용

3 . 업 결과 처리가 필요한 경우, 이전 작업 완료 후 진행

 

동기 vs 비동기

 

 

블로킹 vs 논블로킹, 동기 vs 비동기의 관계

이 개념들은 각각 서로 다른 문제를 해결하고 있다.
블로킹/논블로킹은 작업이 다른 작업의 완료를 기다리는지의 여부를 다루며,
동기/비동기는 작업들 사이의 의존성과 실행 순서의 중요성을 다룬다.

 

1. 동기 / 블로킹 조합
작업 A가 작업 B를 호출할 때, A는 B의 실행이 끝날 때까지 자신의 실행을 멈추고 결과를 기다린다. 이 경우, B가 완료될 때까지 A는 다른 작업을 수행할 수 없다.
예: A가 B의 결과에 따라 다음 실행 코드가 달라진다.

 

 

2. 동기 / 논블로킹 조합
작업 A가 작업 B를 호출하고, B가 실행되는 동안 A는 일시 정지하지만, B를 호출하기 전에 독립적으로 다른 작업을 수행할 수 있다. B의 결과가 준비되면, A는 다시 그 결과에 따라 실행을 계속한다.
예: A는 B의 결과를 기다리며, 그 결과에 따라 다음 코드가 바뀐다.

3.비동기 / 블로킹 조합

이 조합은 특이한 경우로, 작업 A가 작업 B를 비동기적으로 호출하더라도 B의 결과를 기다리는 동안 A는 다른 작업을 수행할 수 없다. 실제로 이는 '동기 / 블로킹'과 유사한 상황을 만들어, 사용되지 않는 조합이다.

4. 비동기 / 논블로킹

작업 A가 작업 B를 호출하면, A는 B의 결과를 기다리지 않고 계속해서 다른 코드를 실행한다. B의 실행 결과가 준비되면, 그 때 A는 이 결과를 받아 처리합니다.
예: A는 B의 결과와 관계없이 자신의 작업을 계속 진행하며, B의 결과를 나중에 처리한다.

 

비동기 I/O와 논블로킹 I/O는 의 차이

  1. 논블로킹 I/O
    논블로킹 I/O는 요청을 할 때 데이터가 바로 사용 가능한지 즉시 확인하고, 데이터가 준비되지 않았다면 바로 제어를 반환한다. 이후에 다시 데이터가 준비되었는지 확인하기 위해 여러 번 시도할 수 있다. 왜냐하면 요청이 별도로 작업을 실행하고 있기 때문이다. 즉, 논블로킹 I/O는 I/O 작업이 완료될 때까지 기다리지 않고 바로 다른 작업을 하다가 중간 중간에 요청이 완료될 때까지 계속해서 상태를 확인하는 방식이다. 이를 '폴링'이라고 한다.
  2. 비동기 I/O
    비동기 I/O는 작업을 요청한 후, 그 작업이 완료될 때까지 기다리지 않고 즉시 제어를 반환한다. 작업의 완료 여부는 콜백 함수나 이벤트, 프로미스 등을 통해 비동기적으로 알려준다. 이 방식에서는 요청을 한 후에도 그 완료를 기다리지 않고 다른 작업을 병렬로 처리할 수 있습니다. 이를 '이벤트 드리븐' 방식이라고 한다.
    → 자연스럽게 논블로킹의 특성을 가진다.



멀티 스레드 환경에서 블로킹 I/O를 사용할때 발생하는 컨텍스트 스위칭 오버헤드를 줄이기 위한 방법

컨텍스트 스위칭은 CPU가 하나의 스레드에서 다른 스레드로 작업을 전환할 때 발생하는 비용을 말하며, 스레드가 많거나 I/O 작업이 빈번히 발생할 경우 성능 저하의 주요 원인이 될 수 있다.

  1. 스레드 풀 사용 스레드를 미리 생성하고 풀에 보관해두면 필요할 때마다 즉시 사용할 수 있다. 이는 스레드 생성과 소멸에 따른 오버헤드를 줄일수 있다.
  2. 적절한 스레드 수 관리 스레드의 수를 시스템의 코어 수에 맞게 조절하면 각 코어가 지속적으로 작업을 처리할 수 있으며, 스레드 간 전환 비용을 줄일 수 있다.



웹 서버 아키텍처에서 논블로킹 방식이 주는 성능적 이점

  1. 일반적으로 하나의 스레드는 한 번에 한 작업만 수행할 수 있다. but 비동기 I/O 모델을 활용하면 하나의 스레드가 여러 I/O 작업을 동시에 처리하는 것처럼 보이게 할 수 있다. → 비동기 I/O 모델에서는 하나의 스레드가 I/O 작업을 직접 수행하지 않고, I/O 멀티플렉싱이나 커널이나 이벤트 루프를 통해 I/O 작업을 처리하는 방식을 사용한다. 즉, 스레드는 I/O 요청을 보낸 후 해당 작업이 끝날 때까지 기다리지 않고 다른 작업을 수행할 수 있다.
    결론: 논블로킹 아키텍처는 동시에 많은 연결을 처리할 수 있다. 하나의 스레드가 여러 I/O 작업을 비동기적으로 처리할 수 있기 때문에, 수천에서 수만 개의 동시 연결을 관리하는 것이 가능하다. → 많은 사용자 동시접속 시 발생할 수 있는 부하를 분산 가능
  2. 각 요청을 처리하는 데 필요한 스레드 수가 적어서, CPU 사용률과 메모리 사용률을 낮출 수 있다.
  3. 요청이 블록되지 않고 빠르게 처리될 수 있기 때문에 전반적인 시스템의 응답 시간이 개선된다.

 

 

끝.