본문 바로가기

정보

동시성 프로그래밍에서 동기(Synchronous)와 비동기(Asynchronous)의 차이점은 무엇인가요?

동기와 비동기는 작업 완료 시점과 작업 대기 여부에 따라 구분됩니다. 동시성 프로그래밍에서 이 두 개념은 작업을 처리하는 방식과 실행 흐름에 중요한 영향을 미칩니다.

 

1. 동기(Synchronous)

동기 방식은 작업이 완료될 때까지 현재 실행 흐름이 대기하는 방식입니다.

  • 특징:
    • 하나의 작업이 끝날 때까지 다음 작업이 실행되지 않습니다.
    • 호출한 함수는 작업 완료 후 결과를 반환합니다.
    • 실행 흐름이 순차적으로 진행됩니다.
  • 장점:
    • 코드의 흐름이 단순하고 이해하기 쉽습니다.
    • 작업 간 의존성이 있는 경우 적합합니다.
  • 단점:
    • 시간이 오래 걸리는 작업(예: 파일 읽기, 네트워크 요청) 중에는 다른 작업이 차단됩니다.
    • 응답성이 저하될 수 있습니다.
func synchronousTask() {
    print("Task 1 시작")
    Thread.sleep(forTimeInterval: 2) // 작업이 완료될 때까지 대기
    print("Task 1 완료")
    print("Task 2 시작")
}

synchronousTask()
// 출력:
// Task 1 시작
// (2초 대기)
// Task 1 완료
// Task 2 시작

 

 

2. 비동기(Asynchronous)

비동기 방식은 작업을 요청한 후 바로 다음 작업으로 실행 흐름이 넘어가는 방식입니다.

  • 특징:
    • 작업 완료 여부와 관계없이 다음 코드를 실행합니다.
    • 작업이 끝난 후 콜백(Callback), 클로저, 프라미스(Promise) 등을 통해 결과를 처리합니다.
    • 실행 흐름이 **비차단적(Non-blocking)**입니다.
  • 장점:
    • 시간이 오래 걸리는 작업 중에도 다른 작업이 실행될 수 있어 효율적입니다.
    • 응답성이 개선되어 UI가 더 매끄럽게 작동합니다.
  • 단점:
    • 코드의 흐름이 복잡해질 수 있습니다(특히 중첩된 콜백 사용 시).
    • 결과 처리를 위해 클로저, 콜백, 또는 비동기 작업 관리 도구(Futures/Promises 등)가 필요합니다.
func asynchronousTask() {
    print("Task 1 시작")
    DispatchQueue.global().async {
        Thread.sleep(forTimeInterval: 2) // 백그라운드 작업
        print("Task 1 완료")
    }
    print("Task 2 시작")
}

asynchronousTask()
// 출력:
// Task 1 시작
// Task 2 시작
// (2초 후)
// Task 1 완료

실행 과정 상세 설명

  1. Task 1 시작 출력
    • 함수가 실행되면서 첫 번째 줄의 print("Task 1 시작")이 바로 실행됩니다.
    • 출력: Task 1 시작.
  2. 비동기 작업 제출 (DispatchQueue.global().async)
    • DispatchQueue.global().async로 비동기 작업을 백그라운드에서 실행하도록 제출합니다.
    • 중요한 점은, 비동기로 실행되므로 현재 함수의 실행 흐름이 멈추지 않고 다음 줄로 넘어갑니다.
    • 백그라운드에서 비동기 작업이 대기열(Queue)에 들어가고, 실행될 준비가 됩니다.
  3. Task 2 시작 출력
    • print("Task 2 시작")은 async 작업이 시작되는 것과 관계없이 바로 실행됩니다.
    • 출력: Task 2 시작.
  4. 백그라운드에서 비동기 작업 실행
    • 대기열에 있던 async 작업이 실행됩니다. 여기서 Thread.sleep(forTimeInterval: 2)로 인해 2초 동안 작업이 중단됩니다.
    • 2초가 지나면 print("Task 1 완료")가 실행됩니다.
    • 출력: Task 1 완료.

 

3. 주요 차이점

특징 동기(Synchronous) 비동기(Asynchronous)
작업 완료 대기 여부 작업 완료 시까지 대기 대기하지 않고 다음 작업으로 진행
흐름 차단 여부 차단(Block) 비차단(Non-block)
효율성 시간이 오래 걸리는 작업에 비효율적 작업을 병렬적으로 처리하여 효율적
코드 단순성 흐름이 단순하고 이해하기 쉬움 콜백이나 클로저로 인해 복잡할 수 있음
사용 사례 순차적인 작업 처리 네트워크 요청, 파일 처리, UI 업데이트 등

 

 

4. 언제 동기와 비동기를 사용할까?

  1. 동기(Synchronous)를 사용하는 경우
    • 작업이 순차적으로 진행되어야 할 때.
    • 한 작업이 끝난 결과를 다른 작업이 반드시 필요로 할 때.
    • 작업 처리 시간이 매우 짧아 응답성에 영향을 미치지 않을 때.
  2. 비동기(Asynchronous)를 사용하는 경우
    • 작업이 오래 걸릴 가능성이 있는 경우(예: 네트워크 요청, 파일 읽기/쓰기).
    • UI의 응답성을 유지해야 하는 경우(예: 사용자 인터페이스 업데이트).
    • 여러 작업을 동시에 처리하거나 효율성을 극대화하고 싶을 때.