콘텐츠로 이동

동기 VS 비동기

  • 동기(Synchronous): 요청한 쪽이 결과를 직접 받아야 다음 흐름으로 진행한다.
  • 비동기(Asynchronous): 요청만 하고, 작업 완료 통지는 콜백/이벤트 등으로 전달된다.
  • 블로킹(Blocking): 작업이 끝날 때까지 현재 스레드가 멈춰 있다.
  • 논블로킹(Non-Blocking): 작업이 끝나지 않았더라도 즉시 제어권을 돌려받는다.

동기/비동기는 결과를 누가 확인하는가, 블로킹/논블로킹은 제어권이 어디에 있는가의 문제다. 두 개념은 독립적이므로 4가지 조합이 가능하다.

코드 예시

동기 + 블로킹

// 결과가 올 때까지 현재 스레드가 대기
String result = httpClient.get("https://api.example.com/data");
System.out.println(result); // result가 와야 실행됨

비동기 + 논블로킹

// 요청만 하고 즉시 다음 라인 실행
CompletableFuture<String> future =
    httpClient.getAsync("https://api.example.com/data");
future.thenAccept(result -> System.out.println(result));
System.out.println("요청 후 바로 실행됨"); // 먼저 출력됨

4가지 조합

상태 상황 특징
동기 + 블로킹 카운터 앞에서 주문 후 음식 나올 때까지 그 자리에서 대기 결과를 직접 기다림, 대기 중 아무것도 못 함
동기 + 논블로킹 주문 후 창구를 반복해서 힐끔힐끔 확인 결과는 내가 직접 확인, 대기 중 움직일 수는 있음
비동기 + 블로킹 진동벨을 받았지만 테이블에서 아무것도 안 하고 대기 결과는 알림으로 받음, 스스로 행동은 멈춤
비동기 + 논블로킹 진동벨 받고 자리에서 다른 일 하다가 벨 울리면 수령 결과는 알림, 대기 중 자유

장점 / 단점

구분 장점 단점
동기 흐름이 직관적, 디버깅 쉬움, 에러 처리 간단 I/O 대기 중 스레드 낭비
비동기 I/O 대기 중 다른 작업 처리 가능, 처리량 향상 코드 복잡도 증가, 에러 처리 어려움

언제 쓰는지

방식 적합한 상황
동기 순서가 중요한 비즈니스 로직, 트랜잭션 처리, 응답을 즉시 사용해야 하는 경우
비동기 이메일 발송, 파일 업로드, 외부 API 호출 등 응답 대기가 긴 작업

주의할 점

  • 비동기 코드는 예외 처리를 별도로 해야 한다. CompletableFuture는 예외가 콜백 체인을 타고 흘러 놓치기 쉽다.
  • 비동기 논블로킹이 항상 빠른 것은 아니다. 단순 계산 작업은 오히려 동기가 더 빠를 수 있다.
  • Spring에서 @Async를 사용할 때 같은 클래스 내부 호출은 프록시를 통하지 않아 비동기로 동작하지 않는다.