동기 / 비동기 처리

velog_ghost·2022년 7월 6일
0

[SeSAC] TIL📚

목록 보기
4/19

비동기 처리의 필요성

핸드폰 화면을 볼때에 핸드폰 화면은 약 1초에 60번씩 화면을 새로 그리는 것! => 실제 화면을 다시 그리는 일은 Thread1(메인쓰레드) 에서 담당 (반복문을 통해 화면을 다시 그림)

이때 1초에 60번씩 화면을 그린다는 용어 : 화면 주사율 60Hz

여러 작업들을 메인쓰레드에 시키면 화면을 그리는 일 + 여러 작업이 되므로 버벅거림 등 문제가 발생함

(ex: 네트워크 작업)

따라서 이러한 문제를 해결하기 위해 작업들을 다른 쓰레드에 시키고 다시 그 값을 받아오면 됌!

이러한 것을 분산처리라고 하며, 분산처리를 어떻게 하는지에 대한 코딩 방법은 비동기 처리 / 동시성 프로그래밍

iOS에서의 동시성을 처리하는 방법 : 작업(Task)을 대기행렬 (큐(Queue))에 보내기만 하면, iOS가 알아서 여러 쓰레드로 나눠서 분산처리를 함.

이때 분산처리 하는 방식은 선입선출(FIFO)로 먼저 들어온 작업을 먼저 배치

-> 따라서 개발자는 작업을 큐로 보내기만 하면 된다!

iOS 프로그래밍에서는 대기열에 크게 2종류가 있음

1) DispatchQueue (GCD: Grand Central DispatchQueue)

2) OperationQueue

OperationQueue는 매우 어려운 개념이므로 설명 x

병렬(Parallel)과 동시성(Concurrency)의 개념

쓰레드는 물리적인 쓰레드, OS영역, 소프트웨어적 쓰레드가 존재

물리적인 쓰레드 : 실제 물리적인 계산을 실행

OS영역 : NSThread라는 객체의 모음

소프트웨어적인 쓰레드 : 앱 단위에서 이루어지는 것

병렬 : 물리적인 쓰레드에서 실제 동시에 일을 하는 개념 => 내부적으로 알아서 동작하므로 개발자가 전혀 신경쓸 필요가 없음

동시성 : 메인 쓰레드가 아닌 다른 소프트웨어적인 쓰레드에서 동시에 일을 하는 개념 : 개발자가 신경써야 함!

개발자는 소프트웨어적인 동시성 처리만 신경쓰면 된다!

GCD

직접적으로 쓰레드를 관리하는 개념이 아닌, 대기열 (Queue)의 개념을 이용해 작업을 분산처리하고 OS에서 알아서 쓰레드 개수를 관리

쓰레드보다 더 높은 레벨/차원에서 작업을 처리 (쓰레드 객체를 직접 생성시키거나 하지 않음)

메인쓰레드가 아닌 다른 쓰레드에서 오래걸리는 작업들이 쉽게 비동기적으로 동작하도록 함

비동기 / 동기의 개념

비동기(Async) 처리 : 다른 쓰레드에 작업을 시키고 작업이 끝날때까지 기다리지 않음

동기(Sync) 처리 : 다른 쓰레드에 작업을 시작시키고, 뿐만 아니라 작업이 끝날 때까지 기다림

이때 메인쓰레드에서는 동기 처리를 할때 작업을 시작시키고 기다리는동안 Blocking이 된 상태로 기다림

Swift는 동기는 Blocking 개념으로, 비동기는 Non-Blocking개념으로 사용

직렬(Serial) / 동시(Concurrent)의 개념

직렬 : 분산처리 작업을 다른 한개의 쓰레드에서만 처리하는 큐

동시 : 분산처리 작업을 다른 여러개의 쓰레드에서 처리하는 큐

동시가 직렬보다 더 좋아보이는데, 왜 직렬을 사용할까?

직렬 : 순서가 중요한 작업을 처리할때 사용!

동시 : 각자 독립적이지만 유사한 여러개의 작업을 처리할때 사용

GCD의 개념 및 종류

디스패치큐(GCD)

메인큐 : DispatchQueue.main (직렬)
글로벌큐 : DispatchQueue.global() (동시)
프라이빗 큐 : DispatchQueue(label: "...") (둘다 가능. 디폴트 : 직렬)

메인큐(DispatchQueue.main)

DispatchQueue.main : 메인큐로 메인 쓰레드를 의미하며 직렬임. UI업데이트 내용을 처리하는 큐
글로벌큐(DispatchQueue.global())

DispatchQueue.global() : 종류가 여러개, 기본설정 동시, Qos(서비스 품질) -> 6종류
// 큐의 서비스 품질 개념은 iOS가 알아서 우선적으로 중요한 일임을 인지하고 쓰레드에 우선순위를 매겨 더 많은
// 쓰레드를 배치하고 CPU의 배터리를 더 집중시켜 사용하도록 해서 일을 빨리 끝내도록 하는 개념

DispatchQueue.global(qos: default) // 일반적인 작업. 디폴트큐
DispatchQueue.global(qos: utility) // 보통 Progress Indictor와 함께 길게 실행되는 작업, 계산
DispatchQueue.global(qos: userInteractive) // 유저와 직접적 인터렉티브
DispatchQueue.global(qos: userInitiated) // 유저가 즉시 필요하긴 하지만 비동기적으로 처리된 작업
DispatchQueue.global(qos: background) // 유저가 직접적으로 인지하지 않고 시간이 중요하지 않은 작업
DispatchQueue.global(qos: unspecified) // legacy API 지원 : 쓰레드를 서비스품질에서 제외시키는

프라이빗큐(DispatchQueue(label: "..."))

프라이빗 큐 : DispatchQueue(label: "...")
커스텀으로 만드는 큐로, 직접 만드는 것!

0개의 댓글