iOS ์ฑ์ด ์คํ๋๋ฉด, ํ๋ฉด์ ๊ณ์ ๋ฐ์ํ๊ณ , ํฐ์น๋ ์ ์ค์ฒ์๋ ๋ถ๋๋ฝ๊ฒ ๋ฐ์ํฉ๋๋ค.
์ด ๋ชจ๋ ๊ฒ์ ์ค์ฌ์๋ ๋ฐ๋ก Main Run Loop๊ฐ ์์ต๋๋ค.
Run Loop๋ ๋ง ๊ทธ๋๋ก '๋ฃจํ(Loop)'์ ๋๋ค.
iOS ๋ด์์ ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ๊ณ ์ฒ๋ฆฌํ๊ณ , UI ์ ๋ฐ์ดํธ๊น์ง ์ ์ดํ๋ ์ค์ฌ ์์คํ ๋ฃจํ์ ๋๋ค.
macOS์ iOS ์ฑ์ ๋ชจ๋ ์ด RunLoop๋ฅผ ์ค์ฌ์ผ๋ก ๋์๊ฐ๋๋ค.
์ฑ์ด ์ผ์ง ์๊ฐ๋ถํฐ ๊บผ์ง ๋ ๊น์ง, ๋ฉ์ธ ์ค๋ ๋์์ ๊ณ์ ์ํํฉ๋๋ค.
์๋๋ RunLoop๊ฐ ํ ๋ฐํด ๋๋ ๊ณผ์ ์ ๋๋ค
UIEvent ๋ฑ์ด ํ์ ์์ฌ ์๋ค๊ฐ ์ฒ๋ฆฌ๋จsetNeedsLayout()์ด๋ setNeedsDisplay()๋ก ์์ฒญ๋ ๋ทฐ ์
๋ฐ์ดํธ๊ฐ ์คํ๋จRunLoop๋ ์ด๋ฒคํธ ๊ฐ์ง โ ์ฒ๋ฆฌ โ UI ์ ๋ฐ์ดํธ ์์๋ก ํ ๋ฐํด๋ฅผ ๋๋๋ค.
๊ทธ๋ฆฌ๊ณ ํ๋ฉด ์ฃผ์ฌ์จ(60Hz, ์ฆ 1์ด์ 60๋ฒ)์ ๋ง์ถฐ UI๋ฅผ ๊ฐฑ์ ํ๋ฉฐ, ์ด ๊ณผ์ ์์ ๋ถ๋๋ฌ์ด ์ฌ์ฉ์ ๊ฒฝํ์ ๋ณด์ฅํฉ๋๋ค.
RunLoop๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฑ์ด ์ข ๋ฃ๋๊ฑฐ๋, ๋ช ์์ ์ผ๋ก ์ค๋จ๋ ๋๊น์ง ์คํ๋ฉ๋๋ค.
์ด๋ฒคํธ ์์ค(ํ์ด๋จธ, ์ ๋ ฅ ๋ฑ)๊ฐ ์์ผ๋ฉด ๋๊ธฐ ์ํ๋ก ์ ํ๋์ง๋ง, ๋ฉ์ธ ์ค๋ ๋์์๋ ์์คํ ์ด ์ด๋ฅผ ์๋ ๊ด๋ฆฌํ๋ฏ๋ก ๊ฐ๋ฐ์๊ฐ ์ข ๋ฃ๋ฅผ ๊ฑฑ์ ํ ์ผ์ ๊ฑฐ์ ์์ต๋๋ค.
iOS ์ฑ์์ Main Run Loop๋ ๋ฉ์ธ ์ค๋ ๋์์ ์๋ํฉ๋๋ค.
DispatchQueue.main์ด๋ UIApplicationMain()์ด ์คํ๋๋ฉด ๋ฉ์ธ ๋ฃจํ๊ฐ ์์๋ฉ๋๋ค.
let runLoop = RunLoop.main
runLoop.run() // ๋ฃจํ๋ฅผ ์๋์ผ๋ก ๋๋ฆด ์๋ ์์
RunLoop๋ ๋ค์ ๋ phase ์ค ํ๋์์ UI๋ฅผ ์ ๋ฐ์ดํธํฉ๋๋ค:
layoutSubviews()๋ draw(_:) ํธ์ถ.๋ฐ๋ผ์ setNeedsLayout()์ด๋ setNeedsDisplay()๋ ์ฆ์ UI๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ , Run Loop์ ๋ค์ ์ฌ์ดํด์์ ์ฒ๋ฆฌ๋ฉ๋๋ค.
UI๋ฅผ Main Run Loop๋ก ๊ทธ๋ ค๋ด๋๋ฐ, ์ด ์์ ์ ๋ฉ์ธ ์ค๋ ๋์์ ์ด๋ค์ง๋๋ค. ๊ทธ๋ฐ๋ฐ UI๊ฐ ๋ฉ์ถ๊ฑฐ๋ ๋๊ธด๋ค๋ฉด ๋๋ถ๋ถ ๋ฉ์ธ ์ค๋ ๋๊ฐ ๊ณผ๋ํ ์์ ์ผ๋ก ๋ฐ๋น ์ RunLoop๋ฅผ ์ ๋๋ก ๋๋ฆฌ์ง ๋ชปํ ๋ ๋ฐ์ํฉ๋๋ค.
RunLoop์ ํ๋ฆ์ ๋ฐฉํดํ์ง ์๋๋ก, ๋ฌด๊ฑฐ์ด ์์ (๋คํธ์ํฌ ํต์ ๋ฑ)์ ๋ฐ๋์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋์์ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค.
DispatchQueue.global(qos: .background).async {
// ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๋คํธ์ํฌ or ์ฐ์ฐ
let result = heavyWork()
// ๋ค์ ๋ฉ์ธ ์ค๋ ๋์์ UI ์
๋ฐ์ดํธ
DispatchQueue.main.async {
self.label.text = result
}
}
async/await)Task {
let data = await fetchHeavyData()
self.updateUI(with: data)
}
์ด ๊ธ์์๋ iOS ์ฑ์ ์ค์ฌ์ธ Main Run Loop์ ๊ทธ ์๋ ์๋ฆฌ, ๊ทธ๋ฆฌ๊ณ ์ฑ๋ฅ ์ ํ ๋ฌธ์ ๊น์ง ์ดํด๋ณด์์ต๋๋ค.
์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค!