[Swift] Dispatch Queue

잡담

항상 비동기적으로 처리해줄려고 할 때, 클로저를 쓰거나 Dispatch Queue를 사용해서 global로 작업들을 넣어줬습니다.

그런데, 생각해보니 정확하게 이해하지 못했다고 느꼈어요. 확실하게 알고가자는 의미에서 다시 한 번 학습해봤습니다.

학습 내용

시작하기 전에 먼저 직렬, 병렬, 비동기, 동기부터 확실하게 말씀드리고 넘어가야할 것 같아요.

직렬, 병렬은 영어로 Serial, Concurrent인데 이 부분부터 비동기와 동기랑 뭐가 다른걸까라는 의문점이 생길 수 있어요.

직렬과 병렬은 큐에서의 스레드 배치가 직렬이냐 병렬이냐라고 생각하시면 돼요.

즉, Dispatch Queue에서의 스레드 배치로 생각하시면 됩니다.

그러면, 여기서 그러면 동기와 비동기는?? 라고 생각하실텐데요.

이건 큐 외적으로 스레드의 흐름 자체가 비동기냐 동기냐를 결정하는 거라고 보시면 될 것 같아요!

이제 Dispatch Queue를 잘 조합해서 여러가지 큐 형태에 대해 살펴봅시다.

1. Serial Async

사실 저도 이 부분 때문에 학습한 거에요 ㅋㅋㅋ Serial이면 직렬이고, Async면 비동긴데.. 음.. 직렬에 비동기??

어떻게 동작할지, 예상도 안되더라구요.. 근데 위에서 설명드렸다시피, 큐에서의 스레드 배치가 직렬이고, 비동기는 큐 외적으로 스레드의 흐름 자체가 비동기다! 라고 말씀드렸죠?

말 그대로라고 생각해요. 큐에 들어가는 작업들은 들어온 순서대로 먼저 할당된 일이 끝나야 다음 작업을 실행합니다. 하지만, 큐 이외의 동작들은 큐 안에서의 동작들이 끝나기 전에 동작이 실행 돼요!

흐름은 비동기로 처리되는 거죠! 예를 들어서 보여드릴게요!

let queue = DispatchQueue.init(label: "nice")

queue.async {
    for _ in 0..<3 {
        print("good")
    }
}

queue.async {
    for _ in 0..<3 {
        print("no")
    }
}

for _ in 0..<4 {
    print("잉")
}

이 코드의 결과값이 어떻게 나올 것 같나요??

항상 같은 결과는 아니겠지만, no는 good이 다 출력된 다음에 출력되지만, “잉”의 경우 코드 순서에 상관없이 무작위로 출력됩니다.

2. Concurrent Async

이건 진짜 제가 정말 너무 많이 애용하던 거에요. ^^

사실 상 Dispatch Queue에 대한 개념에 대해 설명할 수 있는 부분은 이 부분 밖에 없을거에요 ㅋㅋㅋ 이렇게 설정해서 쓰면, 큐에 들어간 작업도 병렬처리되고, 스레드의 흐름도 비동기로 처리됩니다.

3. Serial Sync

이건 사실 하나안하나 동작이 동일해서.. 설명을 뺄까하다가 서술하겠습니다.

큐에 들어간 것도 직렬처리고 스레드의 흐름도 동기적으로 처리됩니다.

만약에 쓸 상황이 올 수 있다고도 생각을 하지만, 지금까지 딱히 써본 기억은 없는 것 같습니다.

4. Concurrent Sync

이것도 좀 혼동이 많았는데, 제가 위에서 설명드렸던 걸로는 병렬 큐면 큐 안에 동작들은 병렬로 처리된다고 말씀드렸습니다. 하지만 결과는 Serial Sync와 동일해요.

그 이유에 대해 곰곰히 생각해봤는데, Sync는 동기적 스레드의 흐름이라고 말씀드렸죠? 그래서 아무리 병렬 큐여도 스레드의 흐름 자체가 동기적이기 때문에 먼저 넣은 동작이 끝날 때까지 기다렸다가 다음 동작이 실행되는 겁니다.

let queue = DispatchQueue.global()

queue.sync {
    for _ in 0..<3 {
        print("good")
    }
}

queue.sync {
    for _ in 0..<3 {
        print("no")
    }
}

for _ in 0..<4 {
    print("잉")
}

코드를 보시면, 모든 출력이 순차적으로 출력됩니다. 그러면 여기서 저렇게 해준 것과 안해준 것에 대한 차이가 뭐냐라고 물어보실 수 있는데, 아마도 작업에 할당되는 스레드가 다르다고 말씀드릴 수 있어요.

queue에 들어가는 작업들은 main 스레드가 아닌 다른 스레드에 작업이 할당됩니다.. 저도 뭐.. 그런다고 해서 어떤 차이가 발생하는지 모르겠습니다. 결국 sync면, 동작이 끝날 때까지 기다린다는 소린데.. 흠..

혹시라도 어떤 상황에 Concurrent Sync를 쓰는지에 대해 알고 계신 분이 있다면, 댓글 남겨주세요!