Skip to content

just1103/BookFinder

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

56 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿ“š BookFinder ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ

Google Books API๋ฅผ ํ†ตํ•ด ๋„์„œ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๋ชฉ๋ก/์ƒ์„ธ ํ™”๋ฉด์— ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

  • Deployment Target : iOS 14.0
  • Architecture : MVVM-C
  • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ : RxSwift, SwiftLint / ์˜์กด์„ฑ ๊ด€๋ฆฌ๋„๊ตฌ : SPM
  • ์ฝ”๋”ฉ ์ปจ๋ฒค์…˜, ์ปค๋ฐ‹ ์ปจ๋ฒค์…˜ ๋“ฑ ์ž์„ธํ•œ ๋‚ด์šฉ์€ Wiki๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

Foldering

BookFinder
โ”œโ”€โ”€ App
โ”œโ”€โ”€ Presentation
โ”‚   โ”œโ”€โ”€ SearchListPage
โ”‚   โ”‚   โ”œโ”€โ”€ View
โ”‚   โ”‚   โ””โ”€โ”€ ViewModel
โ”‚   โ””โ”€โ”€ DetailPage
โ”‚       โ”œโ”€โ”€ View
โ”‚       โ””โ”€โ”€ ViewModel
โ”œโ”€โ”€ Model
โ”œโ”€โ”€ Network
โ”‚   โ””โ”€โ”€  Entities
โ”œโ”€โ”€ Protocols
โ”œโ”€โ”€ Extensions
โ”œโ”€โ”€ Utilities
โ””โ”€โ”€ Resources
BookFinderTests
โ””โ”€โ”€ Mock

๋ชฉ์ฐจ

Feature-1. ๋„คํŠธ์›Œํฌ ๋ฐ ๋ชฉ๋ก ํ™”๋ฉด ๊ตฌํ˜„

1-1 ์ฃผ์š” ๊ธฐ๋Šฅ

  • ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒ€์ƒ‰ํ•œ ๋„์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์™€ ๋ชฉ๋ก์œผ๋กœ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • URLSession์„ ํ†ตํ•ด ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. (MockURLSession์„ ํ†ตํ•œ ํ…Œ์ŠคํŠธ ์‹คํ–‰)
  • SearchController์— ๊ฒ€์ƒ‰ํ‚ค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•  ๋•Œ๋งˆ๋‹ค CollectionView๊ฐ€ ์ฆ‰์‹œ ์—…๋ฐ์ดํŠธ๋ฉ๋‹ˆ๋‹ค.
  • ๋ชฉ๋ก ์ตœํ•˜๋‹จ์œผ๋กœ Scrollํ•˜๋ฉด ์„œ๋ฒ„์—์„œ ๋‹ค์Œ ํŽ˜์ด์ง€์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๋„๋ก Pagination์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • iPad ๋“ฑ Wide Screen๊ณผ ๊ฐ€๋กœ/์„ธ๋กœ ๋ชจ๋“œ ์ „ํ™˜์— ๋Œ€์‘ํ•˜๋Š” ๋ฐ˜์‘ํ˜• ๋””์ž์ธ์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. (โœ… ์ถ”๊ฐ€ ๊ตฌํ˜„)
  • ActivityIndicator๋ฅผ ํ†ตํ•ด ๋กœ๋”ฉ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. (โœ… ์ถ”๊ฐ€ ๊ตฌํ˜„)
  • ์ด๋ฏธ์ง€ Cache๋ฅผ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. (โœ… ์ถ”๊ฐ€ ๊ตฌํ˜„)
  • JSONParserTests, MockNetworkProviderTests, NetworkProviderTests๋ฅผ ํ†ตํ•œ ํ…Œ์ŠคํŠธ ๋ฅผ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. (โœ… ์ถ”๊ฐ€ ๊ตฌํ˜„)

*๋ฐฐ๊ฒฝ ๋ฐ ๋ฆฌ๋ทฐ ๋…ธํŠธ ๋“ฑ์€ ๊ด€๋ จ PR "๊ฒ€์ƒ‰ํ‚ค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ๋ฐ›์•„ ๋ชฉ๋ก ํ™”๋ฉด์— ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค."๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

๋ชฉ๋ก ํ™”๋ฉด

1-2 ๊ตฌํ˜„ ๋‚ด์šฉ

1. ๋„คํŠธ์›Œํฌ ๊ตฌํ˜„ ๋ฐ API ์ถ”์ƒํ™”

RxSwift๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์˜จ ๋ฐ์ดํ„ฐ๋Š” Observable ํƒ€์ž…์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๊ณ , ViewModel์—์„œ ViewController์— ์ „๋‹ฌ (Binding)ํ•˜์—ฌ ํ™”๋ฉด์— ๋‚˜ํƒ€๋‚ด๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ ํ™”๋ฉด์— ๋‚˜ํƒ€๋‚ด๋Š” ์ตœ๋ง๋‹จ ์‹œ์ ์—๋งŒ Subscribeํ•˜์—ฌ Stream์ด ๋Š๊ธฐ์ง€ ์•Š๋Š” ๊ตฌ์กฐ๋ฅผ ์œ ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ API๋ฅผ ์—ด๊ฑฐํ˜•์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ, API๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด case๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์—ด๊ฑฐํ˜•์ด ๋น„๋Œ€ํ•ด์ง€๊ณ , ์—ด๊ฑฐํ˜• ๊ด€๋ จ switch๋ฌธ์„ ๋งค๋ฒˆ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ API๋งˆ๋‹ค ๋…๋ฆฝ์ ์ธ ๊ตฌ์กฐ์ฒด ํƒ€์ž…์œผ๋กœ ๊ด€๋ฆฌ๋˜๋„๋ก ๋ณ€๊ฒฝํ•˜๊ณ , URL ํ”„๋กœํผํ‹ฐ ์™ธ์—๋„ HttpMethod ํ”„๋กœํผํ‹ฐ๋ฅผ ์ถ”๊ฐ€ํ•œ APIProtocol ํƒ€์ž…์„ ์ฑ„ํƒํ•˜๋„๋ก ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ์จ ์ฝ”๋“œ์œ ์ง€ ๋ณด์ˆ˜๊ฐ€ ์šฉ์ดํ•˜๋ฉฐ, ํ˜‘์—… ์‹œ ๊ฐ์ž ๋‹ด๋‹นํ•œ API ๊ตฌ์กฐ์ฒด ํƒ€์ž…๋งŒ ๊ด€๋ฆฌํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. MockURLSession์„ ํ†ตํ•œ ๋„คํŠธ์›Œํฌ ํ…Œ์ŠคํŠธ

์•„๋ž˜์˜ ๋ชฉ์ ์„ ์œ„ํ•ด MockURLSession์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ์‹ค์ œ ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•  ๊ฒฝ์šฐ ํ…Œ์ŠคํŠธ์˜ ์†๋„๊ฐ€ ๋Š๋ ค์ง
  • ์ธํ„ฐ๋„ท ์—ฐ๊ฒฐ์ƒํƒœ์— ๋”ฐ๋ผ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ฌ๋ผ์ง€๋ฏ€๋กœ ํ…Œ์ŠคํŠธ ์‹ ๋ขฐ๋„๊ฐ€ ๋–จ์–ด์ง
  • ์‹ค์ œ ์„œ๋ฒ„์™€ ํ†ต์‹ ์„ ํ•˜๋ฉฐ ์„œ๋ฒ„์— ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์—…๋กœ๋“œ๋˜๋Š” Side-Effect๊ฐ€ ๋ฐœ์ƒํ•จ

3. MVVM-C ์ ์šฉ

