TDD์™€ Clean Architecture๋กœ ์žฌ๊ตฌ์ถ•ํ•œ fromm ๋ผ์ด๋ธŒ ์„œ๋น„์Šค

์ •๊ตญํฌ
  • #fromm
  • #๋ฆฌํŒฉํ„ฐ๋ง
  • #iOS
  • #TDD
  • #Clean Architecture

fromm ๋ผ์ด๋ธŒ ์„œ๋น„์Šค ์†Œ๊ฐœ

์•ˆ๋…•ํ•˜์„ธ์š”! fromm ์•ฑ์˜ iOS ๊ฐœ๋ฐœ์„ ๋‹ด๋‹นํ•˜๊ณ  ์žˆ๋Š” ์ •๊ตญํฌ์ž…๋‹ˆ๋‹ค. fromm ๋ผ์ด๋ธŒ ์„œ๋น„์Šค๋Š” ์•„ํ‹ฐ์ŠคํŠธ๊ฐ€ ์›ํ•˜๋Š” ์‹œ๊ฐ„์— ๋ผ์ด๋ธŒ ๋ฐฉ์†ก์„ ์‹œ์ž‘ํ•˜๋ฉด, ํŒฌ๋“ค์ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐฉ์†ก์— ์ฐธ์—ฌํ•ด ์†Œํ†ตํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์—์„œ ์ฑ„ํŒ… ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ์–‘๋ฐฉํ–ฅ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๋ฐฐ๊ฒฝ

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

์œ ์ง€๋ณด์ˆ˜ ๊ฐœ์„ ์ด ํ•„์š”ํ–ˆ๋˜ ๋ฐฐ๊ฒฝ

๊ธฐ์กด ๊ตฌํ˜„์€ TCA ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์—ˆ์œผ๋ฉฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ์ ๋“ค์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

  1. ์ด์Šˆ ๋ฐœ์ƒ ์‹œ ์›์ธ ํŒŒ์•…์ด ์–ด๋ ต๋‹ค
  • ํ”„๋ ˆ์ž„์›Œํฌ ๋‚ด๋ถ€ ์ถ”์ƒํ™” ๊ณ„์ธต์ด ๊นŠ๊ณ  ๋ณต์žกํ•˜์—ฌ, ๋Ÿฐํƒ€์ž„์—์„œ ๋ฐœ์ƒํ•œ ๋ฌธ์ œ์˜ ์›์ธ์„ ๋น ๋ฅด๊ฒŒ ์ถ”์ ํ•˜๊ธฐ ์–ด๋ ค์› ์Šต๋‹ˆ๋‹ค.
  1. ์ƒํƒœ ๋ณ€๊ฒฝ ์‹œ ์ „์ฒด ๋ทฐ ์—…๋ฐ์ดํŠธ ๊ฐ€๋Šฅ์„ฑ
  • TCA์˜ Store๋Š” ์ „์ฒด ์ƒํƒœ๋ฅผ ๊ด€์ฐฐํ•˜๋Š” ๊ตฌ์กฐ๋กœ ๋˜์–ด ์žˆ์–ด, ํ•˜๋‚˜์˜ ์ƒํƒœ ๋ณ€๊ฒฝ์ด ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์ „์ฒด View ์—…๋ฐ์ดํŠธ๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” SwiftUI์˜ ๋ฐ”๋”” ์žฌ๊ณ„์‚ฐ ๋ฐฉ์‹๊ณผ ๊ฒฐํ•ฉ๋˜๋ฉด์„œ ์„ฑ๋Šฅ ์ €ํ•˜๋กœ ์ด์–ด์งˆ ์—ฌ์ง€๊ฐ€ ์žˆ๋‹ค๊ณ  ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.
  1. Reducer๋ฅผ ์„ธ๋ถ„ํ™”ํ• ์ˆ˜๋ก ๋กœ์ง ํ๋ฆ„์ด ๋ถ„์‚ฐ๋จ
  • ๊ธฐ๋Šฅ ๋‹จ์œ„๋กœ Reducer๋ฅผ ์ž˜๊ฒŒ ๋‚˜๋ˆ„๋‹ค ๋ณด๋ฉด, ํ•˜๋‚˜์˜ ์‚ฌ์šฉ์ž ์•ก์…˜์ด ์—ฌ๋Ÿฌ Layer๋ฅผ ํ†ตํ•ด ๋ถ„์‚ฐ ์ฒ˜๋ฆฌ๋˜์–ด ๋กœ์ง์˜ ํ๋ฆ„์„ ๋”ฐ๋ผ๊ฐ€๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.
  1. Straight-line ํ๋ฆ„์˜ ๋ถ€์žฌ๋กœ ์ธํ•œ ๊ฐ€๋…์„ฑ ์ €ํ•˜
  • Reducer ๋‚ด๋ถ€์—์„œ ๋ถ„๊ธฐ์™€ ์ด๋ฒคํŠธ ์ „ํŒŒ๊ฐ€ ์žฆ์•„ ์ฝ”๋“œ๊ฐ€ ์ง๊ด€์ ์œผ๋กœ ์ฝํžˆ์ง€ ์•Š์œผ๋ฉฐ, ์ˆœ์ฐจ์ ์ธ ์‹คํ–‰ ํ๋ฆ„์„ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ์–ด๋ ค์›€์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  1. ๊ธฐ๋ณธ Swift ๊ธฐ๋Šฅ์˜ ์ถ”์ƒํ™”์— ๋”ฐ๋ฅธ ํ•™์Šต ๋ฐ ์œ ์ง€๋ณด์ˆ˜ ๋น„์šฉ ์ฆ๊ฐ€
  • TCA๋Š” Swift์˜ ์ƒํƒœ ๊ด€๋ฆฌ, ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ, ์˜์กด์„ฑ ์ฃผ์ž… ๊ธฐ๋Šฅ์„ ๊ณ ๋„๋กœ ์ถ”์ƒํ™”ํ•˜์—ฌ ์ œ๊ณตํ•˜์ง€๋งŒ, ๊ทธ ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•˜๊ณ  ํ™œ์šฉํ•˜๋Š” ๋ฐ ์ถ”๊ฐ€์ ์ธ ํ•™์Šต์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋””๋ฒ„๊น… ์‹œ TCA ๋‚ด๋ถ€ ๋™์ž‘๊นŒ์ง€ ์ถ”์ ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žฆ์•˜์Šต๋‹ˆ๋‹ค.
  1. ์ง์ ‘ ๋ฐ”์ธ๋”ฉ ๋ฐฉ์‹๋ณด๋‹ค ํšจ์œจ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Œ
  • View์— ์ง์ ‘ ์ƒํƒœ๋ฅผ ๋ฐ”์ธ๋”ฉํ•˜๋Š” ๋ฐฉ์‹๋ณด๋‹ค ์ค‘๊ฐ„ ๊ณ„์ธต(Reducer ๋“ฑ)์„ ๊ฑฐ์น˜๋ฉด์„œ UI ์—…๋ฐ์ดํŠธ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋Šฅ ์ž์ฒด๋Š” ์•ˆ์ •์ ์œผ๋กœ ๋™์ž‘ํ–ˆ์ง€๋งŒ, ๊ตฌ์กฐ์  ๋ณต์žก์„ฑ๊ณผ ๋‚ฎ์€ ์‘์ง‘๋„๋กœ ์ธํ•ด ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ต๋‹ค๋Š” ๊ฒฐ๋ก ์— ์ด๋ฅด๋ €์Šต๋‹ˆ๋‹ค. 1๋…„๊ฐ„ TCA๋ฅผ ์‹คํ—˜์ ์œผ๋กœ ๋„์ž…ํ•ด ์‚ฌ์šฉํ•ด ๋ณธ ๊ฒฐ๊ณผ, ์œ„์™€ ๊ฐ™์€ ๊ตฌ์กฐ์  ํ•œ๊ณ„๊ฐ€ ๋ช…ํ™•ํ•ด์กŒ๊ณ , ์ด์— ๋”ฐ๋ผ ํ˜„์žฌ๋Š” TCA ๋„์ž…์„ ์ค‘๋‹จํ•œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.

