iOS

iOS 동시성 (GCD Grand Central Dispatch) 기본 개념

728x90

목차

- 왜 공부하게 되었는가( 쓰레드 충돌, 테이블뷰 스크롤 뷰 이동 )

- 동시성이 왜 필요한가

- ios에서 동시성 관리하는 방법

- 동기, 비동기 개념

- 직렬큐, 동시큐 

- DispatchQuque 나머지

왜 동시성을 공부하게 되었는가?

1) 앱 개발을 하던 중에 realm이 쓰레드 충돌을 일으켜서

  -  realm을 싱글톤으로 사용하고 있었고 .NSCalendarDayChanged 에서 충돌이 일어남. 

2) tableView 스크롤이 dispatchQueue로 묶어줘야 동작하는데 그 이유를 알기 위해

// 왜 DispatchQueue로 감싸주어야 하지?
DispatchQueue.main.async() {
    let indexPath:IndexPath = IndexPath(row: 11, section: 0)
    self.tableView.scrollToRow(at: indexPath, at: .top, animated: false)
}

3) Rxswift 공부하기전에 기본 개념을 알기 위해서

 

위 3가지 이유 때문에 GCD을 공부하게 되었다.

 

왜 동시성이 필요한가?

업무를 좀 더 효율적으로 처리하기 위해 필요하다.

업무를 처리 할 수 있는 쓰레드가 여러개 존재한다고 가정 했을 때, 한개의 쓰레드만 사용하는건 너무 비효율적입니다.

Thread 동시성

사진 왼쪽은 하나의 Thread가 모든 Task를 처리하고, 오른쪽은 Thread들에게 Task를 분배해서 처리를 하고 있다.

당연히 후자가 더 효율적이다.

 

그러면 iOS에서 Task들 어떻게 여러개의 Thread에 올릴 수 있을까?

-> 오히려 쉽게 처리가 가능한데 대기행렬(queue)에 올려 놓으면 알아서 Thread에 배치를 해준다. Queue에서 FIFO 방식으로 처리되고 누가 먼저 끝날 지는 Task의 수행시간 마다 다르기 때문에 보장하지 않는다.

 

iOS DispatchQuque

queue에 Task를 올려보자. 

// Quque로 보낼거야.global로.비동기적으로
DispatchQueue.global().async{
// task 
// 이 블록 안이 작업의 한단위가 됩니다.

}

-> Quque로 보낼거야. global로. 비동기적으로

-> apple에서 guide 중에 유창하게 읽히도록 코드를 짜라는 가이드라인이 있는데, 여기서 잘 드러난다.

 

이렇게 작성을 하면 { } 안에 적힌 내용이 Queue(대기행렬)에 올라가게 되고 iOS에서 적당한 시점에 Thread에 올려 비동기적으로 실행을 해줄 것이다.

 

비동기 vs 동기

동기 Sync, 비동기(Async)의 간단한 개념

  • 이전 작업을 기다리지 않고 실행함 - 비동기
  • 이전 작업을 끝내는걸 기다리고 실행함 - 동기

비동기가 존재하는 이유 중 하나는 iOS에서 데이터가 다운로드 된다고 해서 화면 새로고침이 안되거나, 다른 버튼 클릭이 먹통이 된다면 사용자는 버그가 걸렸다고 생각 할 것이다. 데이터가 백그라운드에서 다운로드 되는 와중에도 다른 기능들이 정상적으로 동작해야하는데 이럴 때 비동기적 작업을 한다. 실제로 Javascript의 버튼 클릭과 같은 event들은 모두 비동기다.

 

Serial(직렬) 큐 vs Concurrent(동시) 큐