Coordinator๋ฅผ ํ†ตํ•ด ์˜์กด์„ฑ ์ฃผ์ž…์„ ๊ด€๋ฆฌํ•˜๊ณ , ํ™”๋ฉด์ „ํ™˜ ์—ญํ• ์„ ์ „๋‹ดํ•˜๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด navigationController๋ฅผ ์ƒ์„ฑ์ž ์ฃผ์ž…์œผ๋กœ ํ•˜์œ„ ChildCoordinator์— ์ „๋‹ฌํ•˜๊ณ , ํ™”๋ฉด์ „ํ™˜ ์‹œ ํ•ด๋‹น navigationController๊ฐ€ ๋‹ค์Œ ํ™”๋ฉด์„ push ํ•˜๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.

4. DiffableDataSource ๋ฐ Snapshot ํ™œ์šฉ

์‚ฌ์šฉ์ž๊ฐ€ ๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•  ๋•Œ๋งˆ๋‹ค ๋ชฉ๋ก์„ ์—…๋ฐ์ดํŠธํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด DiffableDataSource๋ฅผ ํ™œ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. reloadData()๋ฅผ ํ˜ธ์ถœํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฏ€๋กœ CollectionView Cell์ด ์—…๋ฐ์ดํŠธ๋  ๋•Œ๋งˆ๋‹ค ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์ ์šฉ๋˜์–ด UX ์ธก๋ฉด์—์„œ ์œ ๋ฆฌํ•˜๋‹ค๊ณ  ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ RxSwift๋ฅผ ํ†ตํ•ด ViewModel๊ณผ ViewController๋ฅผ Binding ์‹œ์ผœ ์—ญํ• ์„ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž๊ฐ€ ๋ชฉ๋กํ™”๋ฉด์—์„œ ์Šคํฌ๋กค์„ ์ตœํ•˜๋‹จ์œผ๋กœ ๋‚ด๋ฆฌ๋ฉด, ViewModel์€ ์„œ๋ฒ„๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ณ , ViewController๋Š” Snapshot์„ applyํ•˜์—ฌ ํ™”๋ฉด์„ ๋‹ค์‹œ ๊ทธ๋ฆฌ๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.

5. ActivityIndicator ๊ด€๋ จ Delegate ํŒจํ„ด ์ ์šฉ

์„œ๋ฒ„ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๋™์•ˆ ๋กœ๋”ฉ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด ActivityIndicator๋ฅผ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ActivityIndicator๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์‹œ์  (ex. ๋ชฉ๋ก ์ตœํ•˜๋‹จ์œผ๋กœ Scrollํ•˜์—ฌ ๋‹ค์Œ ํŽ˜์ด์ง€๋ฅผ ๋‚˜ํƒ€๋‚ผ ์‹œ์  ๋“ฑ)์€ ViewModel์ด ์•Œ๊ณ  ์žˆ์œผ๋ฏ€๋กœ ViewController๋ฅผ delegate๋กœ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ViewModel์—์„œ delegate๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ActivityIndicator์— ์ ‘๊ทผํ•  ๊ฒฝ์šฐ Main ์Šค๋ ˆ๋“œ๋ฅผ ํ†ตํ•ด ํ™”๋ฉด์— ๋‚˜ํƒ€๋‚ด์•ผ ํ•˜๋ฏ€๋กœ DispatchQueue๋ฅผ ํ™œ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

6. SearchController๋ฅผ ํ†ตํ•œ ๊ฒ€์ƒ‰์ฐฝ ๊ตฌํ˜„

UISearchController๋ฅผ ํ™œ์šฉํ•˜์—ฌ NavigationBar ๋‚ด๋ถ€์— ๊ฒ€์ƒ‰์ฐฝ์ด ์œ„์น˜ํ•˜๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค. SearchBar ๋Œ€์‹  UISearchController์„ ์‚ฌ์šฉํ•œ ์ด์œ ๋Š” ๋ชฉ๋ก์„ Scrollํ•  ๋•Œ ์ž๋™์œผ๋กœ ๊ฒ€์ƒ‰์ฐฝ์„ ์ˆจ๊ธฐ๊ณ , ๊ฒ€์ƒ‰์ฐฝ์— ํ…์ŠคํŠธ๋ฅผ ์ž…๋ ฅํ•  ๋•Œ ์ž๋™์œผ๋กœ Navigation Title์„ ์ˆจ๊ธฐ๋Š” ๋“ฑ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด๋‹ค ์ง๊ด€์ ์ธ UX๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