์žฌ๊ตฌ์ถ•์˜ ํ•„์š”์„ฑ

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

๊ธฐ์กด ๊ตฌํ˜„์—์„œ๋Š” ํ•˜๋‚˜์˜ ํ™”๋ฉด์— ๋Œ€ํ•ด ์ตœ์ƒ์œ„ Reducer๊ฐ€ ์กด์žฌํ•˜๊ณ , ํ•˜์œ„ ๋ทฐ๋‚˜ ์œ ์‚ฌํ•œ Usecase ๋‹จ์œ„๋กœ ํ•˜์œ„ Reducer๊ฐ€ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์œ ์‚ฌํ•œ Usecase๋ฅผ ์„œ๋กœ ๋‹ค๋ฅธ ํ™”๋ฉด ๊ฐ„์— ์žฌ์‚ฌ์šฉํ•˜๋ ค๋‹ค ๋ณด๋‹ˆ ์กฐ๊ฑด ๋ถ„๊ธฐ๊ฐ€ ์žฆ์•„์กŒ๊ณ , ์ ์  ์ฝ”๋“œ์˜ ๋ณต์žก๋„๊ฐ€ ์ฆ๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ์˜ ํ๋ฆ„ ๋˜ํ•œ ์ƒ์œ„ โ†’ ํ•˜์œ„ โ†’ ์ƒ์œ„๋กœ ์˜ค๊ฐ€๋ฉฐ ์ฒ˜๋ฆฌ๋˜๋Š” ๊ตฌ์กฐ์—ฌ์„œ, ํŠน์ • ์•ก์…˜์˜ ์ „ํ›„ ๋งฅ๋ฝ์„ ํŒŒ์•…ํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๊ณ„์ธต์„ ํƒ์ƒ‰ํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด ๋นˆ๋ฒˆํ•˜๊ฒŒ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

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

๋ฆฌํŒฉํ„ฐ๋ง์˜ ํ•ต์‹ฌ ๋„๊ตฌ

์ด๋ฒˆ ๋ฆฌํŒฉํ„ฐ๋ง์˜ ํ•ต์‹ฌ ๋ชฉํ‘œ๋Š” ํšŒ๊ท€ ๋ฒ„๊ทธ ์—†์ด ๊ตฌ์กฐ๋ฅผ ๊ฐœ์„ ํ•˜๋Š” ๊ฒƒ์ด์—ˆ์œผ๋ฉฐ, ์ด๋ฅผ ์œ„ํ•ด ๋‘ ๊ฐ€์ง€ ํ•ต์‹ฌ ๋„๊ตฌ๋ฅผ ์ „๋žต์ ์œผ๋กœ ํ™œ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค: ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ(TDD)๊ณผ Clean Architecture์ž…๋‹ˆ๋‹ค.

