Blocking Non-Blocking, Sync ASync는 무엇이고 어떤 차이를 가지고 있을까?
동기와 비동기 방식의 차이는 처리결과에 대한 책임을 호출한 스레드가 가지고 있냐(동기) 아니면 호출된 스레드에 넘기냐(비동기)로 표현할 수 있다.
그림을 보면 sync/blocking 은리턴되고 async/blocking은 콜백으로 호출된다.
Blocking / Non-blocking
블록킹과 넌블럭킹은 순차처리를 보장여부로 구분할 수 있다.
- 블럭킹: 호출된 함수가 작업을 모두 마칠 때까지 제어권을 계속 가지고서 호출한 함수는 대기하고 있다. (순차처리 보장)
- 논블럭킹: 호출된 함수가 자신이 할 일을 채 마치지 않았더라도 바로 제어권을 리턴하고, 콜백을 할 때까지 호출한 함수가 다른 일을 수행할 수 있다. (순차처리 미보장)
- 제어권 : os 스케줄러에 의한 스레드의 상태 맥락(cpu를 할당받아서 실행가능한 상태인가)
블럭킹은 흐름 관점에서 다른 작업이 끝날때 까지 기다리는 것이다.
논블럭킹은 흐름 관점에서 다른 작업이 끝날때 까지 기다리지 않는것을 말합니다.
Synchronous / Asynchronous
동시에 발생하는 것들(always plural, can never be singular).
동시라는 것은 즉, 시(time)라는 단일계(system)에서 같이, 함께 무언가가 이루어지는 두 개 이상의 개체 혹은 이벤트를 의미한다고 볼 수 있겠습니다.
- 호출된 함수의 수행 결과 및 종료를 호출한 함수가(호출된 함수뿐 아니라 호출한 함수도 함께) 신경쓰면 Synchronous
- 호출된 함수의 수행 결과 및 종료를 호출된 함수 혼자 직접 신경쓰고 처리한다면 (as a callback fn.) Asynchronous
비동기랑 논블럭킹의 차이는?
비동기는 코드 실행 관점에서 처리결과에 대한 책임을 넘겨주는 것이고 논블럭킹은 흐름 관점에서 다른 작업이 끝날때 까지 기다리지 않는것을 말합니다.
IO 작업이 발생하면 CPU 를 주어도 당장 instruction 을 수행할 수 없는 상태가 된다.
그 시간 동안 다른 맥락의 코드를 실행하게 하는 것이 비동기 처리의 목적이다.
동기 + 블로킹
즉 sync/blocking 은 제어권을 넘겨주지 않고 호출한 함수가 계속 제어권을 들고 있는 것이다.
(블로킹) 새로운 작업을 요청하게 되면 해당 작업이 종료될 때까지(결과를 리턴할 때까지) 기다림
(동기) 결과를 반환하면 해당 결과에 대한 작업을 바로 처리 (처리 결과에 대한 책임을 호출한 함수가 가지고 있음)
즉 동기는 무조건 순서대로 처리한다. 호출 순서대로 처리가 보장된다.
- 예시
자바의 scanner, 파일 등의 I/O 작업
동기 함수에서 다른 동기 함수 호출
동기 + 논블로킹
sync/non-blocking 은 제어권을 넘겨주지 않고 호출한 함수가 계속 제어권을 들고 있는 것이다.
즉 A 함수가 계속해서 결과를 체크하고 있으니까 완료, 진행, 실패를 무조건 알 수 있다.
(논블로킹) 새로운 작업이 종료될 때까지 기다리지 않으나 주기적으로 작업이 완료되었는지 확인
(동기) 결과를 반환하면 해당 결과에 대한 작업을 바로 처리
즉 동기는 무조건 순서대로 처리한다.
ex) 대표적인 예시로는 스핀락이 있다.
무한 루프 안에서 락 획득이 true 가 나올 때까지 계속 시도한다.
락 획득 - 어콰이어 콜 - 거의 바로 false로 반환되고 또다시 호출 - false 반환 이런 식으로 돈다.
정보를 가지고 올 때까지 프로그래스바 표출
비동기 + 블로킹
aync/blocking 은 즉 비동기 호출을 하는 순간 코드 제어권을 다른 스레드에게 넘겨주고 다른 스레드가 돌다가 명시적으로 콜백 호출을 통해서 다시 파란색 스레드로 제어권을 넘겨준다.
(블록킹) 새로운 작업을 요청하게 되면 해당 작업이 종료될 때까지 (결과를 리턴할 때까지) 기다림
(비동기) 결과에 대한 작업을 호출한 작업에서 처리하지 않고 별도의 스레드나 콜백 함수를 통해 처리
- 예시
I/O 멀티플렉싱(select, poll)
Node.js + MySQL(쿼리 자체는 비동기로 동작하지만 DB에 접근할 때 드라이버를 호출하는 과정은 동기 방식으로 동작)
비동기 + 논블로킹
async/non-blocking 은 제어권을 호출된 함수에게 주었다.
호출된 함수가 콜백 콜 을 안 해주면 호출한 스레드는 진행상황을 알 수 없다.
즉 제어권이 완전히 넘어간 것이다.
(논블로킹) 새로운 작업이 종료될 때까지 기다리지 않으나 주기적으로 작업이 완료되었는지 확인
(비동기) 결과에 대학 작업을 호출한 작업에서 처리하지 않고 별도의 스레드나 콜백함수를 통해 처리
- 예시
자바스크립트 API 요청(ajax, fetch)
async 방식의 파일 I/O
비동기랑 논블럭킹의 차이는?
비동기는 코드 실행 관점에서 처리결과에 대한 책임을 넘겨주는 것이고 논블럭킹은 흐름 관점에서 다른 작업이 끝날때 까지 기다리지 않는것을 말합니다.
비동기 방식은 무조건 좋은가요?
비동기 방식이 항상 좋은 건 아닙니다.
비동기(Asynchronous)란, 요청한 작업의 결과를 기다리지 않고, 작업이 완료된 후에 콜백이나 이벤트로 처리하는 방식입니다.
이를 통해 시스템은 응답을 기다리는 동안 다른 작업을 먼저 수행할 수 있어서 자원을 효율적으로 사용할 수 있는 장점이 있습니다.특히 I/O 작업이 많은 시스템에서는 non-blocking I/O와 함께 사용되면 성능 향상에 효과적입니다. 예를 들어, Spring WebFlux나 Netty 같은 경우입니다.
하지만 무조건 비동기 방식이 유리하진 않습니다.
- 첫째, 비동기 코드는 흐름이 복잡해지고 디버깅이 어려워지며,
- 둘째, 예외 처리나 트랜잭션 관리가 까다롭고,
- 셋째, 결과 순서나 동기적 처리가 중요한 비즈니스 로직에서는 오히려 문제를 유발할 수 있습니다.
따라서 저는 비동기 방식은 성능이 중요한 I/O 중심 애플리케이션에 적절하며,
작업의 특성과 복잡도를 고려해 선택하는 것이 더 중요하다고 생각합니다.
비동기와 동기, 언제 사용하는 게 적절한가요?
동기는 작업이 가볍고, 순차성이 중요한 경우
외부 I/O가 있을수록 비동기가 더 유리합니다. 외부 I/O 는 속도가 느리고 대기 시간이 큼
-> 그 동안 스레드가 멍 때리고 대기만 하고 있는 blocking 상태가 됨.
이럴때는 비동기 + Non-Blocking 을 사용하면 CPU 가 낭비되지 않음.
그런데 외부 I/O 안 탈 때는?
cpu 작업만 있는 경우에 비동기가 꼭 이득이 되는건 아님.
스레드를 비동기로 여러 개 돌리면 컨텍스트 스위칭 오버헤드 발생
트기 작업이 가볍고 순차성이 중요한 경우엔 오히려 동기가 더 좋음.
동기(Synchronous)는 작업 순서가 중요하거나, 이전 작업의 결과가 다음 작업에 꼭 필요할 때 적합합니다.
ex1) 로그인 후 사용자 정보를 가져와야 하는 경우, 인증이 끝나기 전에는 다음 작업을 할 수 없기 때문에 동기 방식이 더 안정적이고 직관적입니다.
ex2) API 에서 pg 사로 결제 요청을 한 경우 pg 사에서 정상적으로 결제처리가 완료되었다는 응답을 받고 추가 작업을 진행하는 경우.
반면에 비동기(Asynchronous)는 처리량이 많거나, 외부 시스템과 통신하는 작업처럼 시간이 오래 걸릴 수 있는 경우에 효과적입니다. 예를 들어 외부 API 호출, 파일 업로드, 알림 전송 같은 작업은 비동기로 처리하면 주 흐름을 방해하지 않으면서 사용자 경험을 높일 수 있습니다.
또, 비동기는 자원을 효율적으로 사용할 수 있어서, 대규모 트래픽을 처리해야 하는 상황에서 시스템의 성능과 확장성 측면에서도 장점이 있습니다.
하지만 무조건 비동기가 좋은 건 아니고, 흐름이 복잡해지고 디버깅이 어려워질 수 있기 때문에, 시스템의 목적과 처리 패턴을 잘 고려해서 사용하는 게 중요하다고 생각합니다.
참고 자료:
https://guiyomi.tistory.com/108
https://deveric.tistory.com/99
https://musma.github.io/2019/04/17/blocking-and-synchronous.html
'CS' 카테고리의 다른 글
컴파일러와 인터프리터의 차이 (0) | 2024.11.22 |
---|---|
Tree 자료구조 (0) | 2024.11.22 |