๐ŸŽŸ๏ธ ์„œ์šธ ๋ฌธํ™”์ƒํ™œ ํƒ

Gundy์˜ ์„œ์šธ์‹œ ๋ฌธํ™”ํ–‰์‚ฌ ์ •๋ณด ์•ฑ์ž…๋‹ˆ๋‹ค. ์„œ์šธ๋ฌธํ™”ํฌํ„ธ์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ฌธํ™”ํ–‰์‚ฌ ์ •๋ณด ์˜คํ”ˆ API๋ฅผ ํ†ตํ•ด ๋ฌธํ™” ํ–‰์‚ฌ ์ •๋ณด๋ฅผ ํ…Œ์ด๋ธ” ํ˜•ํƒœ๋กœ ์ œ๊ณตํ•˜๊ณ  ์›ํ•˜๋Š” ์ •๋ณด๋ฅผ ์Šคํฌ๋žฉํ•˜์—ฌ CoreData์— ์ €์žฅํ•˜๋Š” ์•ฑ์ž…๋‹ˆ๋‹ค.

์ฃผ์š” ๊ธฐ์ˆ  ์Šคํƒ

MVVM, Clean Architecture, Core Data, Async/Await, URLSession, Delegate, NotificationCenter

์•ฑ์˜ ๋ชฉํ‘œ

๋‹ค์–‘ํ•œ ์กฐ๊ฑด์œผ๋กœ ํ•„ํ„ฐ๋งํ•˜์—ฌ ํ–‰์‚ฌ ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์›ํ•˜๋Š” ํ–‰์‚ฌ๋ฅผ ์Šคํฌ๋žฉํ•œ๋‹ค.

๐Ÿ“– ๋ชฉ์ฐจ

  1. ํŒ€ ์†Œ๊ฐœ
  2. Diagram
  3. ํด๋” ๊ตฌ์กฐ
  4. ํƒ€์ž„๋ผ์ธ
  5. ์‹คํ–‰ ํ™”๋ฉด
  6. ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ… ๋ฐ ๊ณ ๋ฏผํ•œ ๋ถ€๋ถ„
  7. ์ฐธ๊ณ  ์ž๋ฃŒ

๐ŸŒฑ ํŒ€ ์†Œ๊ฐœ

Gundy
'์˜ค๋Š˜ ๋ญ ํ•˜์ง€?' ํ•  ๋• ๋ฐ”๋กœ ์ด ์•ฑ!

๐Ÿ“Š Class Diagram

Simple

simple

Detail

แ„‰แ…ฅแ„†แ…ฎแ†ซแ„แ…กแ†จ UML

๐Ÿ—‚ File Tree

