작성
·
374
1
안녕하세요. 강의를 보다가 병렬큐에서의 동작 방식은 이해를 했지만 메인큐 즉 serial큐에서의 동작 원리가 정확하게 이해가 되지 않아서 질문을 남깁니다.
1.
메인스레드에서 main.async를 사용하게되면 현재 메인스레드에서 작업중인 태스크를 메인큐로 보냈다가 이걸 다시 메인스레드로 비동기로 할당한다는건데 동작 방식이 결국 후순위로 미룬다는 의미인거 같아서 조금 헷갈리네요.. 메인스레드에서 main.async를 사용한다는 것은 오래 걸리는 작업은 나중에 해~ 이런 의미로 사용하는걸까요? 이러한 동작방식은 defer를 사용하는 것과 유사해보입니다!
2.
DispatchQueue.main.async {
for i in 0..<20 {
print(i)
}
}
//2번 작업
for i in 60..<80 {
print(i)
}
//3번 작업
DispatchQueue.main.async {
for i in 20..<40 {
print(i)
}
}
//4번 작업
for i in 40..<60 {
print(i)
}
이러한 코드를 테스트 했을 때 동작 순서가 2 -> 1 -> 4 -> 3으로 예상을 했습니다.
그 이유는 1번 작업이 메인 큐로 갔을 때 다음 스레드가 진행되고 메인스레드에 2번 작업이 1번작업 뒤에 바로 할당된다고 생각을 했습니다.
하지만 동작 방식은 2 -> 4 -> 1- > 3으로 하는 것을 확인했습니다.
메인 스레드에서 비동기로 호출 했을 때 기존에 메인스레드에 있는 작업들의 동작 속도가 너무 빨라서 메인큐에서 메인스레드로 할당하기 전에 작업이 끝나서 그런건가라고 생각을 하고 sleep을 줘도 순서는 동일했습니다.
다음과 같이 main스레드에서 비동기를 처리하게 되면 파일에 선언된 코드들이 다 순차적으로 실행되고 나중에 비동기로 넘긴 태스크들이 메인스레드에 할당되는 것인지도 궁금합니다.
3. URLSession은 비동기적으로 작동하는 것으로 알고있는데 이것 또한 메인스레드에서 동작하고 있는 것이 맞나요?
혹시 제가 이해한 개념 중 오개념이 있다면 말씀해주시면 감사하겠습니다!
답변 1
1
안녕하세요, doyun0887 님.
1. defer랑 유사하지 않습니다. 미루지 않고, 할당되는 순서대로 동작합니다. (쉽게 개념적으로 생각하시면 됩니다.) main이라는 큐가 있고, 해당 메인큐는 1개의 쓰레드만 가지기 때문에, 일이 할당된 순서대로 동작합니다. 다만, 실험을 해보시면 0.0000 몇초의 차이로 일의 작업이 배치되는 순서의 차이가 있기 때문에 그렇게 보일 뿐입니다. (또한 내부적으로는 운영체제가 전체적으로 일의 배치와 메인큐를 관리하기 때문에, main.async로 할당하면 나중에 할당되는 것처럼 보이지만, 실제로 순서를 장담할 수 없습니다.)
선입선출 방식으로 할당되는 순서대로 동작하기 때문에 순서를 장담할 수 없다는 것이 정답이고, (다만.. 뇌피셜이긴 합니다만 제가 생각했을때) iOS가 15이후로 넘어오면서, DispatchQueue등의 내부 구현 또는 운영체제 단에서 어떤 구현이 조금 바뀐 것 같긴 합니다. 왜냐면, DispatchQueue 등 할당이 전체적으로 살짝 느려진 감이 있습니다. (예전 버전에서 제가 강의에서 설명드리면서 출력해봤던 내용들이 대체적으로 거의 일정하게 순서대로 나오던 것들이... 현재는 조금씩 다르게 나옵니다. 그렇다고 해서 이론적으로 틀렸다는 것이 아니고, 이론적으로 순서를 장담할 수 없던 것들의 대체적인 프린트 순서가 조금씩 바뀌었다는 것입니다.)
2. 위에서 설명드린 내용으로 대체가 될 것 같긴한데, 사실 정확하게 말씀드리면 순서를 장담할 수 없습니다. 2번작업이 4번작업보다 빠르다는 것은 장담할 수 있고(시리얼 - 동기 이기때문), 선입선출이기 때문에 1번이 3번보다 빠르다는 것은 장담할 수 있지만, 1, 2, 3, 4를 섞어놨을때의 순서를 장담할 수없다는 것이 이론적인 내용입니다.
즉, 이론적으로
1 - 2 - 3 - 4 가 나올 수도 있고, (1번째)
2 - 4 - 1 - 3 이 나올 수도 있고, (2번째)
2 - 1 - 4 - 3 이 나올 수도 있고, (3번째)
2 - 1 - 3 - 4 가 나올 수도 있습니다. (4번째)
다만, 이론과는 조금 다르게.. 출력해 보신대로.. 내부 구현, cpu, 플레이그라운드의 등의 환경적인 요건으로 2번째가 대체적으로 많이 출력이 되는 것이라고 보시면 됩니다. (근데 아마 말씀드렸듯이 iOS가 업데이트 되기 전에는 1번째나 3번째도 많이 나왔을 것 같긴합니다.)
다만, 1번 질문도 그렇고 2번 질문도 그렇고.. main.async의 사용법을 오해하고 계신 것 같아 다시 말씀드리지만, 실험해보신 방식대로 동작시키는 일은 없고, 2, 3, 4번 등의 다른 쓰레드에서 끝난 일들(예를 들어 UI작업등) 다시 1번쓰레드로 보내는 것에 주로 사용하기 때문에.. 위의 내용에 너무 시간 끌지 않으셔도 될 것 같다는 생각은 듭니다.. ^^;
3. URLSession은 비동기적으로 다른 쓰레드(2, 3번 등) 에서 동작합니다. (저는 메인쓰레드에서 동작한다고 말씀드린 적이 없고, URLSession의 당연한 취지가 (메인이 아닌) 다른쓰레드에서 동작하도록 만드는 것 입니다. 오래걸리는 작업이기 때문에 메인쓰레드에서 동작시키면 안되는 메서드입니다.) 제 수업 3번섹션 주의해야할 사항등의 수업에서 4분 50초 정도의 내용을 다시 보시면 됩니다.
도움이 많이 되시길 바라며...!
감사합니다. 좋은 주말 되세요 :)