
를 알아두면 좋다.
요청을 하면 시간이 얼마나 걸리던지 요청한 바로 그 자리에서 결과가 주어져야 한다.
순서에 맞춰 진행된다는 장점이 있지만, 여러가지 요청을 동시에 처리할 수 없다.
위 그림의 (a)처럼 커피 주문을 받고 나올 때까지 기다리는 것이 동기 방식의 대표적인 예시다.
하나의 요청에 따른 응답을 즉시 처리하지 않고, 그 대기 시간동안 또 다른 요청에 대해 처리 가능한 방식이다.
여러 개의 요청을 동시에 처리할 수 있는 장점이 있지만 동기 방식보다 속도가 떨어질 수도 있다.
위 그림의 (b)처럼 점원 한 명이 커피 주문을 받고 다른 점원이 커피를 건네주는 것이 비동기 방식의 예시다.
우리는 일상에 생각보다 많이 동기/비동기적으로 살아가고 있다.
카페, 식당이 비동기 처리의 대표적인 예시다.
동기 처리는 편의점 계산이라고 보면 된다.
내가 결제할 물품을 계산대에 올려 계산하기까지 그 결과를 기다리기 때문이다.
정답은 없다.

'계좌이체'같은 작업은 동기방식으로 처리해야 A에서 보냈는데 B에서 못 받는 상황이 없을 것이다.
반대로 비동기 방식은 위의 예제처럼 노드 사이의 작업 처리 단위를 동시에 맞추지 않아도 된다.
비동기 방식의 예(시험날의 학생과 선생)

학생은 시험지를 푸는 역할을 하고 선생은 시험지를 채점하는 역할을 한다.
서로의 행위(목적)가 다르기 때문에 둘의 작업 처리 시간은 일치하지 않고, 일치하지 않아도 된다.
동기와 비동기는 어떤 작업 혹은 그와 연관된 작업을 처리하고자 하는 시각의 차이이다.
동기는 추구하는 같은 행위(목적)가 동시에 이루어지며,
비동기는 추구하는 행위(목적)가 다를 수도 있고, 동시에 이루어지지도 않는다.
비동기 방식 예제를 통해 블록과 논 블록의 차이를 간략하게 설명하면,
학생이 시험지를 선생에게 건넨 후 가만히 앉아 채점이 끝나 시험지를 돌려받기만을 기다린다면 학생은 블록 상태이다.
하지만 학생이 시험지를 건넨 후 선생에게 채점이 완료되었다는 전송을 받기 전까지 다른 과목을 공부한다거나 게임을 한다거나 다른 일을 하게 되면 학생의 상태는 논 블록 상태이다.
| | 블로킹 | 논블로킹 |
|----------------|---------------------------------------------|----------------------------------------------------|
| 쓰레드 상태 | 대기(Idle) | 다른 작업 수행 가능 |
| 구현 난이도 | 낮음 | 중~상(콜백/스트림/리액티브 패러다임) |
| 적합한 상황 | 짧고 확정적 I/O, 간단한 동기식 트랜잭션 | 고동시성 I/O, 외부 호출이 잦고 지연이 가변적일 때 |
주의: “동기=블로킹, 비동기=논블로킹”이 항상 성립하는 건 아니다.
sequenceDiagram
participant Client
participant API
participant DB
Client->>API: POST /transfer {from,to,amount}
API->>DB: in Tx: debit(from), credit(to)
DB-->>API: commit OK
API-->>Client: 200 OK (result)
sequenceDiagram
participant Client
participant API
participant Queue
participant Worker
participant Webhook
Client->>API: POST /orders
API->>Queue: publish(orderCreated)
API-->>Client: 202 Accepted (trackingId)
Worker->>Queue: consume(orderCreated)
Worker->>Webhook: POST /notify (trackingId, status=Done)
Note over Client: 폴링(/status) 또는 웹훅으로 상태 갱신
Client → API 요청
API → Queue로 메시지 발행
202 Accepted 응답을 반환. Worker가 Queue를 소비(Consume)
Webhook(또는 Polling)
callbackUrl로 결과를 전송하거나,/status/{trackingId}를 주기적으로 조회(polling)함.Client가 결과 수신 및 표시
"비동기 통신 구조에서 응답을 나중에 받는 패턴"을 설명한 거.
즉, “요청은 바로 끝나지만 실제 처리는 나중에 백그라운드에서 진행되는 구조”
이 구조는 요청자가 즉시 응답(“요청을 받았다”)만 받고,
실제 작업은 백엔드의 큐나 워커(Worker)가 나중에 비동기로 처리하는 방식이다.
즉,
요청자(Client)는 “결과를 지금 바로 받지 않아도 된다.”
대신, “작업이 끝나면 나중에 알려줘” 하는 패턴이지.
| 구분 | 동기식 요청-응답 | 비동기식 요청-응답(콜백/웹훅) |
|---|---|---|
| 처리 방식 | API가 모든 작업을 끝내고 응답 | 요청만 받고 작업은 나중에 |
| 응답 시점 | 작업이 완료된 뒤 | 작업을 큐에 넣은 즉시(“Received”) |
| 응답 내용 | 최종 결과 | 처리 중임(Tracking ID 등) |
| 확장성 | 낮음 (요청 지속 유지) | 높음 (비동기 큐로 부하 완화) |
| 예시 | 계좌이체 승인, 로그인 등 | 이메일 전송, 이미지 변환, 결제 정산 등 |
이게 비동기 + 콜백 알림(Webhook) 구조와 완전히 동일한 형태야.
| 구분 | 동기 | 비동기 |
|---|---|---|
| 사용자 피드백 | 즉시 결과, UX 명확 | 즉시 완료가 아닐 수 있음(상태 조회/알림 필요) |
| 복잡도 | 낮음 | 큐/워커/상태관리/멱등성 등 설계 복잡 |
| 확장성/자원 효율 | 쓰레드 영걸림으로 한계 | 고동시성/자원 효율 우수 |
| 일관성 | 강한 일관성 범위 한정 쉬움 | 보통 최종 일관성(eventual) |
| 실패 처리 | 호출부에서 즉시 식별 | 재시도/보상/모니터링 체계 필수 |
// Spring 6: RestClient (블로킹)
RestClient client = RestClient.create("https://pay.example.com");
PaymentResponse res = client.post()
.uri("/approve")
.body(request)
.retrieve()
.body(PaymentResponse.class); // 완료까지 현재 쓰레드 대기
// 논블로킹: 결과는 Mono로 비동기 전달
WebClient webClient = WebClient.create("https://pay.example.com");
Mono<PaymentResponse> mono = webClient.post()
.uri("/approve")
.bodyValue(request)
.retrieve()
.bodyToMono(PaymentResponse.class);
// 체이닝/조합 가능 (subscribe 시점에 실행)
mono.timeout(Duration.ofSeconds(3))
.doOnError(e -> log.warn("timeout/retry"))
.retryWhen(Retry.backoff(3, Duration.ofMillis(200)));
// 생산자
kafkaTemplate.send("order.created", orderId, payload);
// 소비자(멱등 처리)
@KafkaListener(topics = "order.created")
public void handle(String key, OrderCreated evt) {
if (processedRepo.exists(evt.id())) return; // 멱등
// 비즈 처리...
processedRepo.save(evt.id());
}