/LeeJunHo

๐Ÿฃ๋ณ„์•ˆ๊ฐ„ 30๊ธฐ ์•„์š” ๊ณผ์ œ ์ƒค์ƒค์ƒฅ ๊ฐ€๋ณด์ž๊ตฌ~~!๐Ÿ˜Ž $์ฝ”๋ฆฌ๋Š”#์–ธ์ œ๋‚˜%ํ™˜์˜!@#$

Primary LanguageSwift

๐ŸฃLeeJunHo๐Ÿฃ

๊นƒํ—ˆ๋ธŒ ์ด์ค€ํ˜ธ

30๊ธฐ iOS ํŒŒํŠธ ์ปค๋ฆฌํ˜๋Ÿผ๐Ÿ

์ฃผ์ฐจ ๋‚ด์šฉ ์„ธ๋ฏธ๋‚˜ PR ์ฐธ๊ณ 
1์ฃผ์ฐจ iOS ๊ฐœ๋ฐœ ์ž…๋ฌธ : Xcode ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•, Layout ๊ธฐ์ดˆ, View ํ™”๋ฉด ์ „ํ™˜ โœ… โœ…
2์ฃผ์ฐจ UI ์„ค๊ณ„ ๊ธฐ์ดˆ(1) : AutoLayout, StackView, TabBarController โœ… โœ…
3์ฃผ์ฐจ UI ์„ค๊ณ„ ๊ธฐ์ดˆ(2) : ScrollView, TableView, CollectionView โœ… โœ…
4์ฃผ์ฐจ ์„œ๋ฒ„ ํ†ต์‹  ๊ธฐ์ดˆ: ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ์ดํ•ด, RESTful API, Alamofire๋ฅผ ํ™œ์šฉํ•œ ์‹ค์Šต โœ… โœ… ๐Ÿ“Œ
5์ฃผ์ฐจ ํด๋ผ์ด์–ธํŠธ ยท ๋””์ž์ธ ํ•ฉ๋™ ์„ธ๋ฏธ๋‚˜ โœ… โœ… ๐Ÿ“Œ
6์ฃผ์ฐจ ํด๋ผ์ด์–ธํŠธ ยท ์„œ๋ฒ„ ํ•ฉ๋™ ์„ธ๋ฏธ๋‚˜ โœ… โœ… ๐Ÿ“Œ
7์ฃผ์ฐจ ์„œ๋ฒ„ ํ†ต์‹  ๋ฐ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ ์‹ฌํ™” : ์„œ๋ฒ„ ํ†ต์‹  ์ถ”๊ฐ€ ์‹ค์Šต โœ… โœ…
8์ฃผ์ฐจ ์•ฑ์žผ์„ ์œ„ํ•œ ํ”„๋กœ์ ํŠธ ๊ธฐ์ดˆ ์„ธํŒ… ๋ฐ ๊ทธ ์™ธ ๊ฟ€ํŒ ์†Œ๊ฐœ

๐ŸŽฏ๋ชฉํ‘œ

  1. MVVM + RxSwift ์—ฐ์Šต
  2. POP ์—ฐ์Šต
  3. Coordinator ์‚ฌ์šฉ
  4. Moya ์„ธํŒ… : BaseTarget + BaseService
  5. Custom UI Component ๋ถ„๋ฆฌ
  6. ํด๋”๋ง ์™„์„ฑํ•ด๊ฐ€๊ธฐ

โœณ๏ธ 7์ฐจ ๊ณผ์ œ ๋ฐ ๋ชฉํ‘œ ์ ๊ฒ€

โœจ 1์ฐจ ๊ณผ์ œ ~ 4์ฐจ ๊ณผ์ œ๋ฅผ ํ•˜๋ฉฐ ์–ด๋ ค์› ๋˜, ๋˜๋Š” ์ด์Šˆ๋ฅผ ํ•ด๊ฒฐํ–ˆ๋˜ ๋‚ด์šฉ

1~4์ฐจ ๊ณผ์ œ์—์„œ๋Š” ์ธ์Šคํƒ€๊ทธ๋žจ ํด๋ก ์ฝ”๋”ฉ์„ ํ†ตํ•ด ๊ธฐ์ดˆ UI ์ž‘์—… ๋ฐ ๊ฐ„๋‹จํ•œ API ์—ฐ๊ฒฐ ์ž‘์—…์„ ์ง„ํ–‰ํ–ˆ๋‹ค. ๊ฑฐ์˜ ๋ชจ๋“  ๋ถ€๋ถ„์ด ์ด๋ฏธ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์—ˆ๋˜ ๋ถ€๋ถ„์ด์—ˆ๊ธฐ์—, ๊ตฌํ˜„ ์ž์ฒด๋ณด๋‹ค๋Š” ํšจ์œจ์„ฑ ๋ฐ ์ƒˆ๋กœ์šด ๊ธฐ์ˆ  ์Šต๋“์— ๋ชฉํ‘œ๋ฅผ ๋‘์—ˆ๋‹ค. OB๋กœ์„œ iOS ํŒŒํŠธ ๊ณผ์ œ๋ฅผ ๋‘ ๋ฒˆ์งธ๋กœ ํ•˜๋Š” ๊ฒƒ์ด๊ธฐ์— ๋ฃจ์ฆˆํ•ด์ง€์ง€ ์•Š๊ณ  ๋งŽ์€ ๋‚ด์šฉ์„ ์–ป์–ด๊ฐˆ ์ˆ˜ ์žˆ๋„๋ก ์ตœ๋Œ€ํ•œ ๋ชฉํ‘œ๋ฅผ ๋†’๊ฒŒ ์žก์•˜๋‹ค.

์ด๋ ‡๊ฒŒ ์žก์€ ๋ชฉํ‘œ๋“ค์€ 1์ฃผ์ฐจ ์„ธ๋ฏธ๋‚˜๋ถ€ํ„ฐ ReadMe์— ์ ์–ด ๋†“์•˜๊ณ , ํ•ญ์ƒ ๋ถ€์กฑํ•œ ๋ถ€๋ถ„๊ณผ ๋ชฉํ‘œ๋ฅผ ์ƒ๊ธฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค. ๊ฐ๊ฐ์˜ ๋ชฉํ‘œ๋“ค์— ๋Œ€ํ•œ ์„ฑ์ทจ๋„๋ฅผ ์Šค์Šค๋กœ ํ‰๊ฐ€ํ•˜๋ฉฐ ์–ด๋ ค์› ๋˜ ๋‚ด์šฉ, ์ด์Šˆ๋ฅผ ํ•ด๊ฒฐํ–ˆ๋˜ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•˜๋ ค ํ•œ๋‹ค.

1. MVVM + RxSwift ์—ฐ์Šต

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

Rx ์Šคํ„ฐ๋””๋ฅผ ํ•˜๋ฉด์„œ ์ „๋ฐ˜์ ์ธ RxSwift์— ๋Œ€ํ•œ ์ดํ•ด๋„๊ฐ€ ์ดˆ๋ฐ˜์— ๋น„ํ•  ๊ฒƒ ์—†์ด ๋†’์•„์กŒ์œผ๋‚˜, Rx๋ฅผ ํ†ตํ•œ ์„œ๋ฒ„ํ†ต์‹ ์ด๋‚˜ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ์— ๋Œ€ํ•œ ๋ถ€๋ถ„์€ ์•„์ง๊นŒ์ง€ ํฌ๊ฒŒ ์œ ์šฉํ•จ์„ ๋Š๋ผ์ง€ ๋ชปํ•˜๊ณ  ์žˆ๋‹ค. ์ถ”๊ฐ€๋กœ 3์ฐจ ๊ณผ์ œ์—์„œ RxCocoa๋ฅผ ์ด์šฉํ•œ TableView๋ฅผ ๊ตฌ์„ฑํ•ด ๋ณด์•˜๋Š”๋ฐ ์„น์…˜์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด RxDataSource๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋ฉฐ Delegate๋กœ๋Š” Proxy๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„ ๋•Œ๋ฌธ์—, ์•„๋ฌด๋ž˜๋„ DiffableDataSource์™€ CompositionalLayout์„ ์ž˜ ์“ฐ๋Š” ๊ฒƒ์ด ๋” ๋„์›€์ด ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์„ ํ–ˆ๋‹ค. ๋˜ํ•œ Prepare ๋ฉ”์„œ๋“œ๋กœ ์ธํ•ด์„œ DisposeBag์ด ์ž๊พธ ์ดˆ๊ธฐํ™”๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋Š”๋ฐ, ์ด ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ๋Š” ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์— DisposeBag์„ ๋‘๋Š”์ง€, ์…€ ์•ˆ์— DisposeBag์„ ๋‘๋Š”์ง€์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง„๋‹ค๋Š” ์ ์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

RxSwift ๊ธฐ๋ณธ 1ํŽธ : Observable, Observer, Subject

2. POP ์—ฐ์Šต

POP, Protocol-Oriented-Programming๋„ ์‚ฌ์‹ค ์ฒ˜์Œ์—๋Š” ๋ฌด์Šจ ๋ง์ธ์ง€๋„ ์ œ๋Œ€๋กœ ๋ชจ๋ฅด๋ฉด์„œ ์•Œ์•„๋ณด์ž๋Š” ๋Š๋‚Œ์œผ๋กœ ๋ชฉํ‘œ์— ์ ์–ด ๋†“์•˜๋‹ค. ๋ง‰์—ฐํžˆ ๋ชจ๋ฅด๋Š” ๊ฐœ๋…์— ๋Œ€ํ•ด์„œ ์•Œ๊ณ  ์‹ถ๋‹ค๊ณ  ์ƒ๊ฐํ•œ ์ด์œ ๋Š”, GitHub์—์„œ iOS ๊ณ ์ˆ˜๋‹˜๋“ค์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ํ”„๋กœํ† ์ฝœ์„ ์ •๋ง ๋Šฅ์ˆ™ํ•˜๊ฒŒ ๋‹ค๋ฃฌ๋‹ค๋Š” ๋Š๋‚Œ์ด ๋“ค์—ˆ๊ณ , ์ดˆ๊ธฐ์— ํ•œ์ฐฝ ๊ด€์‹ฌ์žˆ์–ด ํ•˜๋˜ ์•„ํ‚คํ…์ณ์—์„œ๋„ ๊ฒฐ๊ตญ Protocol์€ ๊ต‰์žฅํžˆ ์ค‘์š”ํ–ˆ๋‹ค. POP๋Š” ์„ธ๋ฏธ๋‚˜ ๊ณผ์ œ๋ฅผ ํ•˜๋ฉด์„œ, Rx ์Šคํ„ฐ๋”” & ์•„ํ‚คํ…์ณ ๋ฐ ๋””์ž์ธํŒจํ„ด ์Šคํ„ฐ๋””๋ฅผ ํ•˜๋ฉด์„œ ์กฐ๊ธˆ์”ฉ ๊ฐ์ด ์žกํ˜”๋‹ค. ์•„์ง ๋Šฅ์ˆ™ํ•œ ์‚ฌ์šฉ์€ ๋ฉ€์—ˆ์ง€๋งŒ ์ ์–ด๋„ ์™œ Protocol์ด ์ค‘์š”ํ•œ์ง€์— ๋Œ€ํ•ด์„œ๋Š” ๊ฐ์„ ์žก์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์ถ”๊ฐ€์ ์œผ๋กœ ์ด๋ฒˆ ํ•™๊ธฐ์— Java ์ˆ˜์—…์„ ๋“ค์œผ๋ฉด์„œ Interface์™€ Abstract Class๋ฅผ ํ†ตํ•œ ๋””์ž์ธ ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ๋„ ์ข…ํ•ฉ์ ์œผ๋กœ ๋ฐ”๋ผ๋ณผ ์ˆ˜ ์žˆ์–ด์„œ ์ดํ•ด์— ์กฐ๊ธˆ ๋„์›€์ด ๋˜์—ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค.

๊ทธ๋ž˜์„œ ํ”„๋กœํ† ์ฝœ์€, ๋ชจ๋“ˆ ๊ฐ„ ์˜์กด์„ฑ์„ ๋‚ฎ์ถฐ์ฃผ๊ณ (์œ ๋‹› ํ…Œ์ŠคํŒ…์ด ์‰ฌ์›Œ์ง) ํŠน์ • ํด๋ž˜์Šค์— ๋Œ€ํ•œ ์ฒญ์‚ฌ์ง„์„ ์ œ๊ณตํ•˜๋ฉฐ, ํ˜‘์—… ์‹œ์—๋„ ์ฝ”๋“œ์˜ ๊ตฌ์กฐ๋ฅผ ์‚ดํŽด๋ณด๊ธฐ ํŽธํ•˜๊ฒŒ ํ•œ๋‹ค. ์ฒดํ™”๋˜์ง€ ์•Š์€ ๋งŒํผ ์•ž์œผ๋กœ๋„ ๊พธ์ค€ํžˆ POP๋ฅผ ์—ฐ์Šตํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

3. Coordinator ์‚ฌ์šฉ

์•„์‰ฝ์ง€๋งŒ ์•„์ง๊นŒ์ง€ Coordinator๋ฅผ ์ ์šฉํ•ด๋ณด์ง€๋Š” ๋ชปํ–ˆ๋‹ค. ์ด์œ ๋Š” Coordinator๊ฐ€ ์‚ฌ๋žŒ์— ๋”ฐ๋ผ ๋„ˆ๋ฌด ๋‹ค๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ , ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—์„œ๋„ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” Coordinator ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“œ๋Š” ์ผ์ด ๊ฝค๋‚˜ ๊ณ ๋ฏผ์Šค๋Ÿฌ์› ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ž˜๋„ Coordinator์— ๋Œ€ํ•œ ์˜ˆ์ œ๋ฅผ ๋งŽ์ด ๋ถ„์„ํ•ด ๋ณด๊ณ , Factory์™€ ๊ฒฐํ•ฉ๋œ Coordinator๋ผ๋˜์ง€, ํด๋ฆฐ ์•„ํ‚คํ…์ณ๋‚˜ Rx์™€ ์–ด๋–ป๊ฒŒ ํ•จ๊ป˜ ์“ฐ์ด๋Š”์ง€์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•˜๋ฉฐ ๋‹ค๋ฅธ ๊ฐœ๋…์— ๋Œ€ํ•œ ์ดํ•ด๋„๋ฅผ ๋†’์ผ ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ Coordinator๋ฅผ ์ œ์ž‘ํ•˜๋ฉฐ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์˜ ์ฐธ์กฐ๋ฅผ ๋‚จ๊ธฐ๋ƒ, ๋‚จ๊ธฐ์ง€ ์•Š๋ƒ์— ๋”ฐ๋ผ ํ™”๋ฉด์ „ํ™˜์ด ๋˜๊ณ  ์•ˆ๋˜๊ณ ๊ฐ€ ๊ฒฐ์ •๋œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ, ์ด๋กœ ์ธํ•ด VC ๊ฐ„์˜ push, pop, present์— ๋Œ€ํ•ด์„œ ๋‹ค์‹œ๊ธˆ ์งš์–ด๋ณด๋ฉฐ VC์˜ ๋ฉ”๋ชจ๋ฆฌ ๋˜๋Š” ์ฐธ์กฐ ๊ด€๊ณ„์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค. ๋˜ํ•œ View Life Cycle๊ณผ View Drawing Cycle์— ๋Œ€ํ•ด์„œ๋„ ๋‹ค์‹œ ์‚ดํŽด๋ณด์•˜๋‹ค.

Coordinator Pattern ๊ธฐ๋ณธ! With RayWanderlich Tutorial!

4. Moya ์„ธํŒ… : BaseTarget + BaseService

์ด ๋ถ€๋ถ„์€ ์ดˆ๊ธฐ ๋ชฉํ‘œ์™€ ๊ฐ€์žฅ ๋‹ฌ๋ผ์ง„ ๋ถ€๋ถ„์ธ๋ฐ, Moya๊ฐ€ ์•„๋‹ˆ๋ผ Alamofire๋ฅผ BaseAPI์™€ BaseService๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ชจ๋“ˆํ™”ํ–ˆ๋‹ค. ์ดˆ๊ธฐ์— Moya๋ฅผ ์ด์šฉํ•˜๋ ค๊ณ  ํ–ˆ๋˜ ์ด์œ ๋Š” ์•ฑ์žผ์—์„œ ๊ฐ€์žฅ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์šด ์„œ๋ฒ„ํ†ต์‹  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ Moya๋ผ๊ณ  ์ƒ๊ฐํ•ด์„œ์˜€๋Š”๋ฐ, Spark ํ”„๋กœ์ ํŠธ ์ค‘์— Moya๊ฐ€ ๋„ˆ๋ฌด ๋‘ํ…๊ฒŒ Layering๋˜์–ด ์žˆ๊ณ , URLSession์— ๋Œ€ํ•œ ์›๋ก ์ ์ธ ์ ‘๊ทผ ๋ฐ ์ดํ•ด๋ฅผ ๋ง‰๋Š”๋‹ค๊ณ  ์ƒ๊ฐํ•˜์—ฌ ํ•œ ์ˆ˜์ค€ ๋‚ฎ์€ Alamofire๋ฅผ ์ฑ„ํƒํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค. Alamofire๋ฅผ ๋ชจ๋“ˆํ™”ํ•˜๋ฉด์„œ ๋Š๋‚€ ์ ์€, ํ™•์‹คํžˆ ์„œ๋ฒ„ํ†ต์‹ ์— ๋Œ€ํ•œ ์ดํ•ด๊ฐ€ URLSession -> Alamofire -> Moya ์ˆœ์œผ๋กœ ๊ฐ€์•ผ Moya๋„ ์ž˜ ์“ธ ์ˆ˜ ์žˆ๊ฒ ๋‹ค๋Š” ์ ์ด๋‹ค. ์ด์— ๋Œ€ํ•œ ๋‚ด์šฉ์€ ๋ธ”๋กœ๊ทธ์— ์ •๋ฆฌํ•ด ๋†“์•˜๋‹ค.

Alamofire๋ฅผ Moya์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•ด๋ณด์ž! By Router Pattern (1ํŽธ - Foundation Setting)
Alamofire๋ฅผ Moya์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•ด๋ณด์ž! By Router Pattern (2ํŽธ - Services, Routers ๊ตฌํ˜„)
Alamofire๋ฅผ Moya์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•ด๋ณด์ž! By Router Pattern (3ํŽธ - body, queryBody, requestPlain, Multipart ๊ตฌํ˜„)
Alamofire๋ฅผ Moya์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•ด๋ณด์ž! By Router Pattern (4ํŽธ - EventLogger๋กœ ํ†ต์‹  ๊ฒฐ๊ณผ ํ™•์ธํ•˜๊ธฐ)

5. Custom UI Component

1, 2, 3์ฐจ ๊ณผ์ œ์—์„œ ๋ฐ˜๋ณต๋˜๋Š” UI๋ฅผ ์ฐพ์•„์„œ Custom Component Class๋กœ ์ œ์ž‘ํ–ˆ๋‹ค. ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์–ด๋Š ๋ถ€๋ถ„์—์„œ๋“  ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋†’๊ฒŒ ๋งŒ๋“œ๋Š” ์ ์€ ๋‚˜์ค‘์— ํ•ญ์ƒ ์ด์ ์œผ๋กœ ์ž‘์šฉํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค. 3์ฐจ ๊ณผ์ œ์—์„œ๋Š” Builder Pattern์œผ๋กœ ์›ํ•˜๋Š” Actions์„ ๋ฐ›์•„์„œ Closure์— ์ €์žฅํ•˜๊ณ  ์ด๋ฅผ ๋ฒ„ํŠผ์— ๋ถ€์—ฌํ•˜๋Š” Custom Navigation Bar๋ฅผ ์ œ์ž‘ํ–ˆ๋‹ค. ๋˜ํ•œ ๋ชจ๋“  Component๋ฅผ ์ž‘์„ฑํ•  ๋•Œ SOLID ์›์น™์— ๋งž๊ฒŒ ์ž‘์„ฑํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ–ˆ๋‹ค.

6. ํด๋”๋ง ์™„์„ฑ

์ด ๋ถ€๋ถ„์€ 1-4์ฐจ ๊ณผ์ œ๋ฅผ ํ•˜๋ฉด์„œ๋Š” ๋ฌผ๋ก ์ด๊ณ , ํ•ฉ๋™์„ธ๋ฏธ๋‚˜๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ ์กฐ๊ธˆ์ด๋‚˜๋งˆ ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์•„ํ‚คํ…์ณ, ํ˜‘์—…, ํ™•์žฅ์„ฑ์„ ๊ณ ๋ คํ•˜์—ฌ ํด๋”๋ง์„ ํ–ˆ๋Š”๋ฐ, ์•„์ง ๋‹ค๋“ฌ์„ ๋ถ€๋ถ„์ด ๋งŽ๋‹ค. ์œ ์šฉํ•œ Extension์„ ์ •๋ฆฌํ•˜๊ณ , ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์˜ ํด๋”๋ง์„ ๋ณด๋ฉฐ ์™œ ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์—ˆ์„์ง€ ๊ณ ๋ฏผํ•˜๊ณ , ๊ฐ๊ฐ์˜ ๋‹ค๋ฅธ ์•„ํ‚คํ…์ณ๋ฅผ ๊ฐ€์ง„ ํ”„๋กœ์ ํŠธ๋“ค์ด ์–ด๋–ค ํด๋”๋ง์„ ์ฑ„ํƒํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•˜๋ฉฐ ํด๋”๋ง์„ ์™„์„ฑํ•ด ๋‚˜๊ฐ”๋‹ค.

โœจ ํ˜‘์—…์„ ํ•˜๋ฉด์„œ ์–ด๋ ค์› ๋˜ ์ , ์ƒˆ๋กญ๊ฒŒ ์•Œ๊ฒŒ๋œ ์ 

Xcode Project์— ๋Œ€ํ•œ ์›๋ก ์ ์ธ ์ดํ•ด

์ด๋ฒˆ ํ•ฉ๋™์„ธ๋ฏธ๋‚˜๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ ๊ตฌ์ƒํ•ด ๋†“์€ ํด๋”๋ง์„ ์‹œํ—˜ํ•˜๊ณ , ์ฒ˜์Œ์œผ๋กœ ํ˜‘์—…์„ ์œ„ํ•œ ํ”„๋กœ์ ํŠธ๋ฅผ ์„ธํŒ…ํ•ด ๋ณด์•˜๋‹ค. ์ƒ๊ฐ๋ณด๋‹ค ๋ชจ๋ฅด๋Š” ๋ถ€๋ถ„์ด ๋„ˆ๋ฌด ๋งŽ์•˜๊ณ , Git์—์„œ๋„ ๋ช‡ ๋ฒˆ ๊ท€์ฐฎ์€ ์ถฉ๋Œ์ด ๋‚˜์„œ ์—ด์‹ฌํžˆ ๊ตฌ๊ธ€๋งํ•ด์„œ ํ•ด๊ฒฐํ–ˆ๋‹ค. ์ด ๊ณผ์ •์—์„œ ๋Š๋‚€ ์ ์€ Xcode Project์— ๋Œ€ํ•œ ์›๋ก ์ ์ธ ์ดํ•ด๊ฐ€ ๋งŽ์ด ๋ถ€์กฑํ•˜๋‹ค๋Š” ์ ์ด๋‹ค. UI๋ฅผ ์งœ๊ณ  ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ์ผ์€ ์–ด๋–ป๊ฒŒ ํ•ด์„œ๋“  ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ด ํ”„๋กœ์ ํŠธ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ปดํŒŒ์ผ๋˜๊ณ , ๋นŒ๋“œ๋˜๊ณ , ์‹คํ–‰๋˜๋ฉฐ, OS์— ๋Œ€ํ•ด ๊ด€๋ฆฌ๋˜๋Š”์ง€์— ๋Œ€ํ•œ ๊ธฐ์ดˆ์ ์ธ ์ดํ•ด๊ฐ€ ๋ถ€์กฑํ•˜๋‹ค. ๋˜ํ•œ ํ”„๋กœ์ ํŠธ ์„ธํŒ…์—์„œ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์ด ๋งค์šฐ ๋งŽ๊ณ (info.plist๋‚˜ buidl setting๊ณผ ๊ฐ™์€ ๋ถ€๋ถ„), ๋‹ค๋ฅธ ์–ธ์–ด์™€ ๋‹ค๋ฅด๊ฒŒ xcodeproj๋ผ๋Š” ํŒŒ์ผ์ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ๋“ค์— ๋Šฅ์ˆ™ํ•˜๊ฒŒ ๋Œ€์ฒ˜ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ํ˜„์—…์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๋ถ€๋ถ„์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Tuist์™€ ๊ฐ™์€ ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ ํˆด์„ ์“ด๋‹ค๊ณ  ํ•˜๋Š”๋ฐ, ์ด๋Ÿฌํ•œ ํˆด๋„ ๊ฒฐ๊ตญ์—๋Š” Xcode์— ๋Œ€ํ•œ ๊ธฐ๋ณธ์ ์ธ ์ดํ•ด๊ฐ€ ๋’ท๋ฐ›์นจ๋˜์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์•ฑ์žผ ์ „์— ์‹œ๊ฐ„์„ ๋‚ด์„œ ๊ณต๋ถ€ํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

์ ์ ˆํ•œ ์•„ํ‚คํ…์ณ๋ž€? ํ˜‘์—…์„ ์œ„ํ•œ ํด๋”๋ง์ด๋ž€?(ํ•ฉ๋™์„ธ๋ฏธ๋‚˜ ๊ณผ์ œ์—์„œ ๋ฐœ์ทŒ)

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

Compositional Layout

๋‹น๊ทผ๋งˆ์ผ“์ด ๋‘ ๋ฒˆ์งธ ํด๋ก ์ฝ”๋”ฉ์ด๊ธฐ๋„ ํ•˜๊ณ , ํ‰์†Œ์— ๊ถ๊ธˆํ–ˆ๋˜ CompositionalLayout์œผ๋กœ ๋ทฐ๋ฅผ ๊ตฌํ˜„ํ•ด ๋ณด์•˜๋‹ค. CompositionalLayout๋„ CollectionViewLayout์„ ์ปค์Šคํ…€ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์ž‘์—…์— ์ต์ˆ™ํ•ด์ง€๋ฉด ๋” ์ž˜ ์“ธ์ˆ˜ ์žˆ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ์–ด๋–ค ๋ถ€๋ถ„์ด๋“  ๊ธฐ์ดˆ๋ถ€ํ„ฐ ์ถฉ์‹คํ•˜์ž.

[UIKit] CompositionalLayout์œผ๋กœ ๋‹น๊ทผ๋งˆ์ผ“ ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ๋ณด๊ธฐ ๋ทฐ ๊ตฌํ˜„ํ•˜๊ธฐ

โœจ ์•ž์œผ๋กœ ๊ณต๋ถ€ํ•ด๋‚˜๊ฐˆ ๋ถ€๋ถ„

  • ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ ์›๋ก ์ ์ธ ์ดํ•ด + Tuist๋ฅผ ํ†ตํ•œ ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ
  • Git์— ๋Œ€ํ•œ ์ดํ•ด : ๋‹ค๋ฅธ ์‚ฌ๋žŒ์˜ ๋ฌธ์ œ๋„ ํŽธํ•˜๊ฒŒ ํ•ด๊ฒฐํ•ด์ค„ ์ˆ˜ ์žˆ๋„๋ก
  • Clean Architecture : Presentation ๋ง๊ณ  Data Layer์— ๋Œ€ํ•ด์„œ ๋” ๊ณต๋ถ€
  • UNIT Test : ๊ธฐ๋ณธ์ ์ธ ๊ฐœ๋… ๊ณต๋ถ€ ์ดํ›„ RxTest๊นŒ์ง€
  • CI-CD : ์ฒด๊ณ„์ ์ธ ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด
  • Combine : ๊ฐœ๋… ์•Œ๊ณ  ์ฝ”๋“œ ๋ฆฌ๋”ฉ ์ •๋„๋Š” ๊ฐ€๋Šฅํ•˜๋„๋ก
  • SwiftUI : ์ตœ๊ทผ์— Medium์ด๋‚˜ RayWenderlchi๋ฅผ ๋ณด๋ฉด ๊ฑฐ์˜ SwiftUI์— ๋Œ€ํ•œ ๊ฐ•์˜์ž„. ๊ธฐ๋ณธ์ ์ธ ๊ฐœ๋… ์ˆ™์ง€ํ•˜์ž.
  • ๊ธฐ์ˆ 
    • Share Extension
    • Naver Map & Kakao Map
    • WebView
    • Animation : ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋ถ€์—ฌํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”๋ฐ, ๊ฐ๊ฐ์— ๋Œ€ํ•ด ์ฐจ์ด์ ์„ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ณต๋ถ€ํ•˜๊ธฐ