λ¬Έμ
λΉλ§μ΄νλ 1.4.3 λ²μ μ λ©μΈ νλ©΄μμ μ€ν¬λ‘€ μ λκΉ νμμ΄ λ°μν©λλ€.
1. μ½λμ λ¬Έμ μΌ κ²μ΄λ€.
2. λ λλ§ λ¬Έμ μΌ κ²μ΄λ€.
iOS μ΄ν리μΌμ΄μ μ UI λ λλ§ κ³Όμ μ λν΄μ μμλ³΄κΈ°λ‘ νμ΅λλ€. Render Loop, Hitch λ±λ±μ ν€μλκ° λμ€λκ΅°μ. ν€μλμ λν΄μ μμ보λ μ€ κ΄λ ¨ μλ κ² κ°μ WWDC μΈμ μ΄ λͺ κ° λμμ΅λλ€. μ°μ μμλΆν° λ³΄κΈ°λ‘ νμ΅λλ€.
λ€μ μμμ μ°Ύμ보면 μ’μ κ² κ°μ΅λλ€:
- Explore UI animation hitches and the render loop
- Demystify and eliminate hitches in the render phase
- Find and fix hitches in the commit phase
μμμ μ°Ύμ보면 μκ² μ§λ§ μ°μ Render Loop, Commit Phase, hitch λ±μ κ°λ μ λν΄μ μ΄ν΄ν΄μΌ ν©λλ€.
hitch
hitchλΌλ μ©μ΄μ λν΄μ μ°μ μμλ΄ μλ€.
hitchλΌλ μ©μ΄λ μ€μ κ³ λ¦¬ λͺ¨μμΌλ‘ λ§λ€μ΄ νμΉλ λμμ μλ―Ένλ κ²μΌλ‘ μμλ μ©μ΄λΌκ³ ν©λλ€. λ³΄ν΅ λμ λ¬Άκ±°λ 맀λμ μ§μ λ λ§μ§λ§μ νμ κ½ μ£Όκ² λλλ° μ΄λ¬ν λͺ¨μ΅μ λ°νμΌλ‘ κ°μκΈ° μμ§μ΄λ€, ν± μμ§μ΄λ€λΌλ μλ―ΈμΈ jerkμ λΉμ·ν μλ―Έλ‘ μ°μ΄κΈ° μμν©λλ€.
WWDC μΈμ μ 보면 hitchλΌλ μ©μ΄μ λν μ€λͺ μ λ€μκ³Ό κ°μ΄ νκ³ μμ΅λλ€:
hitchλΌλ κ²μ νλ μ(frame)μ΄ μμλ μκ°λ³΄λ€ μ§μ°λκ² λνλλ μκ°μ μλ―Ένλ κ±°μ£ .
νλ μμ΄ μμλ μκ°μ λνλμ§ μλλ€λ κ²μ μ΄λ€ κ²μ μλ―Ένλ κ²μΌκΉμ? μμ΄ν°μ μ£Όμ¬μ¨μ 60Hzμ λλ€. Hz(Refresh Rate, μ£Όμ¬μ¨)μ 1μ΄μ νλ©΄μ λͺ λ² κ°±μ ν μ μλμ§μ λν μμΉμ λλ€. μ°λ¦¬μ ν΄λν°μ μκ°μ νλ¦μ λ°λΌμ 보μ¬μ£Όμ΄μΌ ν νλ©΄μ μκ°, μ¦ νλ μμ μ΄λ° μ λ° μ²λ¦¬λ₯Ό ν΅ν΄ μ€λΉν©λλ€.
μλ₯Ό λ€μ΄μ, ν립λΆμ λ μ¬λ €λ³ΌκΉμ?
μ λλ©μ΄μ μ²λΌ 보μ΄κ² νλ €λ©΄:
- μμ§μμ΄ μ΄μ΄μ§λ κ·Έλ¦Όμ μμ, μλ°±μ₯ μ€λΉνλ€.
- μμμ λ§μΆ° κ·Έλ¦Όμ μλλ€.
- ν μ₯μ© λΉ λ₯΄κ² λκΈ΄λ€.
μμ κ°μ κ³Όμ μΌλ‘ μ μ μΈ κ·Έλ¦Όμ΄ μμ§μ΄λ μ λλ©μ΄μ μ²λΌ 보μ΄κ² λλ κ²μ΄μ£ . ν΄λν°λ λ§μ°¬κ°μ§μ λλ€. ν μ₯μ κ·Έλ¦Όμ΄ νλμ νλ μκ³Ό λμλλ κ±°μμ. μμ΄ν°μ μ£Όμ¬μ¨μ΄ 60HzλΌκ³ νμΌλκΉ 1μ΄μ 60μ₯μ© κ·Έλ¦Ό(νλ μ)μ λΉ λ₯΄κ² 보μ¬μ£Όκ² λλ κ²μ λλ€.
κ·Έλ°λ° λ§μ½μ μμκ° μ ν΄μ Έ μλ κ·Έλ¦Ό(νλ μ)μμ μ€κ°μ λͺ μ₯μ© μ€λΉκ° λ¦μ΄μ§κ±°λ λΉ μ Έμ νμλ₯Ό λͺ»νκ² λλ©΄, λ§€μ° λΆμμ°μ€λ¬μ΄ μ λλ©μ΄μ μ΄ λ³΄μ¬μ§κ² μ£ . μ€μ λ‘ iOSμμλ νλ μμ μ€λΉνλ λ¨κ³κ° λ³λλ‘ μ‘΄μ¬νλλ° μ΄λ€ μ΄μ λ‘ μΈν΄μ νλ μ μ€λΉκ° μ λ λμ§ μμΌλ©΄ νλ©΄μ νμν μ μμ΄μ λΆμμ°μ€λ¬μ΄ μ λλ©μ΄μ (λκΉ νμ)μ΄ λ°μνκ² λ©λλ€.
Render Loop: νλ μ μ€λΉλλ λ¨κ³, λ·°κ° κ·Έλ €μ§λ λ¨κ³
μμμ μ΄μΌκΈ°ν νλ μμ μ€λΉνλ λ¨κ³λ₯Ό Render LoopλΌκ³ ν©λλ€.
μ±μ μ¬μ©νλ€λ³΄λ©΄ μ λ§ λ€μν μ΄λ²€νΈκ° λ°μν©λλ€. μ΄λ²€νΈ μ€μλ μ¬μ©μμ μνΈμμ©νλ μ΄λ²€νΈκ° μμ£ . κ·Έ μ€μλ ν°μΉ μ΄λ²€νΈλ μμ΅λλ€. κ°λ Ή λ²νΌμ λλ¬μ νλ©΄μ μλ λ·°λ₯Ό μμ§μ΄λ μν©μ΄λΌκ³ μκ°ν΄λ΄ μλ€. κ·Έ μκ°μ ν°μΉ μ΄λ²€νΈκ° μ±μΌλ‘ μ λ¬λκ³ , λ€μ UIμ λν λ³κ²½ μ¬νμ΄ μ μ©λ©λλ€. μ΄λ»κ² μμ§μ¬μΌ ν μ§, μ΅μ’ μ μΌλ‘λ λ·°κ° μ΄λ€ μμΉμ μμ΄μΌ ν μ§ λ±μ μ λ³΄κ° μ ν΄μ§κ² μ£ ? μ΄λ¬ν μ 보λ₯Ό λ°νμΌλ‘ νλ μμ μμ±μν€κΈ° μν μμ μ νκΈ° μν΄ κ·Έλ° λ΄μ©λ€μ΄ μ΄μ체μ λ‘ μ λ¬λ©λλ€. μ΄λ¬ν κ³Όμ λ€μ΄ μ±μ μ¬μ©νλ λμ μ°μμ μΌλ‘ μ§νλ©λλ€.
λ¨κ³λ λ μΈλΆμ μΌλ‘ λλμ΄μ§λλ°μ.(λ΄λΆμ μΈκ³λ μ΄λ ΅λ€ μ λ§π₯Ή)
ν¬κ² 3κ°μ§μ λ¨κ³κ° λ³λ ¬μ μΌλ‘ μνλ©λλ€:
- App λ¨κ³ : μ΄λ²€νΈκ° μ²λ¦¬λκ³ UIκ° λ³κ²½λλ λ¨κ³
- Render λ¨κ³ : UIκ° μ€μ λ‘ λ λλ§λλ λ¨κ³
- Display λ¨κ³ : νλ μμ΄ νλ©΄μ λμ€νλ μ΄λλ λ¨κ³
λͺ¨λ λ¨κ³κ° μ λΆ μ€μνμ§λ§ κ°μΈμ μΌλ‘ Render λ¨κ³κ° κ°μ₯ μ€μνλ€κ³ μκ°ν©λλ€. λ·°μ κ³μΈ΅ ꡬ쑰, λ μ΄μμ λ±λ±μ μ¬λ¬κ°μ§ μ 보λ₯Ό μ‘°ν©ν΄μ νλ μ(κ·Έλ¦Ό)μ λ§λ€μ΄λ΄λ λ¨κ³λΌκ³ μκ°νλ©΄ λ κ² κ°μμ. μ΄ μν μ λ΄λΉνλ μΉκ΅¬κ° GPU μ λλ€. λ μ΄μ΄ νΈλ¦¬, λ λ μλ² λ±λ± μ¬λ¬ μ©μ΄κ° λ λμ€μ§λ§ κ·Έ λΆλΆμ λν΄μλ μ’ λ μ°Ύμ보면 μ’κ² κ³ , κ²°λ‘ μ μ€μ§μ μΈ κ·Έλ¦Όμ΄ λ§λ€μ΄μ§λ λ¨κ³λΌλ κ²μ λλ€.
κ° λ¨κ³μλ 16.67ms(1μ΄μ 60νλ μμ΄ μ€λΉλκ³ κ·Έλ €μ ΈμΌ νλκΉ 1μ΄λ₯Ό 60μΌλ‘ λλ μμΉ)μ μ νμκ°μ΄ μμ΄μ. μ νμκ°μ μ§ν€μ§ λͺ»νλ©΄ κ·Έ νλ μμ νλ©΄μ 보μ¬μ§μ§ λͺ»νλ κ²μ΄μ£ . (λ§μΉ κ³Όμ λ₯Ό λ§κ° κΈ°ν μμ νμ§ λͺ»νλ λλμ΄λκΉ.. κ΅μλ μ£μ‘ν΄μ..) κ·Έλμ μ μκ° μμ μμ μ μμνλ κ²μ΄ λ§€μ° μ€μνκ² μ£ ?
μκ°μ μ‘°κΈλ§ ν΄λ³΄λ©΄ 'λ¬΄κ±°μ΄ μμ (λΉμ©μ΄ λ§μ΄ λλ μμ )μ΄λ λΆνμν μμ μ μ€μ΄κ±°λ νμ§ μλ κ²μ΄ μ’λ€'λ κ²°λ‘ μ λμΆν΄ λΌ μ μμ΅λλ€.
ν΄κ²° κ³Όμ
μμμ λͺ κ°μ§ κ°λ μ μ΄ν΄λ³΄λ©΄μ 'λ¬΄κ±°μ΄ μμ (λΉμ©μ΄ λ§μ΄ λλ μμ )μ΄λ λΆνμν μμ μ μ€μ΄κ±°λ νμ§ μλ κ²μ΄ μ’λ€'λΌλ κ²°λ‘ μ λμΆνμ΄μ. λ무 λΉμ°ν λ§μΈλ° μ¬μ€ κ°λ°μλ‘μ¨ κ°λ°νλ κ·Έ μκ°μλ μ μΈμ§νμ§ λͺ»νκ³ λ μ κ²½μ μ°κΈ°λ μ°Έ μ΄λ ΅μ£ .. μ¬ννΌ κ·ΈλΌ μ΄λ»κ² λ¬Έμ λ₯Ό ν΄κ²°ν μ μμκΉμ?
- μ€ν¬λ‘€ μ λκΉ νμμ΄ λ°μνλ€.
- μ΄κ²μ΄ hitchλΌλ κ²μ μκ²λμλ€.
- Render Loopμ λ λλ§ λ¨κ³μμ λ¬Έμ κ° μκΈ΄ κ² κ°λ€. (κ°μ )
- λ¬΄κ±°μ΄ μμ μ΄λ λΆνμν μμ λλ¬Έμ λ λλ§ μκ°μ΄ λ§μ΄ 걸리λ κ² κ°λ€. (κ°μ )
μ΄λ¬ν κ³Όμ μΌλ‘ μκ°μ΄ μ κ°λμκ³ , instrumentsλ₯Ό κ°μ§κ³ κ°μ νλ μν©μ΄ μ λ§ λ§λμ§ νμΈν΄λ³΄κΈ°λ‘ νμ΅λλ€.
instruments
Xcode 12λΆν°λ instrumentsμμ Animation HitchesλΌλ ν νλ¦Ώμ μ 곡ν©λλ€.
μμ ν νλ¦Ώμ μ΄μ©ν΄μ λ©μΈνλ©΄μ μ€ν¬λ‘€ λμλ§ μΈ‘μ ν΄λ³΄μμ΅λλ€.
before
λ°μνκ³ μλ hitchμ κ°μκ° 16κ° μ λ μμ΅λλ€.
Main Thread μͺ½μμ μ΄λ€ μΌμ΄ μΌμ΄λκ³ μλμ§ μ΄ν΄λ³΄λ, μ무λλ MainCVC(컬λ μ λ·° μ )μμ μ΄λ―Έμ§λ₯Ό μ€μ ν΄μ£Όλ κ³³μ λ¬Έμ κ° μλ κ² κ°μ΅λλ€. μμ μκ°μ μκ°λ³΄λ€ μμ² μ‘μλ¨Ήκ³ μλ€μ. μ€μ λ‘ μ μμ μ΄λ―Έμ§λ₯Ό μ€μ ν΄μ£Όλ μ½λλ₯Ό μ£Όμ μ²λ¦¬νκ³ μΈ‘μ μ λ€μ ν΄λ³΄λ hitchκ° κ±°μ λ°μνμ§ μλ€μνΌ μ€μ΄λλ κ²μ νμΈν μ μμμ΅λλ€.
κ·ΈλΌ μ΄μ λ μ΄λ―Έμ§ μ€μ λΆλΆλ§ κ°μ μ ν΄μ£Όλ©΄ λ¬Έμ λ ν΄κ²°μ΄ λλ κ±°κ² μ£ ?
μ΄λ―Έμ§ μ€μ
μ± λ΄μμλ μ΄λ―Έμ§ μΊμ± λ° λ€μ΄λ‘λμ Kingfisher λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νκ³ μκ³ , μ΄λ₯Ό ν λ² λνν΄μ μ΄λ―Έμ§λ₯Ό μ€μ ν΄μ£Όκ³ μμμ΅λλ€. λΆλͺ μ΄μ μ μΊμ μ μ± λ μ€μ ν΄μ£Όκ³ λ©λͺ¨λ¦¬ κ°μ κΉμ§ μμΌμ€¬λλ° μ κ·Έλ° κ±ΈκΉμ? ν κ°μ§λ₯Ό λμΉκ³ μκ°νκ³ μμμ΅λλ€.
μ€ν¬λ‘€ ν λλ§λ€ μλ§μ μ΄λ―Έμ§ λ€μ΄λ‘λ μμ²μ΄ λ°μνκ³ μμμ΅λλ€.
λμ€νλ μ΄ λλ μ μ νν΄μ μ΄λ―Έμ§ λ€μ΄λ‘λ μμ μ μννκ³ , κ·Έ μΈμ μ μ λν΄μλ λ€μ΄λ‘λλ₯Ό μ·¨μνλ μμ λ νμνμ΅λλ€. λν κ°μ μμ²μ λν΄μλ μ€λ³΅μΌλ‘ μμ μ μνν νμλ μμμ£ . Kingfisherλ₯Ό μ¬μ©νκ³ μλ μν©μ΄μ΄μ μ°μ μ μ 곡λλ λ©μλλ νλ‘νΌν°λ₯Ό μ΄μ©ν΄μ ν΄κ²°νκ³ μ νμ΅λλ€.
// Cell
var task: Kingfisher.DownloadTask?
...
func configureFor(plan: PlanViewModel) {
guard let url = URL.decodeURL(urlString: plan.imageURLString) else {
#if DEBUG
print("invalid url")
#endif
return
}
let processor = DownsamplingImageProcessor(size: .init(width: 500, height: 500))
task = KingfisherManager.shared.retrieveImage(with: url, options: [.processor(processor)]) { [weak self] result in
switch result {
case let .success(r):
self?.imageView.image = r.image
case let .failure(error):
print("error: \(error) or cancelled")
}
}
planId = plan.planId
isScrap = plan.isScraped
homePlanPropertiesView.configureFor(plan: plan)
}
// CollectionView DataSource
func collectionView(
_ collectionView: UICollectionView,
didEndDisplaying _: UICollectionViewCell,
forItemAt indexPath: IndexPath
) {
switch cells[indexPath.section] {
case .homePlanCell:
let cell = collectionView.dequeueCell(HomePlanCell.self, for: indexPath)
cell.task?.cancel()
default:
break
}
}
- Cellμμ μμ μ μλμΌλ‘ μ·¨μν μ μλλ‘ Taskμ λν νλ‘νΌν°λ₯Ό μ μΈν΄μ£Όμμ΅λλ€.
- μ μ Configureνλ λ©μλ λ΄μμ μ΄λ―Έμ§λ₯Ό λ€μ΄λ‘λνλ μμ μ νλ‘νΌν°μ λ΄μμ£Όμμ΅λλ€.
- Displayκ° λλ μ μ λν΄μλ λ€μ΄λ‘λκ° μ§ν μ€μΈ μμ μ΄ μμ λ μ·¨μνλλ‘ νμ΅λλ€.
μ 체 μ½λλ₯Ό 첨λΆν μλ μμ§λ§ μμ κ°μ λ°©λ²μ μ΄μ©ν΄μ λ¬Έμ λ₯Ό ν΄κ²°νλ €κ³ νμ΅λλ€.
κ²°λ‘
μ€ν¬λ‘€μ μ λ§ λΉ λ₯΄κ² νλ μν©μμ λͺ¨λ μ μ λν΄ μ΄λ―Έμ§ λ€μ΄λ‘λ μμ μ μννκ² λλ€λ©΄ λ§μ λΆνλ₯Ό μ€ μ λ°μ μκ³ , λ λλ§ μ±λ₯μ΄ μ νλ μ μμ΅λλ€. κ·Έλ κΈ°μ 보μ¬μ§μ§ μλ μ μ λν΄μλ λ€μ΄λ‘λ μμ μ μ·¨μνλ κ²μ΄ νμνλ κ²μ΄μ£ . λΉμ₯μ μ΄λ―Έμ§ μ²λ¦¬μμ λ¬Έμ λ₯Ό λ°κ²¬ν μ μμμ§λ§, μ΄μΈμλ λ λλ§ μ±λ₯μ μν₯μ μ€ μ μλ μΌμ΄μ€λ 무μν λ§μ μ μκΈ°μ μμΌλ‘λ λΉμ·ν λ¬Έμ κ° λ°μνλ©΄ μ°μ instrumentsλ‘ νμΈνλ μ΅κ΄μ λ€μ΄λ©΄ μ’μ κ² κ°μ΅λλ€.
after
μ μλ―Ένκ² hitchμ κ°μκ° μ€μ΄λ κ²μ νμΈν μ μμ΅λλ€. λΉλ§μ΄νλ 1.4.4 λ²μ μ λ€μ΄λ°μ λ©μΈνλ©΄μ μ€ν¬λ‘€ν΄λ³΄λ©΄ λΆλλ½κ² μ€ν¬λ‘€λλ κ²μ νμΈνμ€ μ μμ΅λλ€.
## λ§ν¬
https://github.com/taekki-labs/note/wiki/Commit-Hitch-%EC%A0%9C%EA%B1%B0%ED%95%98%EA%B8%B0
'π iOS & Swift' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[iOS] μ΄λ―Έμ§ μμ² μ·¨μνκΈ° (0) | 2023.10.26 |
---|---|
[iOS] λ°λμ λμ λ©λͺ¨λ¦¬ μ¬μ©λ 91% κ°μμν€κΈ° (2) | 2023.09.07 |
[Swift] Stored Property vs Computed Property vs Method (2) | 2022.11.04 |
[iOS] λ€νΈμν¬ ν΅μ νΊμ보기λ₯Ό μμνκΈ° μ μ(0) (3) | 2022.11.04 |
[RxSwift] Disposableκ³Ό DisposeBag (0) | 2022.10.26 |