<h1><center> iOS interview 7 </center></h1> ###### tags: `๐Ÿ’ป ๋ฉด์ ‘ ์งˆ๋ฌธ` ###### date: `2025-10-1217:21:33.284Z` > [iOS interview](https://github.com/JeaSungLEE/iOSInterviewquestions) ## ๋ชฉํ‘œ ๋ง์„ ๋งŽ์ด ์—ฐ์Šตํ•˜์ž! - concurrency ๋งˆ๋ฌด๋ฆฌ - ๋ฉด์ ‘ ์งˆ๋ฌธ๋ฆฌ์ŠคํŠธ ๋‚˜๋จธ์ง€ ## Level2 ### ์•ˆ์ง„ 10. UIKit์—์„œ ํ…Œ์ด๋ธ” ๋ทฐ(UITableView)์™€ ์ปฌ๋ ‰์…˜ ๋ทฐ(UICollectionView)์˜ ์ฐจ์ด์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? - ํ…Œ์ด๋ธ” ๋ทฐ์™€ ์ปฌ๋ ‰์…˜ ๋ทฐ์—์„œ ์…€์„ ์žฌ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ์™€ ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”. - ํ…Œ์ด๋ธ” ๋ทฐ์™€ ์ปฌ๋ ‰์…˜ ๋ทฐ์˜ ๋ฐ์ดํ„ฐ ์†Œ์Šค(Data Source)์™€ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ(Delegate)์˜ ์—ญํ• ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? - ์ปฌ๋ ‰์…˜ ๋ทฐ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ ˆ์ด์•„์›ƒ(Layout)์˜ ์ข…๋ฅ˜์™€ ํŠน์ง•์„ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”. > UIKit ์ž˜ ๋ชจ๋ฅด๋Š” ์‚ฌ๋žŒ์ด๋ผ.. ์ง„์งœ ์ด ์ฐจ์ด๊ฐ€ ๋ญ”์ง€ ๊ถ๊ธˆํ•ด์„œ ๊ฐ€์ ธ์™”์–ด์š” ํ…Œ์ด๋ธ” ๋ทฐ๋Š” ๋‹จ์ผ ์—ด / ์ปฌ๋ ‰์…˜ ๋ทฐ๋Š” ๋ณต์žกํ•œ UI ํ™œ์šฉ ๊ฐ€๋Šฅ -> ์‚ฌ์‹ค ์ปฌ๋ ‰์…˜ ๋ทฐ๋กœ ๋‹ค ๊ฐ€๋Šฅ ๋‹จ์ˆœํ•œ ๋ฆฌ์ŠคํŠธ์ธ ๊ฒฝ์šฐ, ํ…Œ์ด๋ธ” ๋ทฐ๊ฐ€ ๋” ์ข‹์Œ ํ…Œ์ด๋ธ” ๋ทฐ๋Š” Swipable ์ ์šฉ ๊ฐ€๋Šฅ ์ปฌ๋ ‰์…˜ ๋ทฐ๋Š” ์ ์šฉ ๋ถˆ๊ฐ€๋Šฅ FlowLayout / CompositionalLayout - FlowLayout - ์ง์ ‘ ๊ณ„์‚ฐ ํ•„์š” - ๋„ˆ๋ฌด ์˜ค๋ž˜๋จ - CompositionalLayout - ๋น„์œจ๋กœ Section, Group, Item ์ ์šฉ ๊ฐ€๋Šฅ - ์ด๊ฑธ ๋” ๋งŽ์ด ์“ฐ๊ฑฐ๋ผ 11. ๋ ˆ๊ฑฐ์‹œ MVC ํ”„๋กœ์ ํŠธ๋ฅผ MVVM์œผ๋กœ ์ ์ง„์ ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋ ค๋ฉด ์–ด๋–ค ์ „๋žต์„ ์‚ฌ์šฉํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ๐Ÿ’ก ํžŒํŠธ: ๋ฆฌ์Šคํฌ๋ฅผ ์ตœ์†Œํ™”ํ•˜๋ฉด์„œ ์ ์ง„์ ์œผ๋กœ ์ „ํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•˜์„ธ์š” - ์–ด๋–ค ํ™”๋ฉด๋ถ€ํ„ฐ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„๊นŒ์š”? - ๋ณต์žก๋„๊ฐ€ ๋†’์€ ํ™”๋ฉด vs ๋‹จ์ˆœํ•œ ํ™”๋ฉด, ์–ด๋–ค ๊ธฐ์ค€์œผ๋กœ ์„ ํƒํ•˜๋‚˜์š”? > ๋ณต์žก๋„๊ฐ€ ๋†’์œผ๋ฉด ๋” ๋’ค์— ์ง„ํ–‰ํ•œ๋‹ค > ํ…Œ์ŠคํŠธ๋ฅผ ๋” ๋งŽ์ด ์ž‘์„ฑํ•ด๋ด์•ผํ•œ๋‹ค / ์‚ฌ์šฉ์„ฑ ํ…Œ์ŠคํŠธ๋„ ๋งŽ์ด ํ•ด๋ด๋ผ - ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€๊ฐ€ ๋†’์€ ๋ถ€๋ถ„๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ์ด์œ ๋Š”? > ์™œ ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€๋ฅผ ๊ณ ๋ คํ•ด์•ผ ํ•˜์ง€? - MVC์™€ MVVM์ด ๊ณต์กดํ•˜๋Š” ๊ณผ๋„๊ธฐ์— ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์™€ ํ•ด๊ฒฐ์ฑ…์€? - ๋ฐ์ดํ„ฐ ํ๋ฆ„์˜ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•์€? - ํŒ€์›๋“ค์˜ ํ˜ผ๋ž€์„ ์ตœ์†Œํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์€? - ์•„ํ‚คํ…์ฒ˜ ๋ณ€๊ฒฝ์˜ ์„ฑ๊ณต ์ง€ํ‘œ๋Š” ๋ฌด์—‡์œผ๋กœ ์ธก์ •ํ•˜๋‚˜์š”? > Presentation layer์˜ ์•„ํ‚คํ…์ฒ˜ ๋ณ€๊ฒฝ ์‹œ, ํ…Œ์ŠคํŠธ ์ง„ํ–‰ ๋ฐฉ๋ฒ•์ด ์–ด๋–ป๊ฒŒ ๋˜๋Š”์ง€? > ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ง„ํ–‰ ์‹œ, ๊ธฐ์กด ํ™œ์šฉ ๊ฐ์ฒด์™€ ๋˜‘๊ฐ™๋‹ค๋ฉด ๋„ค์ด๋ฐ ์ฐจ์ด๋ฅผ ์–ด๋–ป๊ฒŒ ๋‘๋Š”์ง€? 14. ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋น„์Šทํ•œ ๋„คํŠธ์›Œํฌ API ํด๋ผ์ด์–ธํŠธ๋ฅผ ํ”„๋กœํ† ์ฝœ๋กœ ์ถ”์ƒํ™”ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ์„ค๊ณ„ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? - ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ํ”„๋กœํ† ์ฝœ ํ™•์žฅ์œผ๋กœ ๊ตฌํ˜„ํ•  ๋•Œ์˜ ์ด์ ๊ณผ ์ฃผ์˜์ ์€? - ํ”„๋กœํ† ์ฝœ ํ™•์žฅ์˜ ๋ฉ”์„œ๋“œ ๋””์ŠคํŒจ์น˜ ๋ฐฉ์‹๊ณผ override ๋ถˆ๊ฐ€๋Šฅํ•œ ์ด์œ ๋Š”? - Associated Type์„ ์‚ฌ์šฉํ•œ ์ œ๋„ค๋ฆญ ํ”„๋กœํ† ์ฝœ์˜ ์žฅ๋‹จ์ ์€? - ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ Mock ๊ฐ์ฒด ์ƒ์„ฑ์ด ์‰ฌ์šด ํ”„๋กœํ† ์ฝœ ์„ค๊ณ„ ๋ฐฉ๋ฒ•์€? <- ์ง„์งœ ๊ถ๊ธˆํ•œ๊ฑด ์ด๊ฑฐ ๐Ÿ’ก > ์•ˆ์ง„ ์ƒ๊ฐ.. > ์˜์กด์„ฑ ์ฃผ์ž…์ด ๊ฐ€๋Šฅํ•œ ํ˜•ํƒœ๋กœ ์„ค๊ณ„ํ•ด์•ผ ํ•œ๋‹ค? > ํ•„์š”ํ•œ ๋‹ค๋ฅธ ๊ฐ์ฒด๋“ค์— ๋Œ€ํ•ด์„œ๋„ Mock์œผ๋กœ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•จ..? - Dependency Injection๊ณผ ํ”„๋กœํ† ์ฝœ์˜ ๊ด€๊ณ„๋Š”? - SwiftUI์˜ View ํ”„๋กœํ† ์ฝœ์ฒ˜๋Ÿผ PAT(Protocol with Associated Type)๋ฅผ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€? - TCA ์“ฐ์„ธ์š”.. TestFeature ์ง€์› ### ํƒœํ˜„ 1. ํ…Œ์ด๋ธ”๋ทฐ๋ฅผ ๋น ๋ฅด๊ฒŒ ์Šคํฌ๋กคํ•  ๋•Œ ์ด๋ฏธ์ง€๊ฐ€ ์ž˜๋ชป๋œ ์…€์— ํ‘œ์‹œ๋˜๋Š” ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜๋‚˜์š”? - ์…€ ์žฌ์‚ฌ์šฉ ๋ฉ”์ปค๋‹ˆ์ฆ˜ > Cell์ด queue(ํ)์—์„œ ๋‹ค์‹œ reuse(์žฌ์‚ฌ์šฉ)๊ฐ€ ๋  ๋•Œ prepareForReuse()๋ฅผ ๊ฑธ์ณ์„œ ์ดˆ๊ธฐํ™”๋ฅผ ํ•œ ํ›„ ๋‹ค์‹œ cellForeRowAt๋ฅผ ํ†ตํ•ด Cell์ด ํ‘œ์‹œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. - ์…€ ์žฌ์‚ฌ์šฉ(Cell Reuse) ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ์ด ๋ฌธ์ œ์™€ ์–ด๋–ค ๊ด€๋ จ์ด ์žˆ๋‚˜์š”? > SwiftUI์—์„œ ๊ธฐ๋ณธ VStack/HStack์—์„œ๋Š” ์žฌ์‚ฌ์šฉ ๊ณ ๋ ค X.. > List๋‚˜ LazyVStack, LazyHStack ๊ฐ™์€ ์นœ๊ตฌ๋“ค์€ ๋‚ด๋ถ€์ ์œผ๋กœ ์•Œ์•„์„œ ์žฌ์‚ฌ์šฉํ•ด์ค๋‹ˆ๋‹ค์š” ๋„ค๋„น ~~5. viewDidLoad์—์„œ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ํ•˜๋ฉด ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‚˜์š”?~~ 8. iOS ์•ฑ์—์„œ ์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection)์€ ์–ด๋–ค ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋‚˜์š”? - ์ถ”์ƒํ™” - ํ™•์žฅ์„ฑ - ๋งŽ์ด๋“ค ์ด์•ผ๊ธฐํ•˜๋Š” DI ๊ฐ€ ๊ฐ€์ง€๋Š” ์žฅ์ ์ด๋‚˜ ๋ชฉ์ ์œผ๋กœ๋Š”, ํ…Œ์ŠคํŠธ ์šฉ์ด / ์œ ์ง€๋ณด์ˆ˜ ์šฉ์ด / ๊ฒฐํ•ฉ ๋‚ฎ์ถ”๊ธฐ ๋“ฑ? - ๊ทผ๋ฐ ์ง„์งœ ์จ๋ณด๊ณ  ๋А๋‚€ ๊ฐ€์žฅ ํฐ ์žฅ์ ์€ - ๋‚ด๋ถ€ ๊ตฌํ˜„ ์—†์ด ํ™œ์šฉ์ด ๊ฐ€๋Šฅํ•ด์ ธ์„œ ๊ตฌํ˜„ ์†๋„๋‚˜ ํŽธ์˜๊ฐ€ ์ข‹๋‹ค? 17. Swift์˜ ๊ณ ๊ธ‰ ์ œ๋„ค๋ฆญ ๊ธฐ๋Šฅ๊ณผ ํƒ€์ž… ์†Œ๊ฑฐ(Type Erasure)์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”. - AnyPublisher 18. iOS ์•ฑ์—์„œ Deep Link์™€ Universal Link์˜ ์ฐจ์ด์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? applinks:app.com ### ํƒœ์œค 8. iOS ์•ฑ์—์„œ ์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection)์€ ์–ด๋–ค ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋‚˜์š”? - ์˜์กด์„ฑ ์ฃผ์ž…์˜ ์„ธ ๊ฐ€์ง€ ์œ ํ˜•(Initializer Injection, Property Injection, Method Injection)์„ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”. init(), ```swift let vc = UserViewController() vc.viewModel = UserViewModel(client: RealAPIClient()) ``` > Property Injection ```swift final class UserService { func fetchUser(using client: APIClient) async throws -> User { // โœ… ๋ฉ”์„œ๋“œ ์ฃผ์ž… try await client.request(.getUser) } } ``` > Method Injection - ์˜์กด์„ฑ ์ฃผ์ž… ์ปจํ…Œ์ด๋„ˆ(Dependency Injection Container)๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? ํŒฉํ† ๋ฆฌ ๊ฐ™์€ ๋†ˆ 14. ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋น„์Šทํ•œ ๋„คํŠธ์›Œํฌ API ํด๋ผ์ด์–ธํŠธ๋ฅผ ํ”„๋กœํ† ์ฝœ๋กœ ์ถ”์ƒํ™”ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ์„ค๊ณ„ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? - ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ํ”„๋กœํ† ์ฝœ ํ™•์žฅ์œผ๋กœ ๊ตฌํ˜„ํ•  ๋•Œ์˜ ์ฃผ์˜์ ์€? ๊ด€๋ฆฌํ•  ๊ณณ์ด ๋งŽ์•„์ง„๋‹ค. Pureํ•œ ๊ณณ์—์„œ๋งŒ ์“ฐ๊ธฐ - ํ”„๋กœํ† ์ฝœ ํ™•์žฅ์˜ ๋ฉ”์„œ๋“œ ๋””์ŠคํŒจ์น˜ ๋ฐฉ์‹๊ณผ override ๋ถˆ๊ฐ€๋Šฅํ•œ ์ด์œ ๋Š”? override - ๊ตฌํ˜„์ฒด๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ๋ถˆ๊ฐ€๋Šฅํ•จ ``` ๊ตฌ๋ถ„ ์ •์˜ ์œ„์น˜ ๋””์ŠคํŒจ์น˜ ๋ฐฉ์‹ ์„ค๋ช… โ‘  ํ”„๋กœํ† ์ฝœ ์š”๊ตฌ์‚ฌํ•ญ protocol ๋ณธ๋ฌธ ๋™์  ๋””์ŠคํŒจ์น˜ ์‹ค์ œ ํƒ€์ž…์ด ์–ด๋–ค ๊ตฌํ˜„์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ๋Ÿฐํƒ€์ž„์— ๊ฒฐ์ • โ‘ก ํ”„๋กœํ† ์ฝœ ํ™•์žฅ ๋ฉ”์„œ๋“œ extension ๋‚ด๋ถ€ (์š”๊ตฌ์‚ฌํ•ญ ์•„๋‹˜) ์ •์  ๋””์ŠคํŒจ์น˜ ์ปดํŒŒ์ผ ํƒ€์ž„์— ๊ฒฐ์ • (์˜ค๋ฒ„๋ผ์ด๋“œ ๋ถˆ๊ฐ€) ``` - Associated Type์„ ์‚ฌ์šฉํ•œ ์ œ๋„ค๋ฆญ ํ”„๋กœํ† ์ฝœ์˜ ์žฅ๋‹จ์ ์€? ```swift protocol DataSource { associatedtype Item func item(at index: Int) -> Item } struct IntSource: DataSource { func item(at index: Int) -> Int { 1 } } struct StringSource: DataSource { func item(at index: Int) -> String { "A" } } let sources: [Any] = [IntSource(), StringSource()] for source in sources { if let intSource = source as? IntSource { print(type(of: intSource.item(at: 0))) // Int (๋Ÿฐํƒ€์ž„์— ํ™•์ธ) } else if let strSource = source as? StringSource { print(type(of: strSource.item(at: 0))) // String } } ``` > ๋Ÿฐํƒ€์ž„์—๋งŒ ์•Œ ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ 20. Swift์—์„œ ํ‚ค ๊ฒฝ๋กœ(Key Path)๋ž€ ๋ฌด์—‡์ด๋ฉฐ, ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋‚˜์š”? > (\.model) - ๋Ÿฐํƒ€์ž„์— ํ‚ค ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์†์„ฑ์— ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ธ๊ฐ€์š”? ์ธ์Šคํ„ด์Šค์—์„œ ์ง์ ‘ ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ•˜๋ฉด, ์†์„ฑ ์ด๋ฆ„์ด ์ฝ”๋“œ์— ํ•˜๋“œ์ฝ”๋”ฉ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ ‘๊ทผํ•  ์†์„ฑ์ด ์ปดํŒŒ์ผ ํƒ€์ž„์— ๊ณ ์ •๋œ๋‹ค. Key Path๋กœ ์ ‘๊ทผํ•œ๋‹ค๋ฉด? ์ ‘๊ทผํ•  ์†์„ฑ์„ ๋Ÿฐํƒ€์ž„์— ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค. (์‚ฌ์‹ค ์ด ๋ง์ด ๋„ˆ๋ฌด ์™€๋‹ฟ์ง€ ์•Š์ง€๋งŒ.. ์•„๋ž˜์™€ ๊ฐ™์€ ์˜ˆ์‹œ๋ฅผ ๋“ค ์ˆ˜ ์žˆ์„ ๋“ฏ) ```swift func getValue<T>(from book: Book, keyPath: KeyPath<Person, T>) -> T { return book[keyPath: keyPath] } let title = getValue(from: book, keyPath: \Book.title) // "์•ˆ๋…•" let price = getValue(from: book, keyPath: \Book.price) // 10000 struct User { var name: String var age: Int } var user = User(name: "TaeYoon", age: 26) let writablePaths: [String: WritableKeyPath<User, Any>] = [ "name": \User.name as! WritableKeyPath<User, Any>, "age": \User.age as! WritableKeyPath<User, Any> ] // โš ๏ธ ์ฃผ์˜: ํƒ€์ž… ์บ์ŠคํŒ…์ด ํ•„์š” (KeyPath๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž… ์•ˆ์ „ ๊ตฌ์กฐ) if let keyPath = writablePaths["age"] { user[keyPath: keyPath] = 27 } print(user.age) // 27 ``` > ์‹ค์ œ ๊ฐ’ ํ• ๋‹น ๋ฐ ๊ฐ€์ ธ์˜ค๋Š”๊ฑด ๋Ÿฐํƒ€์ž„ - ํ‚ค ๊ฒฝ๋กœ์™€ KVO(Key-Value Observing)์˜ ๊ด€๊ณ„๋ฅผ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”. ```swift import Foundation class Person: NSObject { @objc dynamic var name: String init(name: String) { self.name = name } } class ViewController: UIViewController { var person: Person! var observation: NSKeyValueObservation? override func viewDidLoad() { super.viewDidLoad() person = Person(name: "Alice") // โฌ‡๏ธ ์—ฌ๊ธฐ ์ด๋ ‡๊ฒŒ KeyPath๋กœ ์ ‘๊ทผํ•œ๋‹ค observation = person.observe(\.name, options: [.new]) { (person, change) in if let newName = change.newValue { print("Name changed to: \(newName)") } } } deinit { observation?.invalidate() } } ``` https://ahyeonlog.tistory.com/38