Quque도 종류가 있다. 직렬큐와 동시큐가 존재하는데 각각 용도가 다르다.

  • 직렬 큐: 분산처리 시킨 작업을 하나의 쓰레드로만 처리하는 큐
    직렬 큐
  • 동시 큐: 분산처리 시킨 작업을 여러개의 쓰레드에서 처리하는 큐.
  • 동시 큐
     
  • 직렬 큐 왜 필요하지? → 순서가 중요한 작업을 처리할 때
  • 동시 큐 → 각자 독립적이지만 유사한 작업을 처리할 때
    • 각각 한 셀에서 데이터를 요청해서 그리는 작업 → 유사한 작업이고, 동시적으로 처리함

 

iOS에서 UI를 그리는 mainQueue는 직렬 큐로 동작한다.

큐의 종류

DispatchQueue의 나머지

- 우선순위(qos)

: 당연히 Task의 우선순위를 정할 수 있다. 

 

- dispatchqueue 주의사항

: dipatchQuque를 사용 할 때 mainQueue에서 sync를 사용하지 말아라 같은 내용들이 있는데, 이것만 알아도 될 것 같다.

 

- dispatch group

: 여러 dispatch들을 group으로 묶어서 언제 끝나는지 알 수 있다. 필요한 데이터들이 모두 다운로드 되었을 때, 어떤 행위를 하라고 할 수 있다. 예를 들면 앱에서 고정적인 사진을 사용하면 앱을 실행 할 때 필요한 사진들을 url로 다운받고 모두 캐시로 저장하고 앱을 실행 시킬 수 있을 것 같다.

 

- semapore (수기신호)

: 자원의 숫자를 주고, Thread 숫자를 제한하는 작업이다. 즉, 한번에 실행 할 자원의 제한을 주는 것인데 실제로 사용은 안할 것 같다.

예를 들면, 다운로드를 하는데 semapore를 4를 주면 4개씩만 다운로드 하는 것이다. 한번에 다다닥 다운받는게 낫지 굳이 4개씩 딱딱 끊어가며 받을 이유가 뭐가 있겠는가. 다만, 동시성 문제에서 경쟁상황을 해결 할 때, 쓰이긴하지만 경쟁상황이 얼마나 자주 일어나겠나 싶다.

 

- 동시성의 문제들 (경쟁상황, 교착상태, 우선순위의 뒤바뀜) 

: 문제가 생기면 어느시점에서 발생했는지 알기 어렵기 때문에 발견하기 어렵다. 비동기 문제가 언제는 되고 언제는 안되는 문제들이 발생하는데 위의 기본 개념들을 잘 알고 있으면 충분히 해결 가능한 문제들이다. (익숙하지 않아서 엄청 오래걸릴 것 같다.)

 

후기

여기까지 이외에도 출저에 있는 강의에서 많은 걸 가르쳐준다.

실 코드도 dispatchQueue 보여주긴하는데 뭔가 실제로 사용하는 코드가 아닌 그냥 이해를 돕기위한 코드라 다른 블로그나 다른 문서나, 그냥 코드가 있는 다른 강의들 보면 될 것 같다. 

문서들을 직접 안찾아보고 한국어로 되어있는 영상이라 개꿀이였는데, 가격이 비싸긴하다.

역시 돈이 최고인가 싶다..

 

또, 실제로 사용을 해보고 나서 강의를 들어야지 후반의 Operation 부분은 사용해본 적이 없고 굳이 들어야 되나 싶어서 걸렀다. 

나중에 RxSwift를 공부 할 때, 기본개념이 생각이 안나면 한번 더 봐야겠다.

 

출처 : https://www.inflearn.com/course/iOS-Concurrency-GCD-Operation/dashboard

반응형

'iOS' 카테고리의 다른 글

combine - 2. Network 예제 살펴보기  (0) 2022.04.18
combine - 1. Combine에 관하여  (0) 2022.03.14
3. View의 생명주기 (LifeCycle)  (0) 2022.02.04
2. View에 관하여 (Frame, Bounds)  (0) 2022.02.04
1. 계산기 코드로 보는 MVC 패턴  (0) 2022.02.01