Search

The Clean Swift

The Clean Swift Handbook์„ ๋ฐ”ํƒ•์œผ๋กœ ์ •๋ฆฌ๋ฅผ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ถ๋งˆํฌ์— The Clean Swift Handbook ๋งํฌ๋ฅผ ์—ฐ๊ฒฐํ•ด๋‘์—ˆ์Šต๋‹ˆ๋‹ค.

ย Clean Swift

iOS ๊ฐœ๋ฐœ์„ ์‹œ์ž‘ํ–ˆ์„ ๋•Œ, ์‰ฝ๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” Architecture๋Š” ์•„๋ฌด๋ž˜๋„ MVC ํŒจํ„ด์ผ ๊ฒ๋‹ˆ๋‹ค.
์ž‘์€ ํ”„๋กœ์ ํŠธ์—์„œ MVC ํŒจํ„ด์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ์€ ํฐ ๋ฌด๋ฆฌ๊ฐ€ ์—†๊ฒ ์ง€๋งŒ, ํ•ด๋‹น ํ”„๋กœ์ ํŠธ๊ฐ€ ์„ฑ์žฅํ•˜๋ฉด์„œ MVC ํŒจํ„ด์ด ํ”„๋กœ์ ํŠธ์˜ ์„ฑ์žฅ์— ์ œ์•ฝ์„ ์ค„ ์ง€๋„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค.
์ด๋Ÿฐ ๊ฒฝ์šฐ, ์šฐ๋ฆฌ๋Š” ์ƒˆ๋กœ์šด ํŒจํ„ด์„ ์ฐพ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. MVVM, MVP ๋“ฑ ๋‹ค์–‘ํ•œ ํŒจํ„ด์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
์ €์ž๋Š” Clean Swift๋ฅผ ์ ์šฉํ•˜๋ผ๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค.
์™œ Clean Swift๋ฅผ ์ ์šฉํ•˜๋ผ๋Š” ๊ฑธ๊นŒ์š”?
Clean Swift๋Š” ๋‹น์‹ ์˜ ์ฝ”๋“œ๊ฐ€ ๋…ผ๋ฆฌ์ ์œผ๋กœ ์•Œ๋งž๋Š” ์œ„์น˜์— ์ž๋ฆฌ์žก์„ ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.
[ Massive View Controller ]
MVC ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ViewController๊ฐ€ ๋น„๋Œ€ํ•ด์ง€๋Š” ๊ฒฝ์šฐ๋ฅผ ๋งŽ์ด ๋ณด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋น„๋Œ€ํ•ด์ง„ ViewController ๋‚ด๋ถ€์—๋Š” ๋‹ค์–‘ํ•œ ์—ญํ• ์„ ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋“ค์ด ๋ชจ์ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
์ฆ‰, Testableํ•˜์ง€ ๋ชปํ•œ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ๋ชปํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๋˜ํ•œ, SRP(Single Responsibility Principle)๋ฅผ ์œ„๋ฐฐํ•˜๋Š” ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ViewController๊ฐ€ ๋‹ค์–‘ํ•œ ์ฑ…์ž„์„ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์ด์ฃ .
Clean Swift๋Š” ์ฑ…์ž„์„ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•˜์—ฌ ViewController ๋‚ด์— ์žˆ๋Š” ๋‹ค์–‘ํ•œ ์ฑ…์ž„์„ ๊ฐ€์ง„ ์ฝ”๋“œ๋ฅผ Interactor, Presenter, Router ๋“ฑ์œผ๋กœ ๋ถ„๋ฆฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์ด ํ–ฅ์ƒํ•  ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์•Œ๋งž์€ ์ฝ”๋“œ๊ฐ€ ์™„์„ฑ๋ฉ๋‹ˆ๋‹ค.
[ Minimize Context Switching ]
Clean Swift๋Š” Context Switching๋ฅผ ์ตœ์†Œํ™”์‹œ์ผœ ์ค๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ž์‹ ๋งŒ์˜ Zone์— ๋จธ๋ฌด๋ฅผ ์ˆ˜ ์žˆ๋„๋ก(getting in the zone) ๋„์›€์„ ์ค๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” ํš์ผํ™”๋œ ํ…œํ”Œ๋ฆฟ์„ ์ œ๊ณตํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
ViewController-Interactor-Presenter ํ˜•์‹์œผ๋กœ ๊ตฌ์„ฑ๋œ Clean Swift๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ”๋“œ๋ฅผ ์งค ๋•Œ ์–ด๋””์— ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์•ผ ํ•  ์ง€ ๊ณ ๋ฏผํ•˜๋Š” ์‹œ๊ฐ„์„ ์ค„์—ฌ์ฃผ๊ณ , ํ•จ๊ป˜ ํ•˜๋Š” ํŒ€์›๋“ค์ด ๋ชจ๋‘ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๋Š” ์‹œ๊ฐ„ ๋˜ํ•œ ์ค„์—ฌ์ค๋‹ˆ๋‹ค.
์ฆ‰, ๊ฐœ๋ฐœ์ž์˜ ํšจ์œจ์„ 2๋ฐฐ ์ด์ƒ ๋†’ํ˜€์ค๋‹ˆ๋‹ค.
[ Optimize Code For Human Consumption ]
์šฐ๋ฆฌ๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ์ปดํŒŒ์ผํ•˜๋Š” ์ผ์€ ์ปดํ“จํ„ฐ์—๊ฒ ๊ต‰์žฅํžˆ ์‚ฌ์†Œํ•œ ์ผ์ž…๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ, ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์ดํ•ดํ•˜๋Š” ์ผ์€ ์‚ฌ์†Œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์šฐ๋ฆฌ๋Š” ์‚ฌ๋žŒ์ด ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ตœ์ ํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
MVC ํŒจํ„ด์€ ViewController ํ•˜๋‚˜์— ๋ชจ๋“  ๋‚ด์šฉ๋“ค์„ ๋•Œ๋ ค ๋„ฃ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ViewController ๋‚ด๋ถ€์— ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๋Š”๋ฐ ๋“œ๋Š” ๋น„์šฉ์ด ํฝ๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ, Clean Swift๋Š” ๋ชฉ์ ์— ๋งž์ถฐ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ ๋“œ๋Š” ์‹œ๊ฐ„์ด ์ ์Šต๋‹ˆ๋‹ค.
๊ฐ’์„ ๊ณ„์‚ฐํ•˜๋Š” ์ฝ”๋“œ์ธ์ง€, UI์— ๊ด€๋ จ๋œ ์ฝ”๋“œ์ธ์ง€์— ๋”ฐ๋ผ ์œ„์น˜ํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— Clean Swift ๊ฐœ๋…์„ ์ดํ•ดํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ๋ˆ„๊ตฌ๋“  ์‰ฝ๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ณ , ์–ด๋Š ํŒŒ์ผ, ์–ด๋Š ๋ถ€๋ถ„์„ ๋ณด๋ฉด ๋  ์ง€๊ฐ€ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ทธ๋ ค์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
์ €์ž๊ฐ€ Clean Swift์˜ ์žฅ์ ์„ 48ํŽ˜์ด์ง€ ๋‚ด๋‚ด ์žฅํ™ฉํ•˜๊ฒŒ ๋Š˜์–ด๋†“์ง€๋งŒ, ๊ฐ„๋‹จํžˆ ์ •๋ฆฌํ•˜๋ฉด:
Clean Swift๊ฐ€ ์ œ๊ณตํ•˜๋Š” boiler plate๋งŒ์„ ์‚ฌ์šฉํ•ด์„œ ๋ˆ„๊ตฌ๋‚˜ ์ž‘์„ฑํ•˜๊ธฐ ์‰ฝ๊ณ , ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ณ , ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์ข‹์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ย Clean Architecture

