Search

그림으로이해하는 동기(Sync) 비동기(async)의 개념에 대한 가장 직관적인 이해

Inflearn에 있는 [그림으로이해하는]동기(Sync) 비동기(async)의 개념에 대한 가장 직관적인 이해 1, 2강을 정리한 노션입니다.

들어가며

쓰레드가 무엇인가요?
A : 쓰레드는 일을 하는 녀석입니다.
4코어 8쓰레드 -> 일을 하는 녀석이 8개 👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️ 8코어 16쓰레드 -> 일을 하는 녀석이 16개 👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️ 아이폰 11 Pro 6코어 -> 일을 하는 녀석이 12개 👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️👷‍♀️
Plain Text
복사
쓰레드 위에서 작업을 한다는 건 이런 식으로 표현이 가능할 거 같아요.
짧은 Task를 수행중인 Thread 1
위의 그림에서는 Task 수행 시간이 짧아서 쓰레드 1번에서 여러가지 일을 계속 시켜도 우리는 분산처리를 시켜야겠다고 느끼지 않게 됩니다.
  : 만약 각각의 Task의 수행 시간이 오래 걸린다면 어떨까요?
우리는 분산 처리를 하고 싶다고 느낄겁니다.
복사집 예시
복사기를 10개 이상을 사두고 비치해둔 복사집. 하지만, 주인이 잘 사용할 줄 몰라서 주구장창 한 대에만 복사를 진행하는 상황이라고 가정해보자.
  : 힘들어!!!!!
한 대의 복사기는 무진장 힘이 들겁니다. 우리는 다른 작업물을 다른 복사기로 보내서 다른 복사기들도 일을 하도록 처리하고 싶다는 생각이 들기 시작합니다.
  이 개념을 바탕으로 동기, 비동기 개념을 이해하기 된다면 이해가 더 쉬워질 거예요!
만약 쓰레드가 여러 개 존재하는 우리 핸드폰, 컴퓨터에서 쓰레드 한 개만을 계속해서 사용하면서 Task를 수행한다면 이런 생각이 들겁니다.
일을 다른 쓰레드로 보내서 분산처리 하고 싶다.
이를 정확한 용어로는 ‘동시적 처리'라고 하는데, Concurrency, Concurrent한 프로그래밍을 뜻합니다.
이렇게 다른 쓰레드로 Task를 분산처리하는 전체적인 개념에 대해서 알아봅시다!

Synchronous(동기) VS Asynchronous(비동기)

비동기 개념
실제로 분산 처리를 하는 개념으로 다른 쓰레드로 Task를 보냅니다.
작업 순서
1. Thread 1에서 다른 Thread로 작업을 보냅니다.
2. 작업을 보내고 나서 바로 return 합니다.(즉시 리턴)
3. 원래 작업이 있던 곳에 작업이 비게 됩니다.
4. 빈 자리는 다음 작업이 채우게 됩니다.(다음 작업 Task2를 진행)
1번 쓰레드는 다른 쓰레드에서 일을 하도록 시키고 나서 해당 일이 끝나는 것에는 관심을 가지지 않습니다. 원래 작업이 있던 곳을 다른 작업으로 채우고 해당 작업을 처리합니다.
작업을 다른 쓰레드에서 시키고 해당 작업이 끝나는 것을 기다리지 않는 것이 “비동기"입니다.
서버 통신예시
예를 들어서 서버 통신(처리하는 시간 자체가 오래걸리는 작업)을 한다고 가정해봅시다.
서버와 통신을 하게 되면 인터넷을 통해서 서버에 접속하기 때문에 인터넷 환경에 따라서 네트워크가 느려질 수 있습니다.
그 때 비동기 개념을 만나게 됩니다.
일을 시작 시키고, 작업이 끝날때까지 “안 기다린다”
일을 끝나는 걸 기다리지 않기 때문에 서버 통신을 하는 동안 메인 쓰레드(1번 쓰레드)는 다른 일을 처리할 수 있게 됩니다.
동기 개념
Task가 완료될 때까지 기다립니다.
작업 순서
1. Thread 1에서 다른 Thread로 작업을 보냅니다.
2. 1번 작업이 완료될 때까지 Thread는 블락을 하고서 다른 작업을 하지 못하도록 합니다.
3. 해당 작업이 끝나면 return를 하고 다음 작업을 시작합니다.
1번 작업이 완료될 때까지 기다립니다. 이 작업을 끝내야지만 다음 작업을 수행합니다. 따라서, 시작하고 끝나는 시점이 해당 Task와 일치하게 됩니다.
만약 오래 걸리는 작업을 실행하게 된다면?
  : 1번 쓰레드에서는 작업 1(오래 걸리는 작업)을 기다리고 있기 때문에 다른 작업들을 처리하지 못합니다.
“비동기"라는 개념이 일반적으로 필요한 이유는?
대부분 서버와의 통신(네트워크 작업) 때문입니다.

Serial(직렬) VS Concurrent(동시)

직렬 처리
1번 쓰레드에서 하던 작업을 다른 쓰레드로 보내긴 할건데, 다른 하나의 쓰레드로만 보내는 것이 직렬처리
동시 처리
한 개가 아닌 여러 개의 쓰레드로 분산 처리가 이루어 지는 것이 동시처리
*몇 개의 쓰레드로 분산할 지는 시스템이 알아서 결정하게 됩니다.
분산처리 하려는 것이라면 무조건 동시(Concurrent)처리가 무조건 좋아보이는데 왜 직렬(Serial) 처리가 필요할까요?
작업에 순서가 필요할 수도 있기 때문에 직렬 처리가 필요합니다.
당근 마켓
서버를 통해서 이미지를 다운 받아서 가져올 때 이미지 하나하나가 서버와 연결되어서 가져오기 때문에 “독립적이지만 유사한 여러개의 작업"을 처리할 수 있도록 “동시 처리"를 해야 합니다.

비동기(Async)란 말과 동시(Concurrent)란 말이 같은 말인가?

완전히 다른 말입니다.
비동기 : 작업을 보내는 쓰레드에 관련된 개념
1번 쓰레드에서 다른 쓰레드로 보낸 작업을 기다릴지, 무시하고 다른 작업으로 넘어갈지에 관련된 개념
동시 처리: 메인 쓰레드에서 다른 쓰레드로 작업을 보낼 때에 관한 개념
작업을 보내는 쓰레드가 여러 개인가, 아니면 한 개인가

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

예를 들어서, 스크롤이 제대로 일어나지 않는 앱이 존재합니다.
스크롤을 할 때마다 자꾸 버벅거리고 스무스하게 스크롤이 되지 않아요!
왤까요?
앱을 이렇게 진행하고 있어서 그렇습니다.
이미지를 다운로드해서 Cell에 표시하는 작업들을 메인 쓰레드에서만 실행하고 있기 때문!
Plain Text
복사
  메인 쓰레드는 화면을 관리하는 쓰레드(UI 관련)이기 때문에 네트워크와 관련된 개념들을 1번 쓰레드에서 분리시켜서 다른 쓰레드에서 움직이도록 해야 합니다!

마치며

동시성 프로그래밍과 관련된 대부분이 주제들은 성능 / 반응성을 다룹니다. 다른 말로는 앱 최적화에 대해서 다룬다고 얘기할 수 있겠습니다. 일을 다른 쓰레드로 보내서 분산 처리하고 싶다는 개념은 iOS에서는 일반적으로 GCD/Operation을 가지고 처리하고 있습니다.