티스토리 뷰

 

최근 컴바인을 시작했는데 아직 개념적인 부분들이 채워지지 않는것 같아서 기초부터 봐야할 것 같다. 컴바인, Rx 전부 비동기 처리에 있어서 이점이 있다고 들어왔는데 정작 동기, 비동기에 대한 내용을 충분히 이해하고 있다고 생각지 않기 때문이다.


우선적으로 동기와 비동기에 대한 의미부터 보도록 하자. 동기 비동기에 대해 검색을 하다 보니 동기의 의미를 동시에 일어난다!와 같이 설명해주는 내용을 보았는데 다중 스레드에서 동시에 접근하면 동기가 아닌가!? 하는 의문부터 들었다. (보통 비동기 방식이 동시 접근이 가능하지 않나?)

 

여러 글을 보다 다른 해석을 보게되었다. 우선 Synchronous는 명사가 아니며 형용사를 명사로 옮기는 과정에서 오해하기 쉽게 내용이 붙은거 같다는 얘기와 필자는 동기현재 작업의 응답과 다음 작업의 요청의 타이밍이 일치하는 것으로 본다는 것이다. 이런 관점에서 보는게 이해하기가 좀 더 수월했다.

동기(Synchronous)

  • 현재 작업의 응답과 다음 작업의 요청 타이밍이 일치하는 것
  • 작업의 흐름이 순차적으로 진행

비동기(Asynchronous)

  • 현재 작업의 응답과 다음 작업의 요청 타이밍이 일치하지 않아도 되는 것
  • 작업의 흐름이 독립적으로 진행

기초적인 async

print("작업 1 시작")
DispatchQueue.global().async {
    sleep(2)  // 2초 동안 멈춤 (비동기 실행)
    print("작업 1 끝")
}
print("작업 2 시작")

// "작업 1 시작" 이후 "작업 1 끝"은 비동기로 처리가 되었기 때문에 "작업 2 시작"이 먼저 되었다.
작업 1 시작
작업 2 시작
작업 1 끝

 

직렬 큐

let queue1 = DispatchQueue(label: "serialQueue1")  // 직렬 큐 생성
let queue2 = DispatchQueue(label: "serialQueue2")  // 직렬 큐 생성
queue1.async {
	print("작업 1 시작")
	sleep(4)
	print("작업 1 끝")
}
queue2.async {
	print("작업 3 시작")
	sleep(4)
	print("작업 3 끝")
}
queue1.async {
	print("작업 2 시작")
	sleep(2)
	print("작업 2 끝")
}

// 직렬 큐를 2개 만들어서 각 비동기 처리를 해주면 내부 큐에서는 직렬로 비동기 처리
// 작업 1이 끝나야 작업 2를 시작 / 작업 3은 별개로 처리
작업 1 시작
작업 3 시작
작업 1 끝
작업 2 시작
작업 3 끝
작업 2 끝

 

병렬 큐

let queue = DispatchQueue.global(qos: .userInitiated)  // 글로벌 큐 (병렬)
queue.async {
	print("작업 1 시작")
	sleep(2)
	print("작업 1 끝")
}
queue.async {
	print("작업 2 시작")
	sleep(2)
	print("작업 2 끝")
}
print("메인 스레드 실행 중")

// 병렬 큐에서 비동기 처리를 해주기 때문에 모든 작업이 동시에 실행 될 수 있음(꼭 메인 이후 글로벌이 돌아가는 것은 아님 - 순서 바뀔 수 있음)
메인 스레드 실행 중
작업 1 시작
작업 2 시작
작업 1 끝
작업 2 끝

주의점

  • 네트워크 통신 부분은 글로벌 큐(백그라운드)에서 처리해도 괜찮지만 UI업데이트는 반드시 메인 스레드에서 진행해야함
print("1. 네트워크 요청 시작")
DispatchQueue.global().async {
    sleep(2)
    print("2. 네트워크 데이터 받아옴")
    DispatchQueue.main.async {
        print("3. UI 업데이트 실행")
    }
}
print("4. 다음 코드 실행 (비동기 방식)")

"1. 네트워크 요청 시작" - 메인 스레드
"4. 다음 코드 실행 (비동기 방식)" - 메인 스레드
"2. 네트워크 데이터 받아옴" - 백그라운드
"3. UI 업데이트 실행" - 메인 스레드