TDD

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

Clean Architecture

Clean Architecture๋Š” ๋ชจ๋“ˆ ๊ตฌ์กฐ๋ฅผ ์ˆ˜ํ‰ ๊ณ„์ธต์œผ๋กœ ๋‚˜๋ˆ„๊ณ  ๊ฐ ๊ณ„์ธต ๊ฐ„์˜ ์ปดํŒŒ์ผ ํƒ€์ž„ ์˜์กด์„ฑ์„ ๋ฐ”๊นฅ์—์„œ ์•ˆ์œผ๋กœ๋งŒ ํ–ฅํ•˜๋„๋ก ์ œํ•œํ•จ์œผ๋กœ์จ, ๋ณ€๊ฒฝ์— ์œ ์—ฐํ•œ ๊ตฌ์กฐ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์ดˆ์ ์„ ๋งž์ท„์Šต๋‹ˆ๋‹ค. ๊ฐ ๊ณ„์ธต์€ Swift Package์˜ ํƒ€๊ฒŸ์œผ๋กœ ๊ตฌ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฐ˜๋Œ€๋กœ ์‹คํ–‰ํƒ€์ž„ ์˜์กด์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ(์˜ˆ: Usecase๊ฐ€ Adapter๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•  ๋•Œ)๋Š” DI(์˜์กด์„ฑ ์ฃผ์ž…)๋ฅผ ํ™œ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. DI๋Š” Pure DI ๋ฐฉ์‹์„ ์ฑ„ํƒํ•˜๊ณ  ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์ด ์ง์ ‘ ๊ตฌํ˜„ํ•˜์˜€์œผ๋ฉฐ, Clean Architecture์˜ Main Layer๋ฅผย  ๋ณ„๋„์˜ ํƒ€๊ฒŸ์œผ๋กœ ๋‘์–ด ๊ฐ์ฒด ์ƒ์„ฑ ๋ฐ ์˜์กด์„ฑ ์ฃผ์ž…์„ ๋‹ด๋‹นํ•˜๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ, Clean Swift ํŒจํ„ด์„ย  ์ฑ„ํƒํ–ˆ์œผ๋ฉฐ, ๊ทธ๋Œ€๋กœ ์ ์šฉํ•˜์ง€ ์•Š๊ณ  Clean Architecture ๊ตฌ์กฐ์— ๋งž๋„๋ก ๋ณ€ํ˜•ํ•˜์—ฌ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ, View โ†’ Interactor โ†’ Presenter โ†’ View ๋กœ ์ด์–ด์ง€๋Š” ํ๋ฆ„์ด ๋ช…ํ™•ํ•ด์กŒ๊ณ , ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ธฐ์กด ํ…œํ”Œ๋ฆฟ์„ ๋ณด์™„ํ•ด ์‚ฌ์šฉํ•˜์—ฌ ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ ์ฝ”๋“œ ์ž‘์„ฑ์„ ์ค„์ด๊ณ  ์ผ๊ด€๋œ ๊ตฌ์กฐ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

Clean Swift ๊ตฌ์กฐ๋„

Clean Swift ๊ตฌ์กฐ๋„

์ˆ˜์ง์  ๋ถ„๋ฆฌ

์ˆ˜์ง์  ๋ถ„๋ฆฌ

