[Swift] 디스패치큐(GCD)의 종류와 특성 / 주의 사항

yxxjxn·2024년 2월 21일

swift study

목록 보기
8/8

왜 동시성 프로그래밍이 필요할까?

큐만 만들어서 넣으면 iOS가 알아서 교통정리를 해준다

DispatchQueue.global().async {
    // 작업의 한 단위
}
  • 큐에 보낼거야 / 글로벌로 / 비동기적으로

특징

  • 직접적으로 쓰레드를 관리하지 않고, 큐라는 개념을 이용해 작업을 분산 처리
  • GCD / Operation을 사용해 시스템에서 알아서 쓰레드 숫자를 관리함
  • 쓰레드 보다 더 높은 레벨/차원 에서 일을 한다고 보면됨
  • 쉽게 다른 쓰레드에서 오래걸리는 작업들이 비동기적으로 동작하도록 만들어줌

GCD : Grand Central Dispatch = 디스패치큐

  • 간단한 일
  • 함수 사용하는 작업 (메서드 위주)

Operation : 오퍼레이션 큐

  • 복잡한 일
  • 데이터와 기능을 캡슐화한 객체
  • GCD 기반으로 만들어짐 + 여러가지 다른 기능
    • 취소 / 순서지정 / 일시중지 (상태추적)

GCD or Operation?

  • 프로젝트의 효율성, 사례 적합성 등을 활용해 선택해서 사용할 것!

Synchronous vs Asynchronous

  • 비동기는 task가 끝날때까지 메인큐에서 기다리지 않음
    • 작업을 다른 쓰레드에서 하도록 시킨 후, 그 작업이 끝나길 안 기다리고 다음 일을 진행
  • 동기는 기다림.
    • 작업을 다른 쓰레드에서 하도록 시킨 후, 그 작업이 끝나길 기다렸다가 다음 일을 진행

비동기가 필요한 이유

  • 대부분은 서버와의 통신(네트워크 작업) 때문이다
  • 네트워크와 관련된 작업들은 내부적으로 비동기적으로 구현되어있다

Serial vs Concurrency 직렬과 동시

  • 큐의 특성에 관한 것이다
  • 몇개의 쓰레드로 분산할지는 시스템이 알아서 결정

직렬 큐

  • 다른 한개의 쓰레드에서 처리하는 큐
  • 순서가 중요한 작업을 처리할 때 사용

동시 큐

  • 다른 여러개의 쓰레드에서 처리하는 큐
  • 독립적이지만 유사한 여러개의 작업을 처리할 때 사용

비동기 = 동시?

  • 작업을 보내는 시작점에서 기다릴지 말지 → 비동기
  • 대기열로 보내진 작업이 여러개의 쓰레드로 갈건지(동기) 한개로 갈건지(직렬) → 동시

2. 디스패치큐(GCD)의 종류와 특성

대기열마다 특성이 좀 다르다.

작업의 특성, 원하는 일처리에 따라 대기열(큐)의 특성에 맞게 작업을 보내면 된다

메인 큐

  • (유일한)한개, 시리얼, 메인쓰레드

글로벌 큐와 QOS의 이해

  • 알아서 여러개로 나눠서 실행해주는 큐다

  • 중요한 순서대로 큐

  • .userInteractive

    • 거의 즉시, UI
    • 유저와 직접적으로 상호 작용
  • .userInitiated

    • 유저가 즉시 필요하긴 하지만 비동기 : 앱 내에서 pdf 파일 여는 것과 같은
  • default

    • 일반적인 작업
  • .utility

    • 몇초에서 몇분
    • progress indicator와 함께 길게 실행되는 작업, 계산, IO, 네트워킹, 지속적인 데이터 feeds
  • .background

    • 속도보다는 에너지 효율성 증시, 몇분 이상
    • 유저가 직접적으로 인지하지 않고 시간이 안중요한 작업
    • 데이터 미리 가져오기
    • DB 유지
  • .unspecified

프라이빗(커스텀) 큐

  • 커스텀으로 만든다
  • 디폴트 설정(Serial)
  • Concurrent 설정 가능
  • Qos 설정도 가능하다

3. 디스패치 큐 사용시 주의해야할 사항

반드시 메인큐에서 처리해야하는 작업

  • UI 관련 일들은 메인큐에서 처리해야 한다

Untitled

Sync 메서드에 대한 주의사항 (sync 관련 절대 X)

  1. 메인큐에서는 다른 큐로 보낼 때 sync 메서드를 부르면 절대 안된다

    • 메인큐에서는 항상 비동기적으로 보내야한다. → async
    • sync → 다른 쓰레드로 보낸 작업 기다림 → 화면 버벅거림 발생할 수 밖에 없다
  2. 현재의 큐에서 현재의 큐로 동기적으로 보내서는 안된다. → 데드락의 발생 가능성이 존재한다

    DispatchQueue.global().async {
        DispatchQueue.global().sync {
        }
    }

weak, strong capture 주의

  • 객체에 대한 캡쳐 현상
  • 뷰컨트롤러 이미 소멸 됐는데 아직 돌아가고 있을수도 . . .

컴플리션 핸들러의 존재 이유

  • 비동기로 작업을 시키고 나서 작업에 해당하는 값을 바로 사용 x
  • 아직 종료되지 않았는데 해당 값 접근시 잘못된 값 사용할 확률 높음 → completionHandler

동기적 함수를 비동기 함수 처럼 만드는 방법

  • 여러번 재활용하기 위해서
  • 동기 함수 너무 오래 걸려서 → 비동기 처럼!!

캡처리스트의 [weak self]에 대한 이해

클래스의 인스턴스(객체), 클로저 ===> 힙 메모리에 할당

  1. 클래스 인스턴스

    변수를 weak, unowned로 선언 ===> 인스턴스를 참조하되, RC가 올라가지 않게 하므로 강한 참조 사이클 일어나지 않음

  2. 클로저

    클로저의 캡처리스트내에서 + weak, unowned로 선언 ===> 인스턴스를 참조하되, RC가 올라가지 않게 하므로 강한 참조 사이클 일어나지 않음

profile
macos

0개의 댓글