[GCD] 메인 스레드에서 DispatchQueue.main.sync를 사용하면 안되는 이유

2025. 6. 6. 15:25Swift, iOS Foundation

☑️ 데드락 (Deadlock) 발생 상황을 이해해보자

메인 스레드에서 DispatchQueue.main.sync를 호출할 때 아래와 같은 데드락 (Deadlock, 무한 대기 상태) 에러가 발생합니다.

우선 데드락이 발생하는 아래 코드의 의미를 정확하게 이해해보겠습니다.

  • 별도의 설정을 하지 않으면, 기본적으로 우리의 코드는 메인 스레드 (main)에서 동작합니다. -> 해당 코드도 메인 스레드 위에서 동작 중!
  • DispatchQueue.main : main Queue로 작업을 전달한다는 의미입니다. 메인 큐는 기본적으로 Serial Queue (직렬 큐)이기에 동일한 스레드인 자기자신, 메인 스레드 (main)로 작업 (Task)이 할당되겠군요.
  • sync : 동기적인 작업 (= 작업을 보내고 끝날 때까지 기다림)을 의미합니다.

Thread 1: EXC_BREAKPOINT (code=1, sybcode=...) 에러가 발생한 코드 모습


오케이 그러면 위의 코드는 "메인 스레드에게 내 코드를 메인 큐에서 동기적으로 실행하게 해줘"라고 명령한 내용인데요.

이 상황이 데드락 (Deadlock)으로 이어지는 과정을 살펴보겠습니다.
아래 이미지에서 메인 스레드와 호출 코드가 서로 주고받는 과정을 따라가 보시죠!

서로 영원히 코드가 실행되기만을 기다리는 교착 상태가 이런 흐름으로 발생하는 것이죠.


즉, "아직 끝나지 않은 작업이 있는 직렬 큐에게 끝나야 시작할 수 있는 동기 작업을 요청했기 때문에" 데드락이 발생했습니다.

조금 더 전문적인 어려운 단어로 바꿔서 설명하면,
"아직 반환되지 않은 Task가 있는 SerialQueue에게 동기적으로 Task를 전달했기 때문에" 데드락이 발생했습니다.

📌 결론!
직렬 큐가 처리 중인 상태에서, 그 큐에게 동기적으로 새로운 작업을 요청하면 안 된다!
-> 덧붙이면, 직렬 큐 (main)는 동시에 하나씩만 처리할 수 있어 자기 작업이 끝나야만 다음 작업을 할 수 있는데, 그다음 작업이 자기 자신을 기다리면 멈추는 상황이 발생하는 것이다!

 

 

🤔 그렇다면 DispatchQueue.main.sync는 항상 사용할 수 없는 것인가?

결론부터 말하자면 그렇지 않습니다.
만약 지금 위의 글 부분까지 읽고 "아 그러면 main.sync는 쓰면 안되겠네"라고 이해했다면, 문제상황을 제대로 이해하지 못한 것입니다.

문제는 메인큐에 동기 작업을 호출한 것 자체가 아니라, "메인 스레드에서 메인큐에 동기 작업을 덧붙여 호출한 것"이었거든요.

📌 즉, 메인 스레드가 비어있는 상태라면 sync 상태의 Task를 전달해도 받아 실행할 수 있습니다.


아래와 같은 상황은 DispatchQueue.main.sync 코드를 문제없이 사용하는 상황입니다.
동작 흐름이 어떻게 이루어지는지 따라가볼까요?

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에서 또 다른 동기 호출이 있는지 주의해야할 필요는 있을 것 같네요.
결론! 메인 스레드가 해당 동기 코드를 호출하는 시점에 바쁜 상태인지? 아닌지?를 파악하는 것이 중요합니다.