1-3 Trouble Shooting

1. SearchBar์— ๊ณต๋ฐฑ์„ ์ž…๋ ฅํ•˜๋ฉด ์„œ๋ฒ„์—์„œ error๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฌธ์ œ

SearchBar์— ๊ณต๋ฐฑ๋งŒ ์ž…๋ ฅํ•˜๋ฉด ํ™”๋ฉด์ด ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์›์ธ์€ API query์— ๋นˆ๋ฌธ์ž ๋˜๋Š” ๊ณต๋ฐฑ๋งŒ ์ „๋‹ฌํ•˜๋ฉด ์„œ๋ฒ„์—์„œ error๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ stream์ด ๋Š๊ธฐ๋Š” ๊ฒƒ์œผ๋กœ ํŒŒ์•…ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ SearchText๊ฐ€ ๋นˆ๋ฌธ์ž์ด๊ฑฐ๋‚˜ ๊ณต๋ฐฑ์œผ๋กœ๋งŒ ๊ตฌ์„ฑ๋œ ๋ฌธ์ž์—ด์ธ ๊ฒฝ์šฐ, ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜์ง€ ์•Š๋„๋ก ์˜ˆ์™ธ ์ฒ˜๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

2. Mock ๋ฐ์ดํ„ฐ ํ™œ์šฉ ์‹œ Bundle์— ์ ‘๊ทผํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ฌธ์ œ

JSON Parsing ํ…Œ์ŠคํŠธ๋ฅผ ํ•  ๋•Œ, Bundle.main.path๋ฅผ ํ†ตํ•ด Mock ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๋„๋ก ํ–ˆ๋Š”๋ฐ, path์— nil์ด ๋ฐ˜ํ™˜๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. LLDB ํ™•์ธ ๊ฒฐ๊ณผ Mock ๋ฐ์ดํ„ฐ ํŒŒ์ผ์ด ํฌํ•จ๋œ Bundle์€ BookFinderTests.xctest์ด๋ฉฐ, ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์ฃผ์ฒด๋Š” App Bundle์ž„์„ ํŒŒ์•…ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ํ˜„์žฌ executable์˜ Bundle ๊ฐœ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” Bundle.main (์ฆ‰, App Bundle)์ด ์•„๋‹ˆ๋ผ, ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์ฃผ์ฒด๋ฅผ ๊ฐ€๋ฅดํ‚ค๋Š” Bundle(for: type(of: self)) (์ฆ‰, XCTests Bundle)๋กœ path๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

3. Wide Screen ๋Œ€์‘ ์‹œ CollectionView Group์˜ itemCount๋ฅผ ์กฐ์ •ํ•˜๋ฉด์„œ Layout์ด ๊นจ์ง€๋Š” ๋ฌธ์ œ

iPad ๋“ฑ Wide Screen์— ๋Œ€์‘ํ•˜๊ธฐ ์œ„ํ•ด Screen Width๊ฐ€ 1000์ด์ƒ์ธ ๊ฒฝ์šฐ CollectionView Group์˜ itemCount๋ฅผ 2๋กœ ์กฐ์ •ํ•œ ์ดํ›„ ์•„๋ž˜์ฒ˜๋Ÿผ Scrollํ•  ๋•Œ imageView๊ฐ€ ์ปค์ง€๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

Layout์ด ๊นจ์ง€๋Š” ํ˜„์ƒ