Clean Swift๋Š” Clean Architecture์—์„œ ์œ ๋ž˜๋˜์—ˆ๋‹ค๊ณ  ์ €์ž๋Š” ๋งํ•ฉ๋‹ˆ๋‹ค.
ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜๋Š” App Level์˜ UseCase๋ฅผ ๋” ์ž‘์€ ์ฝ”๋“œ ์ˆ˜์ค€์˜ UseCase๋กœ ๋ถ„ํ•ดํ•˜์—ฌ ์ ์ ˆํ•œ ๋ ˆ์ด์–ด๋กœ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋กœ ์ธํ•ด ๊ฐ ๋ ˆ์ด์–ด์˜ ๊ด€์‹ฌ์‚ฌ๊ฐ€ ๋ถ„๋ฆฌ(Separation of Concerns)๋ฉ๋‹ˆ๋‹ค.
์ฆ‰, ๊ฐ ์ฝ”๋“œ๊ฐ€ ๊ด€์‹ฌ์‚ฌ์— ๋งž์ถ˜ ๋ ˆ์ด์–ด์— ์œ„์น˜ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
Clean Swift๋Š” ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜์˜ ๋ ˆ์ด์–ด์— VIP Cycle๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
VIP Cycle์€ Clean Swift์˜ ํ•ต์‹ฌ ๊ฐœ๋…์œผ๋กœ ViewController - Interactor - Presenter๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
ํ•ด๋‹น Cycle์€ ViewController๋กœ๋ถ€ํ„ฐ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.
ViewController์—์„œ ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ๊ฐ€ Interactor๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , Interactor๋Š” Presenter๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ Presenter๊ฐ€ ViewController๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด์„œ Cycle์€ ๋๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
ViewController โ†’ Interactor โ†’ Presenter โ†’ ViewController ์ˆœ์„œ๋กœ ํ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ํ๋ฆ„์ด ํ˜๋Ÿฌ๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
ViewController โ†’ Interactor โ†’ Presenter โ†’ ViewController๊ฐ€ ์„œ๋กœ๋ฅผ ํ˜ธ์ถœํ•  ๋• ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋Š”๊ฐ€?
Clean Swift๋„ ๋ ˆ์ด์–ด์—์„œ ๋‹ค์Œ ๋ ˆ์ด์–ด๋กœ ๋„˜์–ด๊ฐˆ ๋•, Clean Architecture์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ DIP(Dependency Inversion Principle)๋ฅผ ์ ์šฉํ•ด์„œ Protocol method๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
Interactor๋Š” BusinessLogin Protocol๋ฅผ, Presenter๋Š” PresentationLogic Protocol๋ฅผ, ViewController๋Š” DisplayLogic Protocol๋ฅผ conformํ•˜๊ฒŒ ๋˜๊ณ , ์ด์ „ ํด๋ž˜์Šค์— ๋‹ค์Œ ์ˆœ์„œ์˜ ํด๋ž˜์Šค๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ํด๋ž˜์Šค๊ฐ€ conformํ•˜๊ณ  ์žˆ๋Š” Protocol ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ž˜์•ผ ์ถ”ํ›„์— ๋‹ค๋ฅธ ํด๋ž˜์Šค๋กœ ๋ณ€๊ฒฝ์ด ๋ฐœ์ƒํ•ด๋„ protocol๋ฅผ ๋ฐ”๋ผ๋ณด๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ณ€๊ฒฝ ๋ฒ”์œ„๊ฐ€ ์ ์–ด์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ย VIP Cycle