๋ฆฌํŒฉํ„ฐ๋ง ์ „๋žต

  1. ์‘์ง‘๋„ ํ–ฅ์ƒ
  • ํ•˜๋‚˜์˜ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, ํ•ด๋‹น ์ด๋ฒคํŠธ์˜ ํ๋ฆ„์„ ํ•œ ๊ณณ์—์„œ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋„๋ก Interactor ์ค‘์‹ฌ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์žฌ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์ฝ”๋“œ์˜ ํ๋ฆ„์ด ๋ช…ํ™•ํ•ด์ง€๊ณ  ๋””๋ฒ„๊น…์ด๋‚˜ ๋ณ€๊ฒฝ ์‹œ ์ถ”์ ์ด ์‰ฌ์›Œ์กŒ์Šต๋‹ˆ๋‹ค.
  1. ๊ธฐ์กด ๋ชจ๋“ˆ์˜ ๋Œ€๋ถ€๋ถ„์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ
  • UI ๊ตฌ์กฐ์™€ ๊ด€๋ จ๋œ ์š”์†Œ(๋ทฐ ๊ณ„์ธต ๊ตฌ์กฐ, ํ™”๋ฉด ์ˆ˜), Entity ๋ชจ๋ธ, ํ”„๋ ˆ์ž„์›Œํฌ ๋ฐ Driver, Backend API ๋ชจ๋ธ ๋“ฑ์€ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜๋˜, TCA์— ์˜์กดํ•˜๋˜ ์ฝ”๋“œ๋Š” ์ œ๊ฑฐํ•˜๊ณ  ์žฌ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.
  1. SwiftUI์˜ ๊ธฐ๋ณธ ์ƒํƒœ ๊ด€๋ฆฌ ๋ฐฉ์‹ ์‚ฌ์šฉ
  • @State, @ObservedObject, @Bindingย ๋“ฑ์˜ SwiftUI ๋ณธ์—ฐ์˜ ์ƒํƒœ ๊ด€๋ฆฌ ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•ด ๋ทฐ์™€ ์ƒํƒœ๋ฅผ ์ง์ ‘ ๋ฐ”์ธ๋”ฉํ•จ์œผ๋กœ์จ, ์ค‘๊ฐ„ ๊ณ„์ธต์„ ์ œ๊ฑฐํ•˜๊ณ  UI ๋ฐ˜์‘์„ฑ์„ ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.
  1. Reducer์™€ Client์˜ ์ฝ”๋“œ๋ฅผ ์žฌ๊ตฌ์„ฑ
  • ๊ธฐ์กด TCA ๊ตฌ์กฐ์—์„œ Reducer์™€ Client์— ์ž‘์„ฑ๋˜์–ด ์žˆ๋˜ ์ฝ”๋“œ๋ฅผ ์ƒˆ๋กœ์šด ๊ตฌ์กฐ์— ๋งž์ถฐ Usecase, Adapter, Driver Layer๋กœ ์—ญํ• ์— ๋”ฐ๋ผ ๋ถ„๋ฆฌ ์žฌ๋ฐฐ์น˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์—์„œ ์ผ๋ถ€ ๋กœ์ง์€ ํ†ตํ•ฉ๋˜๊ณ , ์ผ๋ถ€๋Š” ๋ถ„๋ฆฌ๋˜๋ฉด์„œ ๊ฐ ํƒ€์ž…์˜ ์ฑ…์ž„์ด ๋ณด๋‹ค ๋‹จ์ผํ•ด์กŒ์Šต๋‹ˆ๋‹ค.
  1. Clean Architecture ์ˆ˜ํ‰ ๊ณ„์ธต ๋ถ„๋ฆฌ ์ ์šฉ
  • ์ˆ˜์ง์ ์ธ ๋ถ„๋ฆฌ๋ฅผ ์œ„ํ•ด ๋ผ์ด๋ธŒ ๋ชจ๋“ˆ์„ ํ•˜๋‚˜์˜ ํŒจํ‚ค์ง€๋กœ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๋ฆฌ๊ณ  ์ˆ˜์ง์ ์ธ ๊ณ„์ธต์€ ํƒ€๊ฒŸ์œผ๋กœ ๋ถ„๋ฆฌํ•ด ๋ฌผ๋ฆฌ์ ์œผ๋กœ ๊ตฌ์กฐํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๊ณ„์ธต ๊ฐ„ ์ปดํŒŒ์ผ ํƒ€์ž„ ์˜์กด์„ฑ์€ ์˜ค์ง ๋ฐ”๊นฅ์—์„œ ์•ˆ์ชฝ์œผ๋กœ๋งŒ ํ–ฅํ•˜๋„๋ก Package.swift๋ฅผ ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ์ˆ˜ํ‰์  ๋ถ„๋ฆฌ ์ˆ˜ํ‰์  ๋ถ„๋ฆฌ
  1. @Shared ์ƒํƒœ ์ œ๊ฑฐ ๋ฐ ๋ช…์‹œ์  ์˜์กด์„ฑ ์ฃผ์ž…
  • @Shared, @SharedReader์ฒ˜๋Ÿผ ๊ฐ„์ ‘์ ์œผ๋กœ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•˜๋˜ ๋ฐฉ์‹์„ ์ง€์–‘ํ•˜๊ณ , ๋ชจ๋“  ์˜์กด์„ฑ์„ ๋ช…์‹œ์ ์œผ๋กœ ์ฃผ์ž…๋ฐ›๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ๋ณ€๊ฒฝ ์ถ”์ ์„ฑ๊ณผ ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ์„ ํ™•๋ณดํ–ˆ์Šต๋‹ˆ๋‹ค.
  1. Entity ์ค‘์‹ฌ์˜ ๋„๋ฉ”์ธ ๋กœ์ง ์žฌ๊ตฌ์„ฑ
  • ๊ธฐ์กด Entity ํƒ€์ž…์—๋Š” ๋กœ์ง์ด ๊ฑฐ์˜ ์กด์žฌํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„ ๋ณ€์ˆ˜๋งŒ ์ •์˜๋˜์–ด ์žˆ์—ˆ๊ณ , ํ•ด๋‹น ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋กœ์ง์€ ํด๋ผ์ด์–ธํŠธ ๊ฐ์ฒด ๋‚ด๋ถ€์— ๋ถ„์‚ฐ๋˜์–ด ์žˆ์–ด ์ค‘๋ณต์ด ๋ฐœ์ƒํ•˜๊ณ  ์‘์ง‘๋„๊ฐ€ ๋‚ฎ์•˜์Šต๋‹ˆ๋‹ค.
  • ์ด๋Ÿฌํ•œ ๋ถ„์‚ฐ๋œ ๋กœ์ง์„ Entity ๋‚ด๋ถ€๋กœ ์ด๋™์‹œ์ผœ, ๋„๋ฉ”์ธ ์ค‘์‹ฌ ์„ค๊ณ„ ์›์น™์— ๋งž๊ฒŒ ์—ญํ• ์„ ์žฌ๋ฐฐ์น˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ์™ธ๋ถ€์—์„œ๋Š” ์ธํ„ฐํŽ˜์ด์Šค์—๋งŒ ์˜์กดํ•˜๋„๋ก ํ•˜์—ฌ ๋ณ€๊ฒฝ์— ์œ ์—ฐํ•˜๊ฒŒ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๊ณ , ๋ถˆํ•„์š”ํ•œ ์†์„ฑ์€ private์œผ๋กœ ์ „ํ™˜ํ•ด ์บก์Аํ™” ์ˆ˜์ค€๋„ ๋†’์˜€์Šต๋‹ˆ๋‹ค.
  1. TDD ๊ธฐ๋ฐ˜ Usecase ์„ค๊ณ„ ๋ฐ ๊ตฌํ˜„
  • ๋ชจ๋“  Usecase๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋จผ์ € ์ž‘์„ฑํ•˜๊ณ  ๊ทธ์— ๋งž์ถฐ ๊ตฌํ˜„ํ•˜๋Š” TDD ๋ฐฉ์‹์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์ด ๊ณผ์ •์„ ํ†ตํ•ด ๊ฐ Usecase์˜ ๊ฒฝ๊ณ„์™€ ์ฑ…์ž„์ด ๋ช…ํ™•ํ•˜๊ฒŒ ๋“œ๋Ÿฌ๋‚ฌ๊ณ , ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ์„ฑ๊ณผ ์žฌ์‚ฌ์šฉ์„ฑ์ด ๊ฐ€๋Šฅํ•œ ๊ตฌ์กฐ๋ฅผ ๊ฐ–์ถœ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  1. ๋ฆฌํŒฉํ„ฐ๋ง ์›์น™ ์ค€์ˆ˜
  • ๋ฆฌํŒฉํ„ฐ๋ง ๊ณผ์ •์—์„œ ๊ธฐ๋Šฅ์˜ ์™ธํ˜•์  ๋™์ž‘์ด๋‚˜ ๊ฒฐ๊ณผ๋Š” ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค๋Š” ์›์น™์„ ์ง€ํ‚ค๊ณ , ๋น„์ •์ƒ์ ์ธ ๋กœ์ง์ด๋ผ ํ•˜๋”๋ผ๋„ ๊ธฐ์กด ๋กœ์ง์„ ๊ทธ๋Œ€๋กœ ๋ฐ˜์˜ํ•œ ํ›„ ํ…Œ์ŠคํŠธ์™€ ๋ฆฌ๋ทฐ๋ฅผ ํ†ตํ•ด ํ–ฅํ›„ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ตฌ์ฒด์ ์ธ ์‹คํ–‰ ๋ฐฉ์•ˆ