CollectionView CompositionalLayout์—์„œ estimatedHeight๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ, Cell Constraints๋ฅผ ์„ค์ •ํ•  ๋•Œ Cell์˜ ํฌ๊ธฐ์™€ ๋™์ผํ•˜๊ฒŒ Horizontal StackView๋ฅผ ๋„ฃ๊ณ , imageView width๋ฅผ stackView width * 0.2์œผ๋กœ ์„ค์ •ํ–ˆ์—ˆ๋Š”๋ฐ, ์ด ์กฐ๊ฑด๋งŒ์œผ๋กœ๋Š” imageView์˜ height๊ฐ€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์•„์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋ผ๊ณ  ํŒŒ์•…ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ estimatedHeight๋ฅผ ์œ ์ง€ํ•œ ์ฑ„๋กœ ๊ธฐ์กด Horizontal StackView๋ฅผ ์‚ญ์ œํ•˜๊ณ , imageView์˜ height:width ๋น„์œจ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์•„๋ž˜์ฒ˜๋Ÿผ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค. (Wide Mode์—์„œ group๋‹น itemCount๊ฐ€ 2์ด ๋˜๋ฉด์„œ Cell width๊ฐ€ 1/2์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์— imageView width๊ฐ€ Cell width์˜ 0.2๊ฐ€ ์•„๋‹Œ 0.4๊ฐ€ ๋˜๋„๋ก ์ž‘์—…์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.)

iPhone8 iPhone13 Pro Max iPad Pro 12.9

4. estimatedHeight ์‚ฌ์šฉ ์‹œ ํŠน์ • ๋ฒ„์ „์—์„œ crash ๋ฐœ์ƒ

CompositionalLayout์—์„œ estimatedHeight๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, iOS 15.0 ์ด์ƒ 15.3 ์ดํ•˜ ๋ฒ„์ „์—์„œ crash๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด์— ๋Œ€์‘ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ์ž์˜ ๊ธฐ๊ธฐ ๋ฒ„์ „์ด iOS 15.0~15.3์ธ ๊ฒฝ์šฐ Alert๋ฅผ ๋„์›Œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์—…๋ฐ์ดํŠธ๋ฅผ ๊ถŒํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

5. ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ ํŠน์„ฑ์„ ๊ณ ๋ คํ•˜์—ฌ Model ํƒ€์ž… ๋ฐ UI ๊ตฌ์„ฑ

subtitle, publishedData ๋“ฑ ์ผ๋ถ€ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ˆ„๋ฝ๋œ ๊ฒฝ์šฐ๊ฐ€ ๋นˆ๋ฒˆํ•˜์—ฌ JSON Parsing ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด DTO ํƒ€์ž…์˜ ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ๋ฅผ ์˜ต์…”๋„ ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ด๋ฏธ์ง€ URL ํฌํ•จ ์œ ๋ฌด๋„ ๋ฐ์ดํ„ฐ๋งˆ๋‹ค ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— URL์ด ์—†๋Š” ๊ฒฝ์šฐ ์ž„์˜์˜ SF Symbol ์ด๋ฏธ์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด์–ด ์—๋Ÿฌ ํ™”๋ฉด์œผ๋กœ ์ธ์‹๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค.

Feature-2. ์ƒ์„ธ ํ™”๋ฉด ๊ตฌํ˜„

2-1 ์ฃผ์š” ๊ธฐ๋Šฅ

  • ๊ฒ€์ƒ‰ ๋ชฉ๋ก์˜ ๋„์„œ Cell์„ ํƒญํ•˜๋ฉด ์ƒ์„ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. (โœ… ์ถ”๊ฐ€ ๊ตฌํ˜„)

*๋ฐฐ๊ฒฝ ๋ฐ ๊ตฌ์ฒด์ ์ธ ์ž‘์—… ๋‚ด์šฉ์€ ๊ด€๋ จ PR "๋ชฉ๋ก ํ™”๋ฉด์—์„œ ๋„์„œ Cell์„ ํƒญํ•˜๋ฉด ์ƒ์„ธ ํ™”๋ฉด์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค."๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

์ƒ์„ธ ํ™”๋ฉด

