BackEnd

Sync / Async / Blocking / Non-Blocking 정리

Raconer 2025. 8. 5. 15:05
728x90

네트워크 I/O, 동시성 프로그래밍을 공부하다 보면 자주 등장하는 개념이 바로 동기(Synchronous), 비동기(Asynchronous), 블로킹(Blocking), 논블로킹(Non-Blocking) 입니다.

처음 접하면 혼동하기 쉬운데, 사실 이들은 서로 다른 기준의 개념입니다.


1️⃣ 개념 정리

 

구분 
의미  특징
Synchronous (동기) 요청 후 응답까지 기다림 함수 호출이 끝나야 다음 코드 실행
Asynchronous (비동기) 요청 후 바로 다음 코드 실행 응답은 콜백, 이벤트, Future/Promise 등으로 나중에 처리
Blocking (블로킹) 스레드가 멈춤 작업이 완료될 때까지 해당 스레드는 대기
Non-Blocking (논블로킹) 스레드가 멈추지 않음 요청 후 바로 반환, 스레드는 다른 작업 수행 가능

즉,

  • Sync vs Async결과를 기다리는 방식
  • Blocking vs Non-Blocking스레드가 멈추는지 여부

두 가지는 별개의 축이라, 다음과 같이 조합될 수 있습니다.


2️⃣ 조합별 특징

유형 특징 예시

동기 + 블로킹 결과가 나올 때까지 스레드 대기 InputStream.read()
동기 + 논블로킹 즉시 반환, 직접 상태를 계속 확인(폴링) SocketChannel.read() 반복 호출
비동기 + 블로킹 거의 사용 X (비효율적) 비동기 호출 후 get()으로 대기
비동기 + 논블로킹 가장 효율적, 콜백/이벤트 기반 CompletableFuture, JS fetch

3️⃣ 동작 흐름도

아래 그림은 각 방식의 흐름을 직관적으로 보여줍니다.

  • Sync + Blocking : 요청 → 작업 → 대기 → 응답
  • Sync + Non-Blocking : 요청 → 작업 → 다른 작업 수행 → 응답
  • Async + Blocking : 요청 → 작업 → 대기 → 응답(비효율적)
  • Async + Non-Blocking : 요청 → 작업 → 다른 작업 수행 → 이벤트 발생 시 응답

4️⃣ 실무에서의 주의점

  1. Blocking은 스레드 수와 직결
    • I/O 작업이 많으면 스레드가 쉽게 고갈됨
  2. Non-Blocking이라고 무조건 성능이 좋은 건 아님
    • 상태 확인(Polling)만 계속하면 CPU 낭비 가능
  3. Async는 콜백 지옥 문제 발생 가능
    • Kotlin Coroutine, Reactor, RxJava 등으로 플로우 제어 권장
  4. CPU 바운드 작업에는 스레드풀 활용
    • 비동기는 I/O 중심일 때 가장 효과적
728x90