Foundry
운영체제
중급
핵심

동기와 비동기, 블로킹과 논블로킹

섞어서 헷갈리는 두 축을 분리해서 본다

두 축은 서로 다른 것을 묻습니다. 블로킹과 논블로킹은 제어권을 바로 돌려주는지, 동기와 비동기는 완료 통보를 누가 챙기는지입니다. 이 둘을 하나로 묶어 외우면 네 조합 중 두 개를 설명할 수 없게 됩니다.

두 축

묻는 것
블로킹 / 논블로킹호출한 함수가 제어권을 바로 돌려주는가
동기 / 비동기작업이 끝났는지를 호출한 쪽이 확인하는가, 통보를 받는가

네 조합

조합동작
블로킹 + 동기끝날 때까지 멈춰 서서 기다린다일반 파일 읽기
논블로킹 + 동기제어권은 바로 받고, 됐냐고 계속 물어본다반복 폴링
블로킹 + 비동기멈춰 서지만 여러 작업을 한 번에 지켜본다다중 입출력 감시
논블로킹 + 비동기맡기고 진행하다 끝나면 통보를 받는다콜백, 이벤트 알림

논블로킹인데 동기인 조합이 자주 빠집니다. 제어권을 바로 돌려받아도 완료 여부를 내가 계속 확인해야 하면 동기입니다. 제어권과 완료 통보는 별개입니다.

왜 백엔드에서 중요한가

요청 하나마다 스레드를 붙이고 블로킹으로 기다리면, 느린 외부 호출 하나가 스레드를 붙잡습니다. 스레드가 바닥나면 CPU 가 한가한데도 새 요청을 못 받습니다.

논블로킹과 비동기로 바꾸면 기다리는 동안 그 스레드가 다른 요청을 처리합니다. 적은 스레드로 많은 연결을 감당하는 구조가 여기서 나옵니다.

흔한 오해

비동기가 항상 빠른 것은 아닙니다. 작업 하나만 놓고 보면 걸리는 시간은 같습니다. 이득은 기다리는 동안 다른 일을 한다는 데서 오므로, 기다림이 없는 CPU 연산에는 효과가 없고 코드만 복잡해집니다.

면접에서 이렇게 나옵니다

Q.동기와 비동기, 블로킹과 논블로킹의 차이를 설명해주세요

두 축이 묻는 것이 다릅니다. 블로킹과 논블로킹은 제어권을 바로 돌려주는지이고, 동기와 비동기는 완료 통보를 누가 챙기는지입니다.

조합동작
블로킹 + 동기끝날 때까지 멈춰 서서 기다린다
논블로킹 + 동기제어권은 바로 받고, 됐냐고 계속 물어본다
블로킹 + 비동기멈춰 서지만 여러 작업을 한 번에 지켜본다
논블로킹 + 비동기맡기고 진행하다 끝나면 통보를 받는다

가장 자주 빠지는 것이 논블로킹이면서 동기인 조합입니다. 제어권을 바로 돌려받아도 완료 여부를 내가 계속 확인해야 하면 동기입니다.

흔한 실수: 두 축을 하나로 묶어 블로킹은 동기, 논블로킹은 비동기라고 답하는 것. 그러면 네 조합 중 두 개를 설명할 수 없습니다. 제어권과 완료 통보는 별개의 질문입니다.

Q.블로킹 방식이 서버 처리량에 어떤 영향을 주나요

느린 외부 호출 하나가 스레드를 붙잡아, CPU 가 한가한데도 새 요청을 못 받는 상태를 만듭니다.

요청마다 스레드를 붙이는 서버, 스레드 풀 200개
외부 결제 API 응답이 평소 50ms 에서 3초로 늘어났다

초당 100건 요청이면 동시에 300개 스레드가 필요해진다
풀 200개가 모두 대기 상태로 묶인다
CPU 사용률은 5퍼센트인데 새 요청은 큐에서 밀린다

병목이 계산 능력이 아니라 기다리는 자리의 수입니다. 스레드를 늘리는 것은 임시 방편이고, 컨텍스트 스위칭과 메모리 비용이 함께 늘어납니다.

논블로킹으로 바꾸면 기다리는 동안 그 스레드가 다른 요청을 처리하므로 적은 스레드로 많은 연결을 감당합니다.

흔한 실수: 스레드 풀을 키우면 해결된다고 답하는 것. 스레드마다 스택 메모리를 쓰고 스위칭 비용이 붙어, 어느 지점부터는 늘릴수록 느려집니다.

Q.비동기로 바꾸면 항상 빨라지나요

아닙니다. 작업 하나만 놓고 보면 걸리는 시간은 같습니다.

이득이 나오는 자리는 기다림이 있는 작업입니다. 네트워크 호출, 디스크 읽기, 데이터베이스 질의처럼 CPU 가 놀고 있는 구간이 있어야 그 시간에 다른 일을 시킬 수 있습니다.

작업 성격비동기 효과
외부 API 호출이 많다크다. 대기 시간에 다른 요청을 처리한다
이미지 변환처럼 CPU 를 쓴다없다. 쉬는 구간이 없다
순서대로 세 번 호출한다병렬로 바꾸면 크다. 그냥 비동기로만 바꾸면 작다

CPU 작업은 오히려 나빠질 수 있습니다. 이벤트 루프를 쓰는 구조에서 무거운 계산을 그대로 올리면 루프가 막혀 전체 요청이 함께 느려집니다.

흔한 실수: 비동기를 성능 개선 기법으로만 이해하는 것. 코드 흐름이 나뉘어 디버깅과 예외 처리가 어려워지는 비용이 있습니다. 기다림이 병목인지 먼저 확인하고 고르는 것이 순서입니다.

Q.적은 스레드로 많은 연결을 처리하는 구조는 어떻게 동작하나요

여러 연결을 한 자리에서 지켜보다가 준비된 것만 처리합니다. 연결마다 스레드를 두지 않습니다.

연결 10,000개를 감시 대상으로 등록한다
커널에게 "이 중에 읽을 준비가 된 것을 알려달라"고 맡긴다
준비된 것만 목록으로 돌아온다
그 연결들만 처리하고 다시 기다린다

스레드는 CPU 코어 수 정도만 있으면 되고, 대기는 커널이 대신합니다. 연결 수가 늘어도 스레드가 늘지 않는 것이 이 구조의 핵심입니다.

구조연결 1만 개일 때
연결마다 스레드스레드 1만 개. 메모리와 스위칭 비용이 감당되지 않는다
감시 후 준비된 것만 처리스레드 수 개. 대기는 커널이 맡는다

흔한 실수: 이 구조를 쓰면 무조건 빠르다고 답하는 것. 요청 하나의 처리 시간은 줄지 않고, 늘어나는 것은 동시에 감당하는 연결 수입니다. 그리고 처리 함수 안에서 블로킹 호출을 하나라도 하면 그 이득이 그대로 사라집니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

읽었으면 문제로 확인해보세요

운영체제 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.