🌀 RunLoop와 예약된 작업 처리
iOS 앱을 개발하다 보면 setNeedsLayout()이나 setNeedsDisplay() 같은 메서드를 쓰는데,
이걸 호출해도 화면이 즉시 바뀌지 않는 경험을 한 번쯤 있습니다..
이 글에서는 왜 즉시 반영되지 않고 '예약'만 되는지, 그리고 그걸 언제 처리하는지
즉, RunLoop가 어떤 역할을 하는지를 정리해보겠습니다.
📌 예약만 하고 바로 안 되는 이유?
UIKit은 성능을 위해 UI 변경 작업을 즉시 처리하지 않고,
한 번에 모아서 처리하는 구조를 사용합니다.
이때 사용하는 시스템이 바로 RunLoop입니다.
🔁 RunLoop란?
RunLoop는 iOS 앱이 실행되는 동안 돌아가는 이벤트 처리 루프입니다.
앱은 항상 RunLoop를 돌며 "터치, 타이머, 네트워크, UI 업데이트" 같은 다양한 이벤트를 처리합니다.
RunLoop가 처리하는 예시들:
- 터치 이벤트
- 타이머 (
Timer) - 네트워크 응답
setNeedsLayout()등의 UI 업데이트 예약- 오토릴리즈 풀 비우기
🔧 예시: setNeedsLayout은 왜 바로 적용되지 않을까?
view.setNeedsLayout()
// 여기선 아무 일도 안 일어남 ❌
위 코드는 단지 "나중에 레이아웃이 필요해"라고 알리는 예약일 뿐입니다.
실제 layoutSubviews()는 RunLoop가 돌아올 때 실행됩니다.
// 다음 RunLoop 사이클에서 실행됨
-> view.updateConstraints()
-> view.layoutSubviews()
-> view.draw()
💡 예약은 왜 필요한가?
UIKit이 이렇게 동작하는 이유는 성능 최적화에 있습니다.
만약 변경마다 즉시 처리한다면?
- CPU 사용량 증가
- 화면 깜빡임
- 애니메이션 끊김
그래서 변경 요청을 하나하나 처리하지 않고, 한번에 묶어서 처리합니다.
이걸 RunLoop가 도와줍니다.
🧪 실전 예시: 즉시 변경이 필요할 때
label.text = "로딩 중..."
view.setNeedsLayout()
sleep(2)
// 여전히 "로딩 중..."이 화면에 안 나올 수 있음
이 경우엔 RunLoop가 layoutSubviews()를 아직 호출하지 않았기 때문에
화면에는 여전히 이전 상태가 보여질 수 있습니다.
해결 방법:
label.text = "로딩 중..."
view.layoutIfNeeded() // 지금 즉시 레이아웃 반영!
✅ 언제 예약되고, 언제 즉시 실행할까?
| 메서드 | 동작 방식 |
|---|---|
setNeedsLayout() |
다음 RunLoop에서 레이아웃 업데이트 예약 |
setNeedsDisplay() |
다음 RunLoop에서 draw 호출 예약 |
layoutIfNeeded() |
바로 레이아웃 계산 & 적용 |
updateConstraintsIfNeeded() |
바로 제약 조건 업데이트 실행 |
🔚 마무리
UIKit은 즉시 반영보다는 예약 기반 처리를 선호합니다.
그 이유는 성능을 고려한 설계 철학 때문이며,
이를 가능하게 하는 게 바로 RunLoop라는 이벤트 루프 시스템입나다.
UI가 바로 안 바뀌는 이유를 정확히 알면,layoutIfNeeded()나 updateConstraintsIfNeeded()를 언제 사용해야 할지 명확해집니다.
📎 참고 자료
'iOS > Swift' 카테고리의 다른 글
| MVVM (Model-View-ViewModel) (0) | 2025.12.05 |
|---|---|
| MVC (Model - View - Controller) (0) | 2025.12.04 |
| ViewModel의 위치? View vs ViewController (0) | 2025.05.07 |
| swift의 소유권 개념 (0) | 2025.04.28 |
| iOS 화면 구성 시 자주 사용하는 Override 함수 정리 (UIView / UIViewController) (0) | 2025.04.19 |