์ด๋ฒˆ ๋ฆฌํŒฉํ„ฐ๋ง ํ”„๋กœ์ ํŠธ๋Š” 3๋ช…์˜ iOS ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ณ‘๋ ฌ์ ์œผ๋กœ ์ง„ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๊ตฌ์กฐ ๊ฐœ์„ , ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€ ํ™•๋ณด, ์•„ํ‚คํ…์ฒ˜ ์žฌ์„ค๊ณ„๋ฅผ ๋™์‹œ์— ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์‹ค์งˆ์ ์ธ ์‹คํ–‰ ์ „๋žต์„ ์ˆ˜๋ฆฝํ•˜๊ณ  ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

iOS ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ TDD ์„ธ์…˜

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

์˜คํ”„๋ผ์ธ ์ฝ”๋“œ ๋ฆฌ๋ทฐ ๋ฐฉ์‹

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

์ธ์ˆ˜ ํ…Œ์ŠคํŠธ๋Š” ํ›„์ˆœ์œ„๋กœ ์ง„ํ–‰

์ธ์ˆ˜ํ…Œ์ŠคํŠธ๋Š” ์ผ์ •์ƒ ์šฐ์„ ์ˆœ์œ„์—์„œ ๋ฐ€๋ ธ์Šต๋‹ˆ๋‹ค. 1์ฐจ๋กœ ๋ชจ๋“  ๊ตฌํ˜„์ด ์™„๋ฃŒ๋œ ํ›„ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ตฌํ˜„ ์ˆœ์„œ: ๋ฐ”๊นฅ์—์„œ ์•ˆ์œผ๋กœ, ๋‹ค์‹œ ์•ˆ์—์„œ ๋ฐ”๊นฅ์œผ๋กœ

ํ™”๋ฉด ํ•˜๋‚˜๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์„ ์ž‘์—… ๋‹จ์œ„๋กœ ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ํ™”๋ฉด์— ๋Œ€ํ•œ ์ „์ฒด ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋ฅผ ๋”ฐ๋ž์Šต๋‹ˆ๋‹ค. Usecase layer์— ์žˆ๋Š” UI ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ถ€๋ถ„์ด ๊ตฌํ˜„์˜ ์‹œ์ž‘์ ์ž…๋‹ˆ๋‹ค.

  1. Interactor ๊ตฌํ˜„: Interactor ํƒ€์ž…์„ TDD๋กœ ๊ตฌํ˜„ํ•˜๋ฉฐ, UI ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๊ณ  ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด์„œ ํ•„์š”ํ•œ Usecase ์˜ ์ธํ„ฐํŽ˜์ด์Šค ๋ฐ Adapter์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋„์ถœํ–ˆ์Šต๋‹ˆ๋‹ค. Interactor์™€ ํ˜‘๋ ฅํ•˜๋Š” ์ƒˆ๋กœ์šด ๋‹ค์ˆ˜์˜ ํƒ€์ž…์ด ๋„์ถœ๋ฉ๋‹ˆ๋‹ค.ย 
  2. Usecase ๊ตฌํ˜„: 1๋‹จ๊ณ„์—์„œ ๋„์ถœ๋œ Usecase ํƒ€์ž…์„ ๋™์ผํ•˜๊ฒŒ TDD๋กœ ๊ตฌํ˜„ํ•˜๋ฉฐ, ์ด ๊ณผ์ •์—์„œ ์—ญ์‹œ ํ˜‘๋ ฅํ•  Usecase ์˜ ์ธํ„ฐํŽ˜์ด์Šค ๋ฐ Adapter์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋„์ถœํ–ˆ์Šต๋‹ˆ๋‹ค.
  3. Adapter ๊ตฌํ˜„: 2๋‹จ๊ณ„์—์„œ ๋„์ถœ๋œ ์ธํ„ฐํŽ˜์ด์Šค์— ๋งž์ถ”์–ด Adapter ํƒ€์ž…์„ ๊ตฌํ˜„ํ•˜๊ณ , ์ด ๊ณผ์ •์—์„œ Driver ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋„์ถœํ–ˆ์Šต๋‹ˆ๋‹ค.
  4. Driver ๊ตฌํ˜„: ๋งˆ์ง€๋ง‰์œผ๋กœ 3๋‹จ๊ณ„์—์„œ ๋„์ถœ๋œ ์ธํ„ฐํŽ˜์ด์Šค์— ๋งž์ถ”์–ด ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‚˜ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”ย  Driver ๊ตฌํ˜„์ฒด๋ฅผ ์™„์„ฑํ•ฉ๋‹ˆ๋‹ค.ย 

์–ด๋–ค ํƒ€์ž…์„ Driver Layer์— ๋†“์ผ์ง€ ์ •ํ•˜๋Š” ๊ธฐ์ค€์€ ํ•ด๋‹น ํƒ€์ž…์ด ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‚˜ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์˜์กดํ•˜๋Š”์ง€ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค.

Driver Layer๋Š” ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‚˜ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ import ํ•˜๋Š” ์œ ์ผํ•œ Layer์ž…๋‹ˆ๋‹ค.ย 

์—ฌ๊ธฐ์—๋Š” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฒ˜๋Ÿผ ์–ด๋–ค Layer์—์„œ๋„ ํ•„์š”ํ•œ ๊ฒƒ์€ ์˜ˆ์™ธ์ž…๋‹ˆ๋‹ค.

๋‹ค์‹œ ๋งํ•˜๋ฉด Adapter ํƒ€์ž…์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‚˜ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์ง์ ‘ import ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  ํ”„๋กœํ† ์ฝœ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.ย 

์ด 4๋‹จ๊ณ„๋ฅผ ํ™”๋ฉด ๋‹จ์œ„๋กœ ๋ฐ˜๋ณตํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ตฌํ˜„ ์ˆœ์„œ๊ฐ€ ๋ฐ”๊นฅ์—์„œ ์•ˆ์œผ๋กœ ์‹œ์ž‘ํ•ด์„œ ๋‹ค์‹œ ์•ˆ์—์„œ ๋ฐ”๊นฅ์œผ๋กœ ๋๋‚œ๋‹ค๋Š” ์˜๋ฏธ๋ฅผ ์ •๋ฆฌํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ๋ฐ”๊นฅ์—์„œ ์•ˆ์˜ ์ˆœ์œผ๋กœ ๊ตฌํ˜„ํ•œ๋‹ค๋Š” ๋ง์€, ๊ฐ€์žฅ ๋ฐ”๊นฅ์— ์žˆ๋Š” Driver Layer์— ๋†“์ธ ๋ทฐ์—์„œ ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ๋ฅผ ์•ˆ์ชฝ์˜ Usecase layer์— ๋†“์ธ Interactor๊ฐ€ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด Usecase ์™€ Adapter ํ”„๋กœํ† ์ฝœ์„ ์ •์˜ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ๋‹ค์‹œ ์•ˆ์—์„œ ๋ฐ”๊นฅ์˜ ์ˆœ์œผ๋กœ ๊ตฌํ˜„ํ•œ๋‹ค๋Š” ๋ง์€, Adapter ํƒ€์ž…์„ ๋จผ์ € ๊ตฌํ˜„ํ•˜๊ณ  Driver ํƒ€์ž…์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์„ ๋งํ•ฉ๋‹ˆ๋‹ค.์ด๋Ÿฌํ•œ ์ˆœ์„œ๋Š” ์‹ค์งˆ์ ์ธ ์š”๊ตฌ์‚ฌํ•ญ ํ๋ฆ„์„ ๋”ฐ๋ฅด๋Š” ๋™์‹œ์—, SOLID ์›์น™ ์ค‘ ํ•˜๋‚˜์ธ DIP(Dependency Inversion Principle)๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋”ฐ๋ฅด๊ฒŒ ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋„์ถœ๋œ ํƒ€์ž…์€ ๋ชจ๋‘ ์‹ค์ œ ์š”๊ตฌ๋กœ๋ถ€ํ„ฐ ์ถœ๋ฐœํ•ด ๋ถˆํ•„์š”ํ•œ ์ฝ”๋“œ ์ž‘์„ฑ์„ ๋ง‰์„ ์ˆ˜ ์žˆ์—ˆ๊ณ , ๊ณ„์ธต ๊ฐ„ ์˜์กด ๋ฐฉํ–ฅ๋„ ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ๊ตฌํ˜„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€

ํ…Œ์ŠคํŠธ ์ž‘์„ฑ ๋„๊ตฌ๋กœ๋Š” Quick, Nimble, Cuckoo๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

Usecase Layer์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์ง‘์ค‘์ ์œผ๋กœ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น Layer๋Š” ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ์ ์šฉ๋œ ํ•ต์‹ฌ ๋„๋ฉ”์ธ ๋กœ์ง์ด๊ธฐ ๋•Œ๋ฌธ์— ์•ˆ์ •์„ฑ์„ ํ™•๋ณดํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•œ ์œ„์น˜๋ฅผ ์ฐจ์ง€ํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  Usecase๋Š” ๊ฐœ๋ณ„ ํ…Œ์ŠคํŠธ ํƒ€๊ฒŸ์ธ LiveUsecases์—์„œ ๊ด€๋ฆฌ๋˜์—ˆ๊ณ , ํ•ด๋‹น ํƒ€๊ฒŸ๋งŒ์„ ํ…Œ์ŠคํŠธ ์‹คํ–‰ ๋Œ€์ƒ์œผ๋กœ ์ง€์ •ํ•˜์—ฌ ์ •ํ™•ํ•œ ์ปค๋ฒ„๋ฆฌ์ง€๋ฅผ ์ธก์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ, ์ด Layer์˜ ์ปค๋ฒ„๋ฆฌ์ง€๋Š” ์•ฝ 99%๋ฅผ ๊ธฐ๋กํ–ˆ์Šต๋‹ˆ๋‹ค.

์ˆ˜๋™ ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ

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

๋ฐœ๊ฒฌ ์ฆ‰์‹œ ์ˆ˜์ •๊ณผ ๋ณด์™„ ์ž‘์—…์„ ๋ณ‘ํ–‰ํ•˜์—ฌ ์•ˆ์ •์„ฑ์„ ์ ์ง„์ ์œผ๋กœ ๋Œ์–ด์˜ฌ๋ฆด ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ, ์ˆ˜๋™ ํ…Œ์ŠคํŠธ ๊ณผ์ •์€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์—†๋Š” ์˜์—ญ์„ ์‹๋ณ„ํ•˜๊ณ  ํ–ฅํ›„ ํ…Œ์ŠคํŠธ ๋ณด๊ฐ•์ด ํ•„์š”ํ•œ ์ง€์ ์„ ํŒŒ์•…ํ•˜๋Š” ๋ฐ๋„ ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ˆ˜๋™ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ

์ž๋™ํ™”๋œ ํ…Œ์ŠคํŠธ์˜ ์‹ ๋ขฐ๋„๋ฅผ ๊ฒ€์ฆํ•˜๊ณ , ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž์ฒด์— ์˜ค๋ฅ˜๊ฐ€ ์—†๋Š”์ง€๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์ˆ˜๋™์œผ๋กœ Usecase์— ๋Œ€ํ•œ TC๋ฅผ ๋ชจ๋‘ ํ…Œ์ŠคํŠธํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด 480์—ฌ๊ฐœ์˜ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๊ฐ€ ์žˆ๊ณ  ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€๋Š” 98.6 % ์ž…๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€

ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€

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

์„ฑ๊ณผ

์ด๋ฒˆ ๋ฆฌํŒฉํ„ฐ๋ง์„ ํ†ตํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฃผ์š” ์„ฑ๊ณผ๋ฅผ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์œ ์ง€๋ณด์ˆ˜์„ฑ ๊ฐ•ํ™”

  • ์ด๋ฒคํŠธ ๋ฐœ์ƒ๋ถ€ํ„ฐ UI ๋ฐ˜์˜๊นŒ์ง€์˜ ํ๋ฆ„์„ Interactor ์ค‘์‹ฌ์œผ๋กœ ์ง‘์ค‘์‹œ์ผœ, ์ฝ”๋“œ ๊ตฌ์กฐ๋ฅผ ํ•œ๋ˆˆ์— ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • Clean Architecture ๊ธฐ๋ฐ˜ ์ˆ˜ํ‰ Layer ๋ถ„๋ฆฌ๋ฅผ ์ ์šฉํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ๊ฒฐํ•ฉ๋„๋ฅผ ์ œ๊ฑฐํ–ˆ์Šต๋‹ˆ๋‹ค.
  • Pure DI๋ฅผ 100% ์ ์šฉํ•˜์—ฌ ์ฝ”๋“œ์˜ ์˜์กด์„ฑ์„ ๋ชจ๋‘ ๋“œ๋Ÿฌ๋‚ด์–ด ์ˆจ๊ฒจ์ง„ ์˜์กด์„ฑ์œผ๋กœ ์ธํ•œ ๊ฐ€๋…์„ฑ ์ €ํ•˜ ๋ฐ ๋ฒ„๊ทธ ์œ ๋ฐœ ๊ฐ€๋Šฅ์„ฑ์„ ์ค„์ผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๋ณ€๊ฒฝ์œผ๋กœ ์ธํ•œ ์˜ํ–ฅ ๋ฒ”์œ„๋ฅผ Driver Layer๋กœ ์ œํ•œํ–ˆ์Šต๋‹ˆ๋‹ค.