2-2 ๊ตฌํ˜„ ๋‚ด์šฉ

1. DetailCoordinator ์ถ”๊ฐ€ ๋ฐ Delegate ํŒจํ„ด ์ ์šฉ

์ƒ์„ธ ํ™”๋ฉด์€ ๋ชฉ๋ก ํ™”๋ฉด๊ณผ ์—ฐ๊ฒฐ๋˜๋ฏ€๋กœ SeachListCoordinator์˜ childCoordinators์— DetailCoordinator๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด ์ƒ์„ธ ํ™”๋ฉด์ด ํ™”๋ฉด์—์„œ pop๋  ๋•Œ, ViewModel์˜ deinit์—์„œ Coordinator๊ฐ€ finish๋˜๋„๋ก ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. SeachListCoordinator๋ฅผ delegate๋กœ ์ง€์ •ํ•˜๊ณ , removeFromChildCoordinators(coordinator:)๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ DetailCoordinator๋ฅผ childCoordinator์—์„œ ์ œ๊ฑฐํ–ˆ์Šต๋‹ˆ๋‹ค.

Debug Memory Graph๋ฅผ ํ†ตํ•œ ๋””๋ฒ„๊น…์œผ๋กœ Coordinator/ViewModel ๋“ฑ์ด ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ •์ƒ์ ์œผ๋กœ ํ•ด์ œ๋˜๋Š”์ง€ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.

2-3 Trouble Shooting

1. ์ƒ์„ธํ™”๋ฉด์—์„œ ๋ชฉ๋กํ™”๋ฉด์œผ๋กœ ๋Œ์•„๊ฐ€๋ฉด ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ๋ฅผ ์žฌ์š”์ฒญํ•˜๋Š” ๋ฌธ์ œ

์ƒ์„ธ ํ™”๋ฉด์ด pop ๋˜๋Š” ๊ฒฝ์šฐ, ๊ฒ€์ƒ‰์ฐฝ์—์„œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•„๋„ updateSearchResults ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ๋ฅผ ์žฌ์š”์ฒญํ•˜๋ฉด์„œ Scroll์ด ๋งจ ์œ„๋กœ ์ด๋™ํ•˜์—ฌ UX์— ์•…์˜ํ–ฅ์„ ์ฃผ๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ ์ž ViewModel์—์„œ searchText๋ฅผ ์ „๋‹ฌ๋ฐ›์„ ๋•Œ distinctUntilChanged operator๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ผํ•œ ๋ฌธ์ž์—ด์ด ์ „๋‹ฌ๋˜๋ฉด ํ•„ํ„ฐ๋ง๋˜๋„๋ก ์ฒ˜๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

2. ScrollView ๊ด€๋ จ Layout ๋ฌธ์ œ

Horizontal Scroll์ด ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ScrollView์˜ ContentView Width๊ฐ€ ํ™”๋ฉด ํฌ๊ธฐ์™€ ๋™์ผํ•˜๋„๋ก ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  TextView์— ํ…์ŠคํŠธ๊ฐ€ ์ฑ„์›Œ์ง€๋ฉด์„œ Scroll์ด ์•„๋ž˜๋กœ ๋‚ด๋ ค๊ฐ€๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ๋‹ค์‹œ Scroll์„ ๋งจ ์œ„๋กœ ์˜ฌ๋ฆฌ๋Š” ์ž‘์—…์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ณด์™„ํ•  ์ 

  • iPad ๋“ฑ Wide Screen์— ๋Œ€์‘ํ•˜๊ธฐ ์œ„ํ•ด Compositional Layout์˜ columnCount ๊ฐ’์„ ์žฌ์„ค์ •ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. (์™„๋ฃŒ)
  • Quick/Numble์„ ํ™œ์šฉํ•˜์—ฌ ViewModel ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.
  • Clean Swift๋ฅผ ์Šคํ„ฐ๋””ํ•˜๊ณ  ์ ์šฉํ•ด๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

About

MVVM-C, RxSwift

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages