동기/비동기, 블로킹/논블로킹 개념을 자바 코드와 함께 헷갈리지 않게 정리했습니다.
동기(Synchronous) - 순서대로, 기다리면서
앞의 작업이 끝나야 다음 작업을 시작합니다. 호출한 쪽이 결과가 나올 때까지 멈춰서 기다립니다.
java
public void order() {
String result = paymentService.pay(); // 결제 끝날 때까지 여기서 멈춤
System.out.println(result); // 결제가 끝나야 이 줄이 실행됨
sendReceipt(); // 그 다음에야 영수증 전송
}
pay()가 3초 걸리면, order()는 그 3초 동안 아무것도 못 하고 결과만 기다립니다.
비동기(Asynchronous) - 기다리지 않고 다음 일로
호출만 해두고, 결과가 나오든 말든 바로 다음 작업으로 넘어갑니다. 결과는 나중에 콜백이나 별도 알림으로 받습니다.
java
public void order() {
paymentService.payAsync(result -> {
System.out.println(result); // 결제가 끝나면 나중에 이 콜백이 실행됨
});
sendNotification(); // 결제 끝나길 기다리지 않고 바로 실행됨
}
payAsync()를 호출한 직후 바로 sendNotification()이 실행됩니다. 결제 결과는 나중에 콜백으로 처리됩니다.
자바에서는 CompletableFuture로
java
CompletableFuture.supplyAsync(() -> paymentService.pay())
.thenAccept(result -> System.out.println(result)); // 결제 끝나면 실행
System.out.println("주문 접수됨"); // 결제 완료를 기다리지 않고 바로 출력
supplyAsync로 별도 스레드에서 결제를 처리하고, 메인 흐름은 결과를 기다리지 않고 다음 코드로 넘어갑니다.
헷갈리는 개념: 블로킹 vs 논블로킹
동기/비동기와 자주 같이 나오는 개념인데, 기준이 다릅니다.
- 블로킹/논블로킹: 호출한 함수가 제어권을 바로 돌려주는가, 아닌가에 대한 기준
- 동기/비동기: 결과를 호출한 쪽이 직접 기다리는가, 나중에 통보받는가에 대한 기준
블로킹 + 동기 : pay()를 호출하고 끝날 때까지 멈춰서 기다림 (가장 흔한 방식)
논블로킹 + 비동기: payAsync()를 호출하고 바로 다음 코드로, 결과는 콜백으로
실무에서는 이 두 개념이 거의 항상 짝을 이뤄서(블로킹+동기, 논블로킹+비동기) 쓰이기 때문에, 엄밀히 구분하기보다는 "동기=기다림, 비동기=안 기다리고 나중에 통보"로 이해해도 충분합니다.
마무리
동기는 "시킨 일이 끝날 때까지 기다렸다가 다음 일을 한다"는 방식이고, 비동기는 "시켜두고 바로 다음 일로 넘어간 뒤, 결과는 나중에 받는다"는 방식입니다. 응답을 오래 기다려야 하는 작업(외부 API 호출, 파일 처리 등)일수록 비동기로 처리하면 그 대기 시간 동안 다른 일을 할 수 있어서 전체 처리량이 늘어납니다.