ํšŒ๊ท€ ๋ฒ„๊ทธ ์ตœ์†Œํ™”

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

๊ฐ์‚ฌ์˜ ๋ง

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ Clean Architecture, TDD,๋‹จ์œ„ ํ…Œ์ŠคํŠธ, Clean Swift, Pure DI ๋“ฑ ์ฒ˜์Œ ๋„์ž…ํ•˜๋Š” ๊ธฐ์ˆ ๋“ค์„ ๋น ๋ฅด๊ฒŒ ํ•™์Šตํ•˜๊ณ  ํ•จ๊ป˜ ๊ตฌํ˜„ํ•ด์ค€ iOS ํŒ€์›๋“ค์—๊ฒŒ ๊นŠ์€ ๊ฐ์‚ฌ๋ฅผ ์ „ํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ๋ฐฉ์‹์— ์—ด๋ฆฐ ๋งˆ์Œ์œผ๋กœ ์ž„ํ•ด์ค€ ๋•๋ถ„์— ๊ตฌ์กฐ์ ์ธ ๋ฆฌํŒฉํ„ฐ๋ง์„ ์™„๋ฃŒํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ , ํ”„๋กœ์ ํŠธ๋ฅผ ๋ฏฟ๊ณ  ๋งก๊ฒจ์ฃผ์‹  ํŒ€์žฅ๋‹˜๊ป˜๋„ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

๋˜ํ•œ, ๋ณธ ๋ฆฌํŒฉํ„ฐ๋ง์—์„œ ์‚ฌ์šฉ๋œ Clean Swift ๋Š” ์˜ค๋ฆฌ์ง€๋„์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐœ์„ ํ•˜์—ฌ ์›ํ‹ฐ๋“œ๋žฉ์—์„œ 2020๋…„๋ถ€ํ„ฐ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š” ํŒจํ„ด์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ , ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์— ๋งž๊ฒŒ Clean Architecture ๊ด€์ ์—์„œ ๋ณ€ํ˜•ํ•˜๊ณ  ๊ฐ•ํ™”ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด ํŒจํ„ด์˜ ์‚ฌ์šฉ์„ ํ”์พŒํžˆ ํ—ˆ๋ฝํ•ด์ฃผ์‹  ์›ํ‹ฐ๋“œ๋žฉ iOS ํŒ€์—๋„ ์ด ์ž๋ฆฌ๋ฅผ ๋นŒ๋ ค ๊ฐ์‚ฌ์˜ ๋งˆ์Œ์„ ์ „ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ์ด์•ผ๊ธฐ

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ๊ตฌ์กฐ ๊ฐœ์„ ๊ณผ ํ…Œ์ŠคํŠธ ๊ธฐ๋ฐ˜ ๋ฆฌํŒฉํ„ฐ๋ง์„ ์ค‘์‹ฌ์œผ๋กœ ์ „์ฒด์ ์ธ ํ๋ฆ„๊ณผ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๊ณต์œ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ๊ธ€์—์„œ๋Š” ์‹ค์ œ ์ฝ”๋“œ์™€ ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋ฅผ ํ•จ๊ป˜ ์†Œ๊ฐœํ•˜์—ฌ, ๋”์šฑ ์ง๊ด€์ ์œผ๋กœ ๋ฆฌํŒฉํ„ฐ๋ง ๋ฐฉ์‹๊ณผ ํŒจํ„ด์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€๋“œ๋ฆฌ๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

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

ํ•จ๊ป˜ํ•  ๋™๋ฃŒ๋ฅผ ์ฐพ๊ณ  ์žˆ์–ด์š”

fromm iOS ํŒ€์€ ํ•จ๊ป˜ ์„ฑ์žฅํ•˜๋ฉฐ ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค์–ด๊ฐˆ iOS ๋„ค์ดํ‹ฐ๋ธŒ ๊ฐœ๋ฐœ์ž๋ฅผ ์ฐพ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๊ณ ๋ฏผํ•˜๊ณ , ๋” ๋‚˜์€ ์ฝ”๋“œ๋ฅผ ํ•จ๊ป˜ ๋งŒ๋“ค์–ด๊ฐ€๋Š” ๊ณผ์ •์— ๊ด€์‹ฌ ์žˆ๋Š” ๋ถ„๋“ค์˜ ๋งŽ์€ ์ง€์›์„ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.

๐Ÿ‘‰ ๊ด€๋ จ ํฌ์ง€์…˜ ๋ฐ ์ง€์› ๋ฐฉ๋ฒ•์€ ์ฑ„์šฉ ํŽ˜์ด์ง€ ๋งํฌ๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”.

โ† ๋ชฉ๋ก์œผ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

Art Changes Life

๋…ธ๋จธ์Šค์™€ ํ•จ๊ป˜ ์—”ํ„ฐํ…Œํฌ ์‚ฐ์—…์„ ํ˜์‹ ํ•ด๋‚˜๊ฐˆ ๋ฉค๋ฒ„๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.

์ฑ„์šฉ ์ค‘์ธ ๊ณต๊ณ  ๋ณด๊ธฐ