iOS/Swift

[Swift] Dispatch Work Item

kimsangjunzzang 2025. 2. 24. 16:47
728x90
반응형

안녕하세요, iOS 개발하는 루피입니다!

 

오늘은 Dispatch Work Item에 대해 정리해 보는 시간을 가져보도록 하겠습니다.

 

바로 시작합니다.


Dispatch Work Item 이란?

수행하고 싶은 작업을 캡슐화해서, 완료 핸들러나 실행 의존성을 붙일 수 있게 해주는 도구입니다.

Dispatch Work Item은 디스패치 큐나 디스패치 그룹에서 실행할 작업을 깔끔하게 묶어 놓은 것이라고 생각하면 편합니다.

.init {
	qos: DispatchQoS = .unspecified,
	flags: DispatchWorkItemFlags = [],
	block: @escaping () -> Void
}

1. 매개변수 (Parameters)

  • qos : 작업 아이템의 실행 우선순위를 정할 때 쓰이는 클래스예요. 이 작업이 얼마나 급한지 시스템에 알려주는 겁니다.
  • flags : 작업 아이템을 설정하는 옵션이에요. 작업을 어떻게 실행할지 세부 조정할 때 사용합니다.
  • block : 실제로 수행할 작업을 담은 블록이에요.

 

let workItem = DispatchWorkItem(qos: .userInitiated) {
    print("빠른 작업!")
}
DispatchQueue.global().async(execute: workItem)

만들어진 Dispatch Work Item을 큐에 넘겨주면, 그 큐에서 실행되도록 스케줄링됩니다.

 

디스패치 큐는 지정한 flags와 큐의 기본 스레드 우선순위에 따라 qos 수준을 조정할 수 있어요. 하지만 절대로 qos 매개변수에 설정한 수준보다 낮게 실행되진 않아 보장된 성능을 기대할 수 있습니다.


2. DispatchWorkItemFlags

DispatchWorkItem의 동작 방식을 설정하는 옵션들의 모음입니다.

예를 들어, 작업의 우선순위나 동시 큐에서 barrier처럼 동작할지, 새 스레드를 독립적으로 띄울지 같은 걸 정할 수 있습니다.

  • assignCurrentContext : 작업 아이템의 속성을 지금 실행 중인 컨텍스트의 속성과 맞춰줍니다.
    • 현재 스레드의 설정을 그대로 따라가게 해요.
  • barrier : 동시 큐에 넣었을 때 이 작업이 장벽처럼 동작하게 해요.
    • 다른 작업을 막고 이 작업이 끝날 때까지 기다리게 만듭니다.
  • detached : 작업 아이템의 속성을 현재 환경과 분리해요.
    • 현재 스레드와 상관없이 독립적으로 실행됩니다.
  • enforceQoS : 작업 블록에 설정된 QoS를 우선시해요.
    • 내가 정한 우선순위를 강제로 적용합니다.
  • inheritQoS : 현재 실행 환경의 QoS를 우선시해요.
    • 현재 스레드의 우선순위를 물려받아요.
  • noQoS : QoS를 아예 지정하지 않고 작업을 실행해요.
    • 우선순위를 시스템이 알아서 정하게 둡니다.

❗️Dispatch work Item vs Dispatch Group

Dispatch work Item 과 Dispatch Group에 차이점이 흔들릴 수 있어 한번 짚고 넘어가 보겠습니다.

  • DispatchWorkItem: 작업 하나를 다룸 → 실행하고 관리하는 데 초점.
  • DispatchGroup: 작업 여러 개를 묶음 → 완료 시점을 체크하는 데 초점.
let group = DispatchGroup()
let workItem1 = DispatchWorkItem { print("작업 1"); sleep(1) }
let workItem2 = DispatchWorkItem { print("작업 2"); sleep(2) }

group.enter()
DispatchQueue.global().async(execute: workItem1) { group.leave() }
group.enter()
DispatchQueue.global().async(execute: workItem2) { group.leave() }

group.notify(queue: .main) { print("모두 끝!") }

3. perform()

현재 스레드에서 작업을 즉시 동기적으로 실행합니다. 비동기 큐(async) 없이 바로 실행되며, qos로 설정한 우선순위 이상을 보장합니다.

let workItem = DispatchWorkItem(qos: .utility) {
    print("직접 실행!")
}
workItem.perform()
// 현재 스레드에서 바로 실행, qos는 .utility 이상 보장

4. wait()

호출한 쪽에서 Dispatch Work Item이 실행을 끝낼 때까지 동기적(호출 스레드를 멈추고)으로 기다리게 해 줍니다.

만약 작업 아이템이 이미 실행을 끝냈다면, 이 메서드는 바로 돌아옵니다. 이때, 메인 스레드에서 호출하면 UI가 멈추니 백그라운드에서 써야 해요.


5. wait(timeout: )

func wait(timeout: DispatchTime) -> DispatchTimeoutResult // 상대 시간
func wait(wallTimeout: DispatchWallTime) -> DispatchTimeoutResult // 절대 시간

호출한 쪽에서 Dispatch Work Item이 실행을 끝낼 때까지, 또는 지정한 시간이 지날 때까지 동기적으로 기다리게 합니다.

5 - 1. 매개변수 (Parameters)

timeout : 작업이 끝나길 기다리는 최대 시간입니다. distantFuture를 넣으면 그냥 wait()처럼 무한정 기다리는 것과 같아요."

5 - 2. 반환값 (Return Value)

  • DispatchTimeoutResult.success : 작업이 지정한 시간 안에 끝나서 메서드가 돌아왔을 때.
  • DispatchTimeoutResult.timedOut : 타임아웃 시간이 됐는데 작업이 안 끝났을 때.

5 - 3. DispatchTime vs DispatchWallTime 차이

  • DispatchTime: 시스템 부팅 이후의 상대적 시간(나노초 단위). 디바이스가 잠들었다 깨어나면 시간이 멈췄다가 다시 흐릅니다.
  • DispatchWallTime: 실제 벽시계 시간(Unix 타임스탬프 기준). 디바이스 상태와 상관없이 절대 시간으로 계산합니다.

6. cancel()

작업 아이템을 비동기적으로 취소합니다. 이후 실행 시도는 무시되고, 이미 시작된 작업은 끝까지 실행됩니다. 자원 해제는 진행 중인 작업이 완료될 때까지 미뤄집니다.

 


오늘도 화이팅 입니다!

 

728x90
반응형