VIP Cycle๊ณผ Clean Architecture๋ฅผ ํ•ฉ์น˜๋ฉด ์ด๋Ÿฌํ•œ ์›์ด ๋‚˜์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

โ€ข ViewController

Clean Swift์—์„œ ViewController๋Š” ๋‘๊ฐ€์ง€ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
โ€ข
View : Cycle์˜ ๊ฒฐ๊ณผ๋ฌผ์„ ํ™”๋ฉด์— ๋„์›Œ์„œ ์œ ์ €์—๊ฒŒ ๋ณด์—ฌ์คŒ
ViewController๋Š” DisplayLogic๋ฅผ conformํ•˜๊ณ  ์žˆ์–ด Presenter๋กœ๋ถ€ํ„ฐ input์ด ๋“ค์–ด์˜ค๋ฉด ์ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
โ€ข
Controller : Interactor๋ฅผ ์ž‘๋™ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด business logic๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์›€
Controller๋Š” BusinessLogic Protocol method๋ฅผ ํ˜ธ์ถœ์‹œ์ผœ output๋ฅผ Interactor๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
์ „๋‹ฌ๋œ output์€ business logic protocol๋ฅผ conformํ•˜๋Š” ๋ถ€๋ถ„์œผ๋กœ ๋„˜์–ด ๊ฐ”๊ธฐ ๋•Œ๋ฌธ์— ๋ˆ„๊ฐ€, ์–ด๋–ป๊ฒŒ ๊ฐ’์„ ์ฒ˜๋ฆฌํ•˜๋Š”์ง€๋Š” ViewController๊ฐ€ ๊ด€์‹ฌ๊ฐ€์ง€์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

โ€ข Interactor

Interactor๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•  ๋•Œ, Worker๋ฅผ ๋‘๊ณ  ๋ณต์žกํ•œ ๋กœ์ง์€ ๋Œ€์‹  ์ˆ˜ํ–‰ํ•˜๋„๋ก ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
๋‹ค์–‘ํ•œ Interactor์—์„œ ๋น„์ผ๋น„์žฌํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์˜ ๊ฒฝ์šฐ ํ•˜๋‚˜์˜ Worker๊ฐ€ ๋‹ด๋‹นํ•˜๋„๋ก ํ•˜์—ฌ ์ค‘๋ณต ์ฝ”๋“œ๋ฅผ ์ค„์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋กœ์ง์„ Worker๋กœ ๋ถ„๋ฆฌํ–ˆ์„ ๊ฒฝ์šฐ์— ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์˜์กด ๋กœ์ง์ด Worker๋กœ ํ•œ์ •๋˜์–ด ์˜ํ–ฅ ๋ฒ”์œ„๊ฐ€ ์ค„์–ด๋“ค๊ฒŒ ๋˜๋Š” ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

โ€ข Presenter

ํ™”๋ฉด์— ๋ณด์—ฌ์ค„ ํ˜•ํƒœ๋กœ ๊ฐ€๊ณตํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

ย Next Step

Clean Swift๋ฅผ ์กฐ๊ธˆ ๋” ์™€๋‹ฟ๊ฒŒ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ Clean Swift๋ฅผ ์ ์šฉํ•œ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
์ด์ „์— MVVM, MVP ํŒจํ„ด ๊ณต๋ถ€์— ์‚ฌ์šฉํ–ˆ๋˜ ImageExample_Pattern ํ”„๋กœ์ ํŠธ์— Clean Swift๋ฅผ ์ ์šฉํ•ด๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.
๋‚ด์šฉ์ด ๋ฐฉ๋Œ€ํ•˜์—ฌ ๋‹ค์Œ ๊ฒŒ์‹œ๋ฌผ์—์„œ ์ด์–ด์„œ ์ง„ํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.