본 게시물은 앨런의 인프런 강의를 듣고 작성한 글 입니다.
네트워크 통신을 위해 비동기를 접하고 사용하였지만 원리를 제대로 파악하지 못하고 코드만 복사해서 동작하는 나를 발견하고 비동기에 대한 두려움을 없애기 위해 본 강의를 수강하기로 결정하였다.
자가진단표를 읽어봤을 때 대부분 내가 어려워하는 내용으로 구성되어 있었고, 내가 사용하면서 궁금했던 내용들이 많이 있었다.
왜 동시성 프로그래밍이 필요할까?
무언가를 학습하기에 앞서 중요한건 이 개념이 왜 등장했을까를 고민해보는 시간이라고 생각한다. 모든 개념들은 아무 이유 없이 등장한것이 아니기 때문에 그 이유를 아는것은 앞으로의 학습 내용에 큰 밑거름이 되어 줄 것이라고 생각한다.
동시성 프로그래밍이 내게 낯설게 느껴졌던 이유가 이것의 필요성을 몸소 깨닫지 못해서라는 생각도 든다. 내가 다루는 데이터의 양은 그다지 크지 않고 간단한 데이터들만을 다루었기 때문에 대규모의 데이터를 다룰 때 나타나는 현상을 경험하지 못했고 고민하지 않았다.
토이프로젝트를 진행하며 가상화폐의 정보를 가진 api를 사용한 경험이 있는데, 이 데이터를 불러와서 테이블 뷰로 나타내는 과정에서 버벅임이 있었다. 이를 해결하기 위해서 생각한 방법은 모든 데이터를 한번에 나타내는것이 아닌 어느정도의 데이터만 불러오고 사용자의 요청이 있다면 다음 데이터를 불러오는 방식으로 해결하는 방법을 생각했다. (paging)
아무튼 이와 같이 버벅이는 이유는 여러 task를 하나의 thread로 처리하는 과정에서 생기는 것이고 동시성 프로그래밍을 사용하여 task를 다른 thread에서 동시에 일을 하게 한다.
이는 task를 대기행렬에 보내기만 하면 된다는 의미이고, 여기서 대기행렬은 Queue를 의미한다. (FIFO방식 사용)
그 후 알아서 OS가 task를 다른 thread로 분산처리 하게된다.
GCD와 Operation
위에서 언급한 task를 thread로 옮기는 과정에서 필요한 Queue가 바로 GCD와 Operation이다.
1. 직접적으로 쓰레드를 관리하지 않고 큐(대기행렬)라는 개념을 이용해 작업을 분산처리한다.
2. GCD와 Operation을 사용해 시스템에서 알아서 thread를 관리한다.
* 직접 thread를 생성하여 관리할 수 있지만 이는 잘못 사용하면 오히려 앱이 느려질 수 있다.
3. thread보다 더 높은 레벨에서 일을 한다고 보면 된다.
4. 쉽게 다른 thread에서 작업들이 비동기적으로 동작하도록 만들어준다.
* 이때 작업은 보통 네트워크와 관련되고 오래 걸리는 작업이다.
DispatchQueue.global().async {
//code (closure)
}
iOS를 조금만 공부하면 볼 수 있는 코드이다.
이런식으로 구성된다고 생각하면 된다! 여기서 글로벌 큐가 궁금해졌는데..
큐는 main큐와 global큐, private큐(커스텀큐)로 크게 나누어지는데 main 큐는 하나만 존재, global 큐는 여러개 존재할 수 있다.
UI 처리는 꼭 main큐에서 처리해주어야 하는데 느려지는 UI 업데이트에 작업을 global로 분산시켜 task를 처리한다.
그래서 main큐에서는 중요한 일을 처리하고 global에서는 비교적 덜 중요한 일을 처리한다고 이해할 수 있다.
위에 그림에서 보면 thread1이 main큐, 나머지 thread가 global큐라고 이해할 수 있다.
기존 GCD만을 사용하였을 때, GCD는 간단한 일, 함수를 사용하는 작업등의 일을 처리하였지만, 보다 복잡한 일을 처리하기 위해 GCD에 기반하여 Operation이 등장하였다.
Operation은 보다 복잡하고, 데이터와 기능을 캡슐화한 객체를 다루어 취소, 순서지정, 일시중지와 같은 보다 복잡한 일을 처리할 수 있다.
Synchornous(동기)와 Asynchronous(비동기)
위 첫번째 그림에서 thread1에 있는 task를 thread2로 분산하는 과정에서..
동기는 task하나가 모두 일을 처리할 때 까지 기다린 후 다음 task를 처리한다.
따라서 소요시간은 task1 + task2 + task3 + task4 이다.
비동기는 task 하나를 다른 thread에 보내고 즉시 리턴하기 때문에 task가 일을 처리할 때 까지 기다리지 않는다.
즉, 메인thread가 다른 일을 처리할 수 있기 때문에 소요시간을 굉장히 짧다.
비동기라는 개념이 일반적으로 필요한 이유는 대부분의 서버와의 통신 때문이다. 네트워크와 관련된 작업들은 내부적으로 비동기적으로 구현되어 있는데, 만약 동기로 처리한다면 task하나하나가 모든 일을 처리할 때 까지 기다려야하기 때문에 시간이 굉장히 오래 걸린다.
따라서 네트워크 통신과 비동기는 필연적이라 볼 수 있다.
Serial(직렬)과 Concurrent(동시)
직렬큐는 메인큐에서 분산처리 시킨 작업을 다른 한개의 thread에서 처리하는 큐, 동시큐는 메인큐에서 분산처리 시킨 작업을 다른 여러개의 thread에서 처리하는 큐를 의미한다.
그렇다면 동시큐가 직렬큐보다 더 좋아보이는데 직렬큐가 필요한 이유는 무엇일까?
직렬큐는 순서가 중요한 작업을 처리할 때 사용한다. 그리고 동시큐는 각자 독립적이지만 유사한 여러개의 작업을 처리할 때 사용한다.
이와 같은 특징을 활용하여 직렬큐와 동시큐를 용도에 맞게 사용한다.
마지막으로.. 비동기라는 말과 동시라는 말은 같은 말일까?
이 강의를 듣기 전이라면 같은 말이라고 했을 수도 있을 것 같다. 결과적으로 둘은 다른 말이며, 동기/비동기는 작업을 보내는 시작점에서 기다릴지 말지를 다루는 것 직렬/동시는 대기열로 보내진 작업이 여러개의 thread로 갈 것인지, 한개의 thread로 갈 것인지를 다루는 것을 의미한다.
'iOS' 카테고리의 다른 글
[iOS] 디스패치큐(GCD) 사용 시 주의해야할 사항 (0) | 2022.12.11 |
---|---|
[iOS] 디스패치큐(GCD)의 종류와 특성 (메인큐, 글로벌큐, 프라이빗큐) (0) | 2022.12.07 |
[iOS/Swift] Github OAuth - 깃허브 로그인 구현하기 (2) | 2022.10.08 |
iOS 개인정보 처리방침 (0) | 2022.09.25 |
[iOS] Apple developer 개발자 팀 등록 (Certificates, identifiers & Profiles가 나타나지 않을 때) (0) | 2022.04.17 |