<h1><center> SwiftUI View Rendering (1) </center></h1> ###### title: `SwiftUI View Rendering` ###### tags: `๐Ÿ’ป TIL`, `SwiftUI`, `View Rendering` ###### date: `2023-11-14T10:39:33.284Z` > [color=#724cd1][name=๋ฐ๋ฆญ] > [SwiftUI View Lifecycle - Vadim Bulavin](https://www.vadimbulavin.com/swiftui-view-lifecycle/) > [Thinking in SwiftUI](https://www.objc.io/books/thinking-in-swiftui/) > [The SwiftUI render loop - Rens Breur](https://rensbr.eu/blog/swiftui-render-loop/) > [Exploring SwiftUI 3: View Hierarchies and State Updates - Benedict Quinn](https://blog.scottlogic.com/2020/01/28/Exploring-SwiftUI-3-View-Updates.html) > [Understanding View Rendering Cycle in SwiftUI - azamsharp(YouTube)](https://www.youtube.com/watch?v=imiKAwYTX6s) > [SwiftUIโ€™s relationship to UIKit and AppKit - WWDC by Sundell](https://wwdcbysundell.com/2019/swiftui-relationship-to-uikit-appkit/) > [Advanced Graphics and Animations for iOS Apps - WWDC NOTES by Federico Zanetello](https://www.wwdcnotes.com/notes/wwdc14/419/) > [๋ธ”๋กœ๊ทธ - Coden](https://velog.io/@ictechgy/SwiftUI%EC%9D%98-View-%EB%A0%8C%EB%8D%94%EB%A7%81%EC%9D%80-%EC%96%B8%EC%A0%9C-%EC%9D%B4%EB%A3%A8%EC%96%B4%EC%A7%80%EB%8A%94%EA%B0%80) ## ๊ฐœ์š” > SwiftUI์˜ View์˜ Rendering ๊ณผ์ •์ด ์–ด๋–ป๊ฒŒ ๋˜๋Š”๊ฐ€? <br> > ์ด ๊ณผ์ •์ด ๊ถ๊ธˆํ•œ ์ด์œ ๋Š” View์˜ UIComponent์˜ ์ƒํƒœ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค, onAppear๊ฐ€ ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. onAppear ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฌด์—‡์ด ์žˆ๋ƒ๋ฉด, ๋‚ด๊ฐ€ ์˜ˆ๊ธฐ์น˜ ๋ชปํ•œ ์ƒํ™ฉ์—์„œ๋„ ํ˜ธ์ถœ์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. UIKit์œผ๋กœ ์ƒ๊ฐํ•ด๋ณด๋ฉด layout์˜ subviews๋ฅผ ๋‹ค์‹œ ๊ทธ๋ ค๋ผ๋Š” ๋ฉ”์„œ๋“œ(setneedslayout, layoutifneeded)๋ฅผ ์‹คํ–‰ ์‹œํ‚ค์ง€ ์•Š์œผ๋ฉด viewWillAppear๊ฐ€ ๋‹ค์‹œ ํ˜ธ์ถœ๋˜๋Š” ์ƒํ™ฉ์€ ์ƒ๊ฐํ•˜๊ธฐ ์–ด๋ ต๋‹ค. <br> - ๊ทธ๋ž˜์„œ ์ผ๋‹จ ์–ด๋–ป๊ฒŒ View Rendering์„ ํ•˜๊ณ  View์˜ Lifetime์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•˜๊ณ ์ž ํ•œ๋‹ค. - ๋„ˆ๋ฌด ๋‚ด์šฉ์ด ๋ฐฉ๋Œ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹œ๋ฆฌ์ฆˆ๋กœ ๋‚˜๋ˆ ์„œ ํ•ด๋‹น ๋‚ด์šฉ์„ ์ž‘์„ฑํ•  ๊ฒƒ์ด๋‹ค. ## UnderStanding SwiftUI Views > UIKit๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ง€๋งŒ, SwiftUI ๋˜ํ•œ ์•ฑ์„ ๋งŒ๋“ค ๋•Œ ๋ผ์ดํ”„ ์‚ฌ์ดํด์„ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ํ•„์ˆ˜์ ์ด๋‹ค. View์— ํ‘œ์‹œ๋˜๋Š” Content๋ฅผ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ์กฐํšŒ์ˆ˜ ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ ๋‹ค. SwiftUI๋Š” UI๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๊ธฐ ์œ„ํ•ด View ๊ทธ๋ž˜ํ”„๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ, ์ƒˆ๋กœ์šด ์ƒํƒœ ๊ฐ’์„ ํ†ตํ•ด ์ƒˆ๋กœ์šด View ๊ทธ๋ž˜ํ”„๊ฐ€ ๊ณ„์‚ฐ๋œ๋‹ค. ๊ทธ ๋‹ค์Œ SwiftUI๋Š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์œ„ํ•ด Rendering ์ž‘์—…์„ ์ง„ํ–‰ํ•œ๋‹ค. > SwiftUI์˜ identity์™€ lifetime์€ SwiftUI์— ์ •์˜๋œ struct์˜ lifetime๊ณผ๋Š” ๋ณ„๊ฐœ๋กœ ๋ถ„๋ฆฌ๋œ๋‹ค. SwiftUI์˜ ViewGraph๋Š” ๋ทฐ์˜ Rendering, non-Rendering ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. **Non-Rendering ๊ณ„์ธต๊ตฌ์กฐ** - Screen์— ํ‘œ์‹œ๋˜์–ด์•ผ ํ•˜๋Š” ํ•ญ๋ชฉ๋“ค์— ๋Œ€ํ•œ ์ •์˜์ด๋‹ค. - SwiftUI๋Š” struct์˜ body๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ View๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค. SwiftUI๋Š” UI์— ๋Œ€ํ•œ ๋ชจ๋“  ์—…๋ฐ์ดํŠธ๋ฅผ Non-Rendering ๊ณ„์ธต ๊ตฌ์กฐ์˜ ์ด์ „ ๋‚ด์šฉ๊ณผ ์ƒˆ๋กญ๊ฒŒ ๋งŒ๋“ค์–ด์ง„ Snapshot์„ ํƒ์ƒ‰ํ•˜์—ฌ ๋ณ€๊ฒฝ๋œ ๋‚ด์šฉ๋“ค์„ ๊ณ„์‚ฐํ•œ๋‹ค. - ๋ณ€๊ฒฝ๋œ ๋‚ด์šฉ์„ ๋น„๊ตํ•˜๊ธฐ ์œ„ํ•ด private AttributeGraph Framework๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. **Rendering ๊ณ„์ธต๊ตฌ์กฐ** - SwiftUI๋Š” Rendering ๊ณ„์ธต๊ตฌ์กฐ๋ฅผ ํ†ตํ•ด ์‹ค์ œ ๊ทธ๋ ค์งˆ ๋ถ€๋ถ„์„ ์ƒ์„ฑํ•˜๊ฒŒ ๋œ๋‹ค. ์ด ๋•Œ, ๊ณ„์ธต๊ตฌ์กฐ์˜ ๋ทฐ์—๋Š” ๊ฐ๊ฐ ๊ณ ์œ ํ•œ ID๊ฐ€ ์žˆ์œผ๋ฉฐ, ๊ฐ ๋ทฐ๋“ค์˜ lifetime์€ Screen์— ํ‘œ์‹œ๋˜๋Š” ๋™์•ˆ์˜ ์‹œ๊ฐ„์„ ๋งํ•œ๋‹ค. > View Body์˜ ํƒ€์ž…์€ ์ „์ฒด ๋ทฐ์˜ ํ•˜์œ„ ๊ทธ๋ž˜ํ”„๋ฅผ Encodingํ•œ๋‹ค. ์•ฑ์˜ root View ๋‚ด body ํƒ€์ž…์„ ๊ฒ€์‚ฌํ•˜๋ฉด ๋ทฐ ์ „์ฒด ๊ณ„์ธต๊ตฌ์กฐ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ```swift import SwiftUI struct ContentView: View { var body: some View { Text("Hello, world") .background(Color.yellow) .font(.title) .dump() } } extension View { func dump() -> Self { print(Mirror(reflecting: self)) return self } } ``` ``` // Mirror for ModifiedContent<ModifiedContent<Text, _BackgroundModifier<Color>>, _EnvironmentKeyWritingModifier<Optional<Font>>> ``` printํ•˜๋ฉด ์œ„์™€ ๊ฐ™์€ ๋‚ด์šฉ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด print์—๋Š” View์— ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๋ณ€ํ˜•๋“ค์ด ํฌํ•จ๋œ๋‹ค. ์ด ๋‚ด์šฉ์€ ์•„๋ž˜์—์„œ ๋‹ค์‹œ ๊ฒ€์ฆํ•œ๋‹ค. ```swift struct ContentView_: View { var body: some View { Group { if true { Color.yellow } else { Text("Impossible") } } .dump() } } ``` ``` // Mirror for Group<_ConditionalContent<Color, Text>> ``` - Text๋Š” ๋ณด์—ฌ์งˆ ์ˆ˜ ์—†์ง€๋งŒ, `_ConditionalContent<Color, Text>`์—๋Š” ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. **NOTE** > `Thinking in SwiftUI`์— ๋”ฐ๋ฅด๋ฉด ํ˜„์žฌ ๋ณด์ด๋Š” ๊ณ„์ธต ๊ตฌ์กฐ๋ณด๋‹ค ๋ทฐ ์ „์ฒด์˜ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ์ธ์ฝ”๋”ฉํ•˜๋ฉด ๋” ํšจ์œจ์ ์ธ ๋น„๊ต๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์ด์ ์ด ์žˆ๋‹ค. ์ „์ฒด ๋ทฐ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ body์˜ ํƒ€์ž…์œผ๋กœ ์ธ์ฝ”๋”ฉํ•˜๋ฉด ๋ทฐ ๊ทธ๋ž˜ํ”„์˜ ํฐ ๋ถ€๋ถ„์ด ๋ฏธ๋ฆฌ ๊ตฌ์„ฑ๋œ๋‹ค. ๋” ๋‚˜์•„๊ฐ€์„œ, SwiftUI์˜ Data Essentials์— ๋”ฐ๋ฅด๋ฉด ๋ทฐ๋Š” ์ž์ฃผ ๋ณต์‚ฌ๋˜๋Š”๋ฐ ์ด ๋•Œ ๋‘ ๊ฐ€์ง€ ์‚ฌํ•ญ์„ ์—ผ๋‘์— ๋‘๊ณ  ๊ฐœ๋ฐœํ•ด์•ผ ํ•œ๋‹ค. - initialization์˜ ๋น„์šฉ์ด ์ ๊ฒŒ ๋“ค๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค. - body ํ•จ์ˆ˜๋Š” side effect๊ฐ€ ์—†๊ฒŒ pureํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค. ์–ด๋–ค ์ถ”๊ฐ€์ ์ธ ์ถ”์ ์ด ํ•„์š”ํ•œ ์ž‘์—…์—†์ด body ๋‚ด์—์„œ ๋‹จ์ˆœํ•˜๊ฒŒ ๋ทฐ๋ฅผ ๋งŒ๋“ค๊ณ  ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค.