왕논의 연구실

iOS에서 UI 변경이 바로 적용되지 않는 이유 본문

iOS/Swift

iOS에서 UI 변경이 바로 적용되지 않는 이유

ywangnon 2025. 5. 9. 22:52
반응형

🌀 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)
// 여전히 "로딩 중..."이 화면에 안 나올 수 있음

이 경우엔 RunLooplayoutSubviews()를 아직 호출하지 않았기 때문에
화면에는 여전히 이전 상태가 보여질 수 있습니다.

해결 방법:

label.text = "로딩 중..."
view.layoutIfNeeded() // 지금 즉시 레이아웃 반영!

✅ 언제 예약되고, 언제 즉시 실행할까?

메서드 동작 방식
setNeedsLayout() 다음 RunLoop에서 레이아웃 업데이트 예약
setNeedsDisplay() 다음 RunLoop에서 draw 호출 예약
layoutIfNeeded() 바로 레이아웃 계산 & 적용
updateConstraintsIfNeeded() 바로 제약 조건 업데이트 실행

🔚 마무리

UIKit은 즉시 반영보다는 예약 기반 처리를 선호합니다.
그 이유는 성능을 고려한 설계 철학 때문이며,
이를 가능하게 하는 게 바로 RunLoop라는 이벤트 루프 시스템입나다.

UI가 바로 안 바뀌는 이유를 정확히 알면,
layoutIfNeeded()updateConstraintsIfNeeded()언제 사용해야 할지 명확해집니다.


📎 참고 자료

반응형