동기/비동기 방식의 조합

동기, 비동기 방식에 직렬, 병렬 연결을 조합하면 4가지 조합이 등장한다

  1. SerialQueue + Sync : 메인을 멈추고 큐에 담긴 순서대로 모든 Task를 처리 (직렬 + 동기)
  2. SerialQueue + Async : 메인을 멈추지 않고 큐에 담긴 순서대로 모든 Task를 처리 (직렬 + 비동기)
  3. Concurrent + Sync : 메인을 멈추고 여러큐에 담긴 Task를 각자 처리 (병렬 + 동기)
  4. Concurrent + Async : 메인을 멈추지 않고 여러큐에 담긴 Task를 각자 처리 (병렬 + 비동기)

Q) 직렬 Async는 언제 쓸까? : 단순히 생각해보면 컬렉션이나 테이블 셀을 생성할때 각 셀을 비동기로 처리하면서 내부 셀을 생성할때는 정보를 받아오고 셀을 생성해야하니 직렬로 구성하는게 맞는것 같다 -> 전체 셀(병렬처리) > 각 셀(직렬처리)

Dispatch Queue의 종류

앞에서 확인해보았던 소스에서 확인이 가능하다

  1. DispatchQueue.main
    • 메인 스레드
    • Serial 특성을 지님
    • UI 업데이트는 메인에서만 진행
  2. DispatchQueue.global()
    • 서브 스레드
    • Concurrent 특성을 지님
    • QoS (Quality of Service)에 따라 6종류로 나뉨
    • 우선 순위가 높은 작업에 더 많은 스레드가 배치됨
  3. DispatchQueue(label: "커스텀 스레드의 이름")
    • 커스텀 스레드
    • Default는 Serial 특성, Concurrent로 설정 가능
    • DispatchQueue(label: "큐1", attributes: .concurrent) : "큐1" 이라는 이름으로 concurrent특성을 지닌 커스텀 스레드를 생성, QoS는 자동 추론
    • DispatchQueue(label: "큐2", qos: .utility, attributes: .serial) : "큐2" 라는 이름으로 serial 특성을 지니고 qos는 utility를 지닌 커스텀 스레드를 생성

QoS 종류

1. userInteractive : The quality-of-service class for user-interactive tasks, such as animations, event handling, or updating your app’s user interface.

  • 사용자 상호 작용(애니메이션, 이벤트, 인터페이스 업데이트) 작업을 위함
  • DispatchQueue.main 은 QoS가 userInteractive임 (인터페이스 업데이트를 위해서) - 다만 역으로 userInteractive QoS라 해서 main 인 것은 아님
  • 이 내용같은 경우 UI업데이트는 메인에서 해야한다는 얘기와 상충이 된다고 볼 수 있지만, 여기의 내용을 보면 사용자의 동작을 따라가기 위해 메인에서 특정 동작이 들어가는 동안 다른 코어에서 무언가를 계산해야 하는 경우가 존재하기 때문에 global에서도 설정이 가능하다고 함

2. userInitiated : The quality-of-service class for tasks that prevent the user from actively using your app.

  • 사용자가 앱을 적극적으로 사용하지 못하게 하는 작업을 위함
  • 즉각적인 결과가 필요한 작업 (저장된 문서 열기)

3. default : The default quality-of-service class.

  • 가장 기본적인 작업을 위함

4. utility : The quality-of-service class for tasks that the user does not track actively.

  • 사용자가 적극적으로 추적하지 않는 작업을 위함
  • 보통 progress bar와 함께 길게 실행되는 작업 (데이터 다운로드)

5. background : The quality-of-service class for maintenance or cleanup tasks that you create.

  • 사용자가 만든 유지관리, 정리 작업을 위함
  • 직접적으로 인지하지 않는 시간이 덜 중요한 작업 (동기화, 백업)

6. unspecified : The absence of a quality-of-service class.

  • 등급이 없는 작업을 위함( etc 인듯 )
  • 거의 사용할 일 없음

참고자료

'프로그래밍 > iOS' 카테고리의 다른 글

[Combine-2] Combine? Publisher? Subscriber? Operator?  (0) 2025.03.06
SnapKit, Then 알아보자  (0) 2025.03.04
뷰컨트롤러 생명주기  (1) 2024.07.18
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함