SeoulCulturalLife
โ”œโ”€โ”€ AppDelegate
โ”œโ”€โ”€ SceneDelegate
โ”œโ”€โ”€ Resource
โ”‚   โ””โ”€โ”€ Info.plist
โ”œโ”€โ”€ Utility
โ”‚   โ”œโ”€โ”€ Extensions
โ”‚   โ”‚   โ”œโ”€โ”€ DateFormatter+
โ”‚   โ”‚   โ”œโ”€โ”€ UIButton+
โ”‚   โ”‚   โ”œโ”€โ”€ UIImage+
โ”‚   โ”‚   โ”œโ”€โ”€ UILabel+
โ”‚   โ”‚   โ””โ”€โ”€ UIStackView+
โ”‚   โ””โ”€โ”€ GlobalConstant
โ”œโ”€โ”€ Entities
โ”‚   โ”œโ”€โ”€ Category
โ”‚   โ”œโ”€โ”€ Gu
โ”‚   โ””โ”€โ”€ Event
โ”œโ”€โ”€ UseCases
โ”‚   โ”œโ”€โ”€ UseCase
โ”‚   โ”œโ”€โ”€ UseCaseDelegate
โ”‚   โ”œโ”€โ”€ ListUseCase
โ”‚   โ””โ”€โ”€ ScrapUseCase
โ”œโ”€โ”€ InterfaceAdapters
โ”‚   โ”œโ”€โ”€ ViewModel
โ”‚   โ”‚   โ”œโ”€โ”€ ViewModel
โ”‚   โ”‚   โ”œโ”€โ”€ ListViewModel
โ”‚   โ”‚   โ””โ”€โ”€ ScrapViewModel
โ”‚   โ”œโ”€โ”€ DataAdapter
โ”‚   โ”‚   โ”œโ”€โ”€ DataAdapter
โ”‚   โ”‚   โ”œโ”€โ”€ JSONDataAdapter
โ”‚   โ”‚   โ””โ”€โ”€ CoreDataAdapter
โ”‚   โ”œโ”€โ”€ DTO
โ”‚   โ”‚   โ”œโ”€โ”€ EventDTO
โ”‚   โ”‚   โ””โ”€โ”€ EventResponseDTO
โ”‚   โ””โ”€โ”€ CoreData
โ”‚       โ””โ”€โ”€ SeoulCulturalLife.xcdatamodeld
โ”‚           โ””โ”€โ”€ SeoulCulturalLife.xcdatamodel
โ”‚               โ””โ”€โ”€ contents
โ””โ”€โ”€ FrameworksAndDrivers
    โ”œโ”€โ”€ ViewController
    โ”‚   โ”œโ”€โ”€ EventsViewController
    โ”‚   โ”œโ”€โ”€ ListViewController
    โ”‚   โ”œโ”€โ”€ ScrapViewController
    โ”‚   โ”œโ”€โ”€ FilterViewController
    โ”‚   โ”œโ”€โ”€ DetailViewController
    โ”‚   โ””โ”€โ”€ EventsTabBarController
    โ”œโ”€โ”€ View
    โ”‚   โ”œโ”€โ”€ ListCell
    โ”‚   โ””โ”€โ”€ ScrapCell
    โ”œโ”€โ”€ NetworkManager
    โ”‚   โ”œโ”€โ”€ APIProvider
    โ”‚   โ”œโ”€โ”€ EventAPIProvider
    โ”‚   โ”œโ”€โ”€ NetworkingError
    โ”‚   โ”œโ”€โ”€ DataFetcher
    โ”‚   โ””โ”€โ”€ NetworkManager
    โ””โ”€โ”€ CoreDataManager
        โ”œโ”€โ”€ EntityManager
        โ”œโ”€โ”€ EventEntityManager
        โ””โ”€โ”€ CoreDataManager

๐Ÿ“† ํƒ€์ž„๋ผ์ธ

๊ฐœ๋ฐœ ๊ธฐ๊ฐ„ 2023๋…„ 9์›” 25์ผ ~ 2023๋…„ 10์›” 4์ผ

๋‚ ์งœ ์ž‘์—…๋‚ด์šฉ
9์›” 25์ผ Entities, UseCases ์ž‘์—…
9์›” 26์ผ ListViewModel ์ž‘์—…
9์›” 27์ผ ListViewController, FilterViewController ์ž‘์—…
9์›” 28์ผ ํ•„ํ„ฐ์˜ UIMenu ์ž‘์—…
9์›” 30์ผ NetworkManager ์ž‘์—…
10์›” 1์ผ DetailViewController ์ž‘์—…
10์›” 2์ผ ScrapViewModel, ScrapViewController ์ž‘์—…
10์›” 3์ผ CoreDataManager, EventsTabBarController ์ž‘์—…
10์›” 4์ผ ์ปจ๋ฒค์…˜ ์ •๋ฆฌ ๋ฐ ๋ฆฌ๋“œ๋ฏธ ์ž‘์„ฑ

๐Ÿ“ฑ ์‹คํ–‰ ํ™”๋ฉด

๋ฆฌ์ŠคํŠธ ํ•„ํ„ฐ ๋ฆฌํ”„๋ ˆ์‹œ
Simulator Screen Recording - iPhone 15 Pro - 2023-10-04 at 12 45 02 Simulator Screen Recording - iPhone 15 Pro - 2023-10-04 at 12 45 52 Simulator Screen Recording - iPhone 15 Pro - 2023-10-04 at 12 46 07
์Šคํฌ๋žฉ ์–ธ์Šคํฌ๋žฉ ํ•˜์ดํผ๋งํฌ
Simulator Screen Recording - iPhone 15 Pro - 2023-10-04 at 12 47 07 Simulator Screen Recording - iPhone 15 Pro - 2023-10-04 at 12 47 34 Simulator Screen Recording - iPhone 15 Pro - 2023-10-04 at 12 48 04

๐ŸŽณ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ… ๋ฐ ๊ณ ๋ฏผํ•œ ๋ถ€๋ถ„

์—ฌ๋Ÿฌ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ทฐ๋ชจ๋ธ

์กฐ๊ฑด ์„ค์ •์„ ์œ„ํ•œ ํ•„ํ„ฐ ํ™”๋ฉด๊ณผ ๊ฒ€์ƒ‰๊ฒฐ๊ณผ๋ฅผ ์กฐํšŒํ•˜๋Š” ํ™”๋ฉด๊ฐ„์˜ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ์„ ์œ„ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ทฐ๋ชจ๋ธ์„ ๊ณต์œ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋•Œ ๋ทฐ์™€ ๋ชจ๋ธ๊ฐ„์˜ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์„ ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ์ข‹์„์ง€ ๊ณ ๋ฏผ์ด์—ˆ์Šต๋‹ˆ๋‹ค. Delegate ํŒจํ„ด์œผ๋กœ ๋ฐ”์ธ๋”ฉ ํ•  ๊ฒฝ์šฐ ๋ทฐ์™€ ๋ทฐ๋ชจ๋ธ์˜ 1:1์˜ ์—ฐ๊ฒฐ๋งŒ์ด ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ์ ์ ˆํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ํด๋กœ์ €๋กœ ์ฃผ๊ณ  ๋ฐ›๋Š” ๋ฐฉ๋ฒ•๋„ ๋ฐฐ์—ด ๋“ฑ์„ ํ†ตํ•ด ๋ทฐ ๋ณ„๋กœ ์›ํ•˜๋Š” ๋ฆฌ์•ก์…˜์„ ์ถ”๊ฐ€ํ•œ๋‹ค๋ฉด ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ๊ฒ ์œผ๋‚˜ ์ž˜ ๊ด€๋ฆฌํ•˜๊ธฐ๋„ ์–ด๋ ต๊ณ  ๋น„ํšจ์œจ์ ์ด๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Notification ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. 1:1๋กœ ์—ฐ๊ฒฐ๋  ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๋Ÿฌ ๋ทฐ๊ฐ€ ๋ทฐ๋ชจ๋ธ์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ณตํ†ต ํŠน์„ฑ์„ ๋ฌถ์–ด ์ค‘๋ณต ์ฝ”๋“œ ์ œ๊ฑฐํ•˜๊ธฐ

UseCase, ViewModel, DataAdapter, EventsViewController, EntityManager ๋“ฑ์€ ๊ณตํ†ต ํŠน์„ฑ์„ ์ •์˜ํ•˜๊ฑฐ๋‚˜ ์š”๊ตฌํ•˜๊ธฐ ์œ„ํ•ด ์ž‘์„ฑํ•œ ํ”„๋กœํ† ์ฝœ ๋ฐ ์ถ”์ƒํ™” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ์ฒ˜์Œ์—๋Š” ๋ชจ๋‘ ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜๊ณ ์ž ๋งˆ์Œ๋จน์—ˆ๊ธฐ ๋•Œ๋ฌธ์— Class Diagram ๋˜ํ•œ ํ”„๋กœํ† ์ฝœ๊ณผ ์ค€์ˆ˜ํƒ€์ž…์œผ๋กœ ๊ตฌ๋ถ„ํ•ด ์ž‘์„ฑํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋‚˜๊ฐ€๋‹ค๋ณด๋‹ˆ ํ”„๋กœํ† ์ฝœ์˜ ๊ธฐ๋ณธ๊ตฌํ˜„๋งŒ์œผ๋กœ๋Š” ์ค‘๋ณต ์ฝ”๋“œ๋ฅผ ์ ์ ˆํžˆ ์ œ๊ฑฐํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•˜์Šต๋‹ˆ๋‹ค. ํด๋ž˜์Šค์˜ ์ƒ์†์ฒด๊ณ„์—์„œ๋Š” ์žฌ์ •์˜์™€ super ํ˜ธ์ถœ์„ ํ†ตํ•ด ๊ธฐ์กด ์ •์˜ ๋ถ€๋ถ„์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ถ”๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์—ˆ๋Š”๋ฐ, ํ”„๋กœํ† ์ฝœ ๊ธฐ๋ณธ ๊ตฌํ˜„์—์„œ๋Š” ๊ทธ๋Ÿฐ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ์„ฑ๋Šฅ์ ์œผ๋กœ๋Š” ํด๋ž˜์Šค๋ณด๋‹ค ๊ตฌ์กฐ์ฒด๋ฅผ ํƒํ•จ์ด ์œ ํšจํ•˜๊ฒ ์ง€๋งŒ ๊ฒฐ๊ตญ ์ฝ”๋“œ๋Š” ์‚ฌ๋žŒ์ด ์ฝ๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆํ•„์š”ํ•œ ์ค‘๋ณต ์ฝ”๋“œ๋ฅผ ์ œ๊ฑฐํ•ด ์ „์ฒด ์ฝ”๋“œ์˜ ๊ธธ์ด๊ฐ€ ์ค„์–ด๋“œ๋Š” ๊ฒƒ์ด ๊ฐ€๋…์„ฑ์— ์ข‹๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋•Œ๋ฌธ์— ๊ทธ๋Ÿฌํ•œ ๊ฒฝ์šฐ ViewModel๊ณผ ๊ฐ™์ด ์ถ”์ƒํ™” ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•˜์˜€์Šต๋‹ˆ๋‹ค.

UINavigationController vs UITabBarController

๋ชฉ๋ก ํ™”๋ฉด๊ณผ ์Šคํฌ๋žฉ ํ™”๋ฉด ๋ชจ๋‘ UINavigationController์™€ UITabBarController๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ์ง€๋…”์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ์ ์€ '์–ด๋–ค ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๊ณ„์ธต ๊ตฌ์กฐ์˜ ์ƒ๋‹จ์— ์œ„์น˜ํ•ด์•ผ ํ•˜๋Š”๊ฐ€'์˜€์Šต๋‹ˆ๋‹ค. ์ฒ˜์Œ์—๋Š” ํƒญ๋ฐ” ์ปจํŠธ๋กค๋Ÿฌ์— ๊ฐ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๊ฐ–๊ณ  ์žˆ๋Š” ๋„ค๋น„๊ฒŒ์ด์…˜ ์ปจํŠธ๋กค๋Ÿฌ๋“ค์„ ๋„ฃ์–ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฐ˜๋Œ€๋กœ ์ตœ์ƒ์œ„์— ๋„ค๋น„๊ฒŒ์ด์…˜ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์žˆ๊ณ  ๊ทธ ์•„๋ž˜์— ํƒญ๋ฐ”์™€ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๋“ค์ด ์žˆ๋‹ค๋ฉด ๋”์šฑ ํšจ์œจ์ ์ธ ๊ตฌ์กฐ๊ฐ€ ๋จ์„ ๊นจ๋‹ฌ์•„ ์ˆ˜์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๊ณ  ํ•ญ์ƒ ๋„ค๋น„๊ฒŒ์ด์…˜ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์ตœ์ƒ์œ„์—ฌ์•ผ ํ•˜๋Š”๊ฐ€? ์ด ์˜๋ฌธ์„ ๋”์šฑ ๊ณ ๋ฏผํ•ด๋ณด๊ณ  ๋‚ด๋ฆฐ ๊ฒฐ๋ก ์€ '๊ตฌ์กฐ์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ๊ฒƒ์ด๋‹ค' ์ž…๋‹ˆ๋‹ค. ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋ชจ๋“  ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๋„ค๋น„๊ฒŒ์ด์…˜ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ•„์š”๋กœ ํ–ˆ๊ณ , ๋„ค๋น„๊ฒŒ์ด์…˜ ์ปจํŠธ๋กค๋Ÿฌ์— pushํ•˜๋Š” ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๊ฐ™๊ณ , ํƒญ๋ฐ”๊ฐ€ ์‚ฌ๋ผ์ง€๊ธธ ์›ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋„ค๋น„๊ฒŒ์ด์…˜ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์ตœ์ƒ์œ„์— ์œ„์น˜ํ•œ ๊ฒƒ์ด ์ ์ ˆํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ pushํ•˜์—ฌ ๋“ค์–ด๊ฐ€๋”๋ผ๋„ ํƒญ๋ฐ”๊ฐ€ ์œ ์ง€๋˜๊ธธ ์›ํ•œ๋‹ค๊ฑฐ๋‚˜, ํƒญ๋ฐ”์˜ ์•„์ดํ…œ ์ค‘ ๋„ค๋น„๊ฒŒ์ด์…˜ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๋“ค์ด ์žˆ๋‹ค๊ฑฐ๋‚˜ ํ•˜๋Š” ๊ฒฝ์šฐ๋ผ๋ฉด ํƒญ๋ฐ”๊ฐ€ ์ตœ์ƒ๋‹จ์— ์œ„์น˜ํ•  ์ˆ˜๋„ ์žˆ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“š ์ฐธ๊ณ  ์ž๋ฃŒ

WWDC

Meet async/await in Swift

Apple Developer Documentation

Concurrency


โฌ†๏ธ ๋งจ ์œ„๋กœ ์ด๋™ํ•˜๊ธฐ