2025. 6. 6. 15:25ㆍSwift, iOS Foundation
☑️ 데드락 (Deadlock) 발생 상황을 이해해보자
메인 스레드에서 DispatchQueue.main.sync를 호출할 때 아래와 같은 데드락 (Deadlock, 무한 대기 상태) 에러가 발생합니다.
우선 데드락이 발생하는 아래 코드의 의미를 정확하게 이해해보겠습니다.
- 별도의 설정을 하지 않으면, 기본적으로 우리의 코드는 메인 스레드 (main)에서 동작합니다. -> 해당 코드도 메인 스레드 위에서 동작 중!
- DispatchQueue.main : main Queue로 작업을 전달한다는 의미입니다. 메인 큐는 기본적으로 Serial Queue (직렬 큐)이기에 동일한 스레드인 자기자신, 메인 스레드 (main)로 작업 (Task)이 할당되겠군요.
- sync : 동기적인 작업 (= 작업을 보내고 끝날 때까지 기다림)을 의미합니다.
오케이 그러면 위의 코드는 "메인 스레드에게 내 코드를 메인 큐에서 동기적으로 실행하게 해줘"라고 명령한 내용인데요.
이 상황이 데드락 (Deadlock)으로 이어지는 과정을 살펴보겠습니다.
아래 이미지에서 메인 스레드와 호출 코드가 서로 주고받는 과정을 따라가 보시죠!
즉, "아직 끝나지 않은 작업이 있는 직렬 큐에게 끝나야 시작할 수 있는 동기 작업을 요청했기 때문에" 데드락이 발생했습니다.
조금 더 전문적인 어려운 단어로 바꿔서 설명하면,
"아직 반환되지 않은 Task가 있는 SerialQueue에게 동기적으로 Task를 전달했기 때문에" 데드락이 발생했습니다.
📌 결론!
직렬 큐가 처리 중인 상태에서, 그 큐에게 동기적으로 새로운 작업을 요청하면 안 된다!
-> 덧붙이면, 직렬 큐 (main)는 동시에 하나씩만 처리할 수 있어 자기 작업이 끝나야만 다음 작업을 할 수 있는데, 그다음 작업이 자기 자신을 기다리면 멈추는 상황이 발생하는 것이다!
🤔 그렇다면 DispatchQueue.main.sync는 항상 사용할 수 없는 것인가?
결론부터 말하자면 그렇지 않습니다.
만약 지금 위의 글 부분까지 읽고 "아 그러면 main.sync는 쓰면 안되겠네"라고 이해했다면, 문제상황을 제대로 이해하지 못한 것입니다.
문제는 메인큐에 동기 작업을 호출한 것 자체가 아니라, "메인 스레드에서 메인큐에 동기 작업을 덧붙여 호출한 것"이었거든요.
📌 즉, 메인 스레드가 비어있는 상태라면 sync 상태의 Task를 전달해도 받아 실행할 수 있습니다.
아래와 같은 상황은 DispatchQueue.main.sync 코드를 문제없이 사용하는 상황입니다.
동작 흐름이 어떻게 이루어지는지 따라가볼까요?
DispatchQueue.global().async { ... } 코드에 의해, 해당 로직은 백그라운드 큐에서 비동기 작업으로 동작합니다.
메인 스레드에서 실행 중이지도 않구요. 앞선 작업이 끝날 때까지 기다렸다가 실행하는 것도 아닙니다 !
이 클로저 (Task) 내부에서는 DispatchQueue.main.sync { ... } 코드 블록에 의해, 백그라운드에서 메인 큐로 작업을 전달합니다.
sync이기 때문에 즉시 실행될거구요. 메인 큐는 해당 작업이 끝날 때까지 기다리고 있어야 합니다.
메인 큐에서 해당 작업 (⭐️을 print하는 거겠죠?)을 실행한 다음, 다시 백그라운드 스레드로 복귀하게 됩니다. 아무 문제가 없네요!
해당 코드와 같은 케이스는 실제 애플리케이션에서도 활용될 수 있습니다.
백그라운드에서 비동기로 네트워크 작업으로 새로운 데이터를 불러온 이후에,
네트워크 결과 데이터를 UI에 즉시 반영하고 싶은 상황에 -> main.sync 블럭으로 작업을 즉시 동기적으로 반영하도록 명령할 수 있죠!
UI를 반드시 메인 스레드에서 동작하도록 해야하는 이유와 관련해서는 아래 글을 참고해주세요 ^__^
[iOS] Swift의 UI 작업은 반드시 Main Thread에서 동작해야한다?
Swift의 UI 작업은 Main Thread에서 동작해야한다!아요 개발하다가 한 번쯤 아래와 같은 보라색 경고를 보신 적이 있을 겁니다.해당 상황의 경우에는,"오직 메인 스레드 (main thread only)에서만 사용할
mini-min-dev.tistory.com
물론 main.sync가 lock 상태인지. 혹은 main.sync에서 또 다른 동기 호출이 있는지 주의해야할 필요는 있을 것 같네요.
결론! 메인 스레드가 해당 동기 코드를 호출하는 시점에 바쁜 상태인지? 아닌지?를 파악하는 것이 중요합니다.
'Swift, iOS Foundation' 카테고리의 다른 글
[WWDC25] 2025 Platforms State of the Union 빠르게 톺아보기 (2) | 2025.06.12 |
---|---|
[Swift] COW (Copy-On-Write) 개념 완전 정복하기 (0) | 2025.06.03 |
[Swift] Swift Equatable 완전 정복하기 (0) | 2025.04.28 |
[iOS] Swift의 UI 작업은 반드시 Main Thread에서 동작해야한다? (0) | 2025.04.07 |
[Swift] some, any 제대로 구분해서 사용하기 (Opaque and Boxed Protocol Types in Swift) (0) | 2025.02.26 |