동기와 비동기는 작업 완료 시점과 작업 대기 여부에 따라 구분됩니다. 동시성 프로그래밍에서 이 두 개념은 작업을 처리하는 방식과 실행 흐름에 중요한 영향을 미칩니다.
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 완료
실행 과정 상세 설명
- Task 1 시작 출력
- 함수가 실행되면서 첫 번째 줄의 print("Task 1 시작")이 바로 실행됩니다.
- 출력: Task 1 시작.
- 비동기 작업 제출 (DispatchQueue.global().async)
- DispatchQueue.global().async로 비동기 작업을 백그라운드에서 실행하도록 제출합니다.
- 중요한 점은, 비동기로 실행되므로 현재 함수의 실행 흐름이 멈추지 않고 다음 줄로 넘어갑니다.
- 백그라운드에서 비동기 작업이 대기열(Queue)에 들어가고, 실행될 준비가 됩니다.
- Task 2 시작 출력
- print("Task 2 시작")은 async 작업이 시작되는 것과 관계없이 바로 실행됩니다.
- 출력: Task 2 시작.
- 백그라운드에서 비동기 작업 실행
- 대기열에 있던 async 작업이 실행됩니다. 여기서 Thread.sleep(forTimeInterval: 2)로 인해 2초 동안 작업이 중단됩니다.
- 2초가 지나면 print("Task 1 완료")가 실행됩니다.
- 출력: Task 1 완료.
3. 주요 차이점
특징 | 동기(Synchronous) | 비동기(Asynchronous) |
작업 완료 대기 여부 | 작업 완료 시까지 대기 | 대기하지 않고 다음 작업으로 진행 |
흐름 차단 여부 | 차단(Block) | 비차단(Non-block) |
효율성 | 시간이 오래 걸리는 작업에 비효율적 | 작업을 병렬적으로 처리하여 효율적 |
코드 단순성 | 흐름이 단순하고 이해하기 쉬움 | 콜백이나 클로저로 인해 복잡할 수 있음 |
사용 사례 | 순차적인 작업 처리 | 네트워크 요청, 파일 처리, UI 업데이트 등 |
4. 언제 동기와 비동기를 사용할까?
- 동기(Synchronous)를 사용하는 경우
- 작업이 순차적으로 진행되어야 할 때.
- 한 작업이 끝난 결과를 다른 작업이 반드시 필요로 할 때.
- 작업 처리 시간이 매우 짧아 응답성에 영향을 미치지 않을 때.
- 비동기(Asynchronous)를 사용하는 경우
- 작업이 오래 걸릴 가능성이 있는 경우(예: 네트워크 요청, 파일 읽기/쓰기).
- UI의 응답성을 유지해야 하는 경우(예: 사용자 인터페이스 업데이트).
- 여러 작업을 동시에 처리하거나 효율성을 극대화하고 싶을 때.
'정보' 카테고리의 다른 글
Swift의 동시성(Concurrency) 프로그래밍에 대해 설명해주세요. (1) | 2024.11.23 |
---|---|
GCD(Grand Central Dispatch)의 주요 개념과 사용 방법을 설명해주세요. (1) | 2024.11.20 |
Swift의 클로저와 함수의 차이점은 무엇인가요? (2) | 2024.11.19 |
Swift의 제네릭(Generic)에 대해 설명해주세요. (0) | 2024.11.15 |
의존성 주입을 활용하여 테스트 가능한 코드 작성 - 추가 (0) | 2024.11.15 |