๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐ŸŽ ๊ฐœ๋ฐœ29

[iOS]Unit Test์˜ ์‚ฌ์šฉ ์ด๋ฒˆ ๊ณผ์ œ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ๊ฐ€์žฅ ํ•„์š”์„ฑ์„ ์ ˆ์‹คํžˆ ๋Š๊ผˆ๋˜ ๊ฒƒ์ด ๋ฐ”๋กœ ์ด test์˜€๋‹ค. ์—ฌ๊ธฐ๊นŒ์ง€๋Š” ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์„, ์•ˆ์ „ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ํ™•์‹ ํ•˜๊ณ  ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์งœ๊ณ  ์‹ถ์€ ๊ทธ ๋งˆ์Œ..!! ๊ทธ๋Ÿฐ๋ฐ ๋งˆ์นจ ํ™œ๋™ํ•™์Šต์—์„œ Unit Test์™€ TDD๊ฐ€ ๋‚˜์™”๊ธธ๋ž˜, ์ •๋ฆฌํ•ด๋ณด์•˜๋‹ค. Unit Test Unit Test๋Š” ๋ฉ”์„œ๋“œ๋ณ„ ๊ธฐ๋Šฅ์ด ์˜๋„ํ•œ ๋Œ€๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ๋Š”์ง€ ๊ฒ€์ฆํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์†Œ์Šค ์ฝ”๋“œ์˜ ํŠน์ • ๋ชจ๋“ˆ์ด ์˜๋„๋œ๋Œ€๋กœ ์ •ํ™•ํžˆ ์ž‘๋™ํ•˜๋Š”์ง€ ๊ฒ€์ฆํ•˜๋Š” ์ ˆ์ฐจ๋ฅผ ํ†ตํ•ด ์ž‘์„ฑํ•œ ์ฝ”๋“œ์˜ ์•ˆ์ •์„ฑ์„ ๋ถ€์—ฌํ•œ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ค Test๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ• ๊นŒ? FIRST ์›์น™ Fast ๋น ๋ฅด๊ฒŒ Independent / Isolated ๋…๋ฆฝ์ ์œผ๋กœ Repeatable ๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•œ Self-Validating ์Šค์Šค๋กœ ๊ฒ€์ฆํ•˜๋Š” Timely ์ ์‹œ์— F. ํ…Œ์ŠคํŠธ๋ผ๋Š” ๋ชฉ์ ์— ๋งž.. 2024. 2. 5.
[iOS] UICollectionViewFlowLayout์œผ๋กœ Pinterest Layout ๊ตฌํ˜„ํ•˜๊ธฐ ์ฒ˜์Œ ๊ณผ์ œ๋กœ ๋ฐ›์€ ํ”ผ๊ทธ๋งˆ์— Pinterest๋กœ ๊ตฌํ˜„๋œ View๋ฅผ ๋ณด๊ณ , Compositional๋กœ ๋„์ „ํ•ด์•ผ์ง€! ๋ผ๊ณ  ํ˜ธ๊ธฐ๋กญ๊ฒŒ ์ƒ๊ฐํ–ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Compositional์˜ ๋ฒฝ์€ ๋†’์•˜๊ณ .. item๊ณผ group, section์œผ๋กœ ํฌ๊ธฐ๋ฅผ ์ฃผ๋Š” ๊ฒƒ์—์„œ item ํฌ๊ธฐ๋“ค์„ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅด๊ฒŒ ์ค˜์•ผ ํ• ์ง€ ๊ฐ์ด ์•ˆ ์žกํžˆ๋”๋ผ. Section๋ณ„๋กœ๋Š” ์‰ฌ์šด๋ฐ!! ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์„ ๊นŒ๋ณด๋ฉด, Compositional + Combine์˜ ์กฐํ•ฉ์œผ๋กœ pinterest๊ฐ€ ๊ตฌํ˜„๋˜์–ด ์žˆ์—ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ RxSwift๋‚˜ Combine์„ ์•„์ง ์ž˜ ๋ชจ๋ฅด๋Š”๋ฐ, ๊ณผ์ œ ๊ธฐ๊ฐ„์€ ๋งค์šฐ ์งง์•˜๊ธฐ์— ์ฐจ๋งˆ ์ด๋ฒˆ์— ๋„์ „ํ•  ์ž์‹ ์€ ์—†์—ˆ๋‹ค. ์ด๋ฏธ collectionView, diffable data source, compositional ๋“ฑ ์ฒ˜์Œ ์จ๋ณด๋Š” ๊ฒƒ์ด ์‚ฐ๋”๋ฏธ..... 2024. 1. 31.
[NSCache&URLCache]์™œ ์ด๋ฏธ์ง€ ํŒŒ์ผ์ด URLCache์—์„œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์•„๋‹Œ ๋””์Šคํฌ์— ์ €์žฅ๋ ๊นŒ? ์•ˆ๋…•ํ•˜์‹ญ๋‹ˆ๊นŒ, ๋ฏผํŠธ์ž…๋‹ˆ๋‹ค. ๐Ÿ˜ˆ๋ฐ์ดํ„ฐ๋“ค์€ ์–ด๋””์— ์ €์žฅ๋˜๊ณ  ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋ ๊นŒ์š”?๋จผ์ € ํ•˜๋“œ ๋””์Šคํฌ์— ์šฐ๋ฆฌ์˜ ๋ฐ์ดํ„ฐ๋“ค์ด ์ „๋ถ€ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ๋•Œ๋ฌธ์— ํ•˜๋“œ ๋””์Šคํฌ๋Š” ์šฉ๋Ÿ‰์ด ๋งค์šฐ ํฌ๊ณ , ๊ธฐ์–ต์„ ํ•˜๋Š” ๊ฒƒ์— ์น˜์ค‘๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.RAM, ๋ฉ”๋ชจ๋ฆฌ๋Š” ๊ทธ๋Ÿฌํ•œ ํ•˜๋“œ ๋””์Šคํฌ์—์„œ ์•ฑ์„ ์‹คํ–‰ํ•˜๋Š”๋ฐ์— ํ•„์š”ํ•œ ์ค‘์š” ๋ฐ์ดํ„ฐ๋“ค์„ ๋“ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์—ฌ์ „ํžˆ ๋‚ด์šฉ์€ ๋ฐฉ๋Œ€ํ•˜๊ณ , RAM์€ ๋””์Šคํฌ๋ณด๋‹จ ๊ธฐ์–ตํ•  ์ˆ˜ ์žˆ๋Š” ์–‘์ด ์ ๊ณ , CPU์™€ ๊ฐ€๊นŒ์›Œ์„œ ๋น ๋ฅด์ง€๋งŒ ์–ด์ฐŒ ๋˜์—ˆ๊ฑด ๊ธฐ์–ต์„ ํ•˜๋Š” ๊ฒƒ์—๋งŒ ๋Šฅ๋ ฅ์ด ์น˜์ค‘๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.CPU๋Š” RAM์—์„œ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋“ค์„ ์ด์šฉํ•ด ์•ฑ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์–ต๋ณด๋‹ค๋Š” ์„ฑ๋Šฅ์ด ์ค‘์š”ํ•ด, ๊พธ์ค€ํ•˜๊ฒŒ ์„ฑ๋Šฅ์ด ์—…๊ทธ๋ ˆ์ด๋“œ ๋˜์–ด ์™”์Šต๋‹ˆ๋‹ค. ๋•Œ๋ฌธ์— RAM๊ณผ CPU๋Š” ๊ธฐ์–ต๊ณผ ์„ฑ๋Šฅ์œผ๋กœ ๊ฐ์ž์˜ ๋ชฉ์ ์ด ๋‹ค๋ฅด๊ธฐ์— ์„œ๋กœ์„œ๋กœ ์„ฑ๋Šฅ์ฐจ์ด๊ฐ€ ์ ์  ์‹ฌํ•˜๊ฒŒ ๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. .. 2024. 1. 28.
[iOS] Test ํŒŒ์ผ์„ ๋„ฃ์„ Asset ์ƒ์„ฑ์‹œ ์˜ค๋ฅ˜_ Bundle ์‚ฌ์šฉ ํ…Œ์ŠคํŠธ์šฉ JSON ํŒŒ์ผ์€ ์ดํ›„์—๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๊ธฐ์— test ํด๋”์— ๋”ฐ๋กœ Asset catalog๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ทธ๊ณณ์—์„œ๋งŒ ๋„ฃ์–ด๋‘๊ณ  ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค. ๋•Œ๋ฌธ์— ํด๋”๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์„œ ์ด๋ฆ„์„ Json.xcassets ์œผ๋กœ ์„ ์–ธํ•˜๊ณ  ๊ทธ ์•ˆ์— ํŒŒ์ผ์„ ๋„ฃ์—ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ asset catalog์˜ ๋ชจ์–‘์ด ๊ธฐ์กด์˜ ๊ฒƒ๊ณผ๋Š” ๋‹ฌ๋ž๋‹ค. ํ™•์ธํ•ด๋ณด๋‹ˆ asset catalog๋ฅผ ๋งŒ๋“ค๋•Œ๋Š” ๋‹จ์ˆœํ•˜๊ฒŒ ํด๋”๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ File → New → File์„ ํƒ€๊ณ  ๋“ค์–ด๊ฐ€ Resource์˜ Asset Catalog๋ฅผ ์„ ํƒํ•˜์—ฌ ๋งŒ๋“ค์–ด์•ผ ํ–ˆ๋‹ค. ๊ทธ ํ›„ test code๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ๋Œ๋ฆฌ๋Š”๋ฐ ์ด๋ฒˆ์—๋Š” NSDataAsset์„ ๊ฐ€์ ธ์˜ค๋Š” guard๋ฌธ์—์„œ ๊ณ„์† retrun์œผ๋กœ ๋น ์ง€๋ฉฐ ์ข…๋ฃŒ๋˜์—ˆ๋‹ค. guard let json = NSDataAsset(n.. 2024. 1. 28.
[UIKit]loadView์— view๋Š” ์–ธ์ œ ํ• ๋‹น๋ ๊นŒ? ์•ˆ๋…•ํ•˜์‹ญ๋‹ˆ๊นŒ, ๋ฏผํŠธ์ž…๋‹ˆ๋‹ค. ๐Ÿ˜ˆloadView์— View๋Š” ์–ธ์ œ ํ• ๋‹น๋ ๊นŒ์š”?์ฝ”๋“œ๋ฒ ์ด์Šค๋กœ ์ง  ์ฝ”๋“œ์—์„œ ์‹คํ—˜ํ•ด ๋ณธ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. ์˜ˆ์ƒ์œผ๋กœ๋Š”, super.loadView()๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” view๊ฐ€ nil์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ’์ด ์—†์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋•Œ๋ฌธ์— LLDB๋กœ view๋ฅผ loadView() ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์ฐ์–ด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์˜ˆ์ƒ๊ณผ๋Š” ๋‹ค๋ฅธ ์ผ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. super.loadView()๊ฐ€ ๋ถˆ๋ฆฌ๊ธฐ ์ „์— po view๋กœ ์ฐ์–ด๋ณด๋‹ˆ, loadView์™€ loadView๋์ด ์ฐํžˆ๋”๋‹ˆ, ๊ฐ’์ด ๋œจ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค! ์ฐธ๊ณ ๋กœ ์˜†์— UIViewController์˜ view๋Š” (id) 0x0์œผ๋กœ ํ• ๋‹น๋˜์–ด ์žˆ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์˜ค๋ฅ˜์ธ๊ฐ€? ์™œ view๊ฐ€ ์ฐํžˆ์ง€?๊ทธ๋ž˜์„œ loadView()๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ์ฐ์–ด๋ณด๊ณ  ํ•˜๋‚˜์”ฉ ๋‚ด๋ ค๊ฐ€๋ฉด์„œ po v.. 2024. 1. 27.
[๋””์ž์ธ ํŒจํ„ด]Delegate Pattern delegate pattern์€ ์ฃผ๋กœ ํ™”๋ฉด์˜ ์ „ํ™˜์—์„œ ์‚ฌ์šฉ๋œ๋‹ค. ํ™”๋ฉด์€ ์–ด๋–ป๊ฒŒ ์ „ํ™˜๋ ๊นŒ? 1๋ฒˆ ํ™”๋ฉด๊ณผ 2๋ฒˆ ํ™”๋ฉด์ด ์žˆ๋‹ค. ๋‹ค์‹œ ๋งํ•ด, 1๋ฒˆ view controller์™€ 2๋ฒˆ view controller๊ฐ€ ์žˆ๋‹ค. 1๋ฒˆ view controller์—์„œ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ 2๋ฒˆ view controller๋กœ ํ™”๋ฉด์ด ๋„˜์–ด๊ฐˆ ๋•Œ, 1๋ฒˆ ํ™”๋ฉด์€ ๋‹จ์ˆœํžˆ ์‚ฌ๋ผ์ง€๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. 2๋ฒˆ ํ™”๋ฉด์ด 1๋ฒˆ ํ™”๋ฉด์˜ ์œ„์— ์Œ“์ด๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋•Œ 2๋ฒˆ ํ™”๋ฉด์ด ์ƒ๊ธฐ๋ฉด์„œ 2๋ฒˆ view conroller๋Š” ์ดˆ๊ธฐํ™”๋˜์–ด ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์œผ๋กœ 1๋ฒˆ view controller๋กœ๋ถ€ํ„ฐ ์ •๋ณด๋“ค์„ ๋ฐ›์•„์˜ค๊ฒŒ ๋œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋งŒ์ผ 2๋ฒˆ ํ™”๋ฉด์—์„œ ๋’ค๋กœ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์œผ๋กœ ๋‹ค์‹œ 1๋ฒˆ ํ™”๋ฉด์œผ๋กœ ๋Œ์•„๊ฐ€๊ฒŒ ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? 1๋ฒˆ ํ™”๋ฉด์ด ๋‚˜์˜ค๋ฉด์„œ ์ƒˆ๋กญ๊ฒŒ 1๋ฒˆ view contro.. 2024. 1. 27.
[๋””์ž์ธ ํŒจํ„ด]Observer Pattern ์˜ท๊ฐ€๊ฒŒ์—์„œ ์ผํ•  ๋•Œ ์žˆ์—ˆ๋˜ ์ผ์ด๋‹ค. ์šฐ๋ฆฌ๋Š” ๋ฌด์ž‘์œ„์ ์œผ๋กœ ํ• ์ธ ํ–‰์‚ฌ๋ฅผ ์—ด์—ˆ๋Š”๋ฐ ํƒ€์ด๋ฐ์„ ๋†“์นœ ์†๋‹˜๋“ค์ด ํ•œ๊ฒฐ๊ฐ™์ด ํˆฌ๋œ๊ฑฐ๋ฆฌ๊ณ ๋Š” ํ–ˆ๋‹ค. ํ• ์ธ ํ•  ๋•Œ ๋ฌธ์ž ์ข€ ์ฃผ๋ฉด ์ข‹๊ฒ ๋‹ค๊ณ . ๋งค๋ฒˆ ๋ฉฐ์น  ์ „๊นŒ์ง€ ํ• ์ธ ํ–ˆ๋‹ค๋Š” ๊ฑธ ์•Œ๊ณ  ๋‚˜๋ฉด ์†์ƒํ•˜๋‹ค๊ณ . ์˜ต์ €๋ฒ„ ํŒจํ„ด์€ ์ด๋Ÿฌํ•œ ์†๋‹˜๋“ค์„ ์œ„ํ•œ ๋ฌธ์ž ๋ฐœ์†ก๊ณผ ๊ฐ™๋‹ค. “๊ด€์ฐฐ์ž”๋ผ๋Š” ๋‹จ์–ด๋ฅผ ๋ณด๋ฉด ํ•ด๋‹น ์ด๋ฆ„ํ‘œ๋ฅผ ๋‹ฌ๊ณ  ์žˆ๋Š” ๊ฐ์ฒด๋Š” ์–ด๋– ํ•œ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•  ๊ฒƒ ๊ฐ™์€๊ฐ€? ๋ˆ„๊ตฐ๊ฐ€๋ฅผ ๋ฉด๋ฐ€ํžˆ ์ง€์ผœ๋ณด๋Š” ์—ญํ• ์€ ์•„๋‹๊นŒ? ์˜ต์ €๋ฒ„ ํŒจํ„ด์—์„œ๋Š” ์ด ์˜ต์ €๋ฒ„์˜ ์˜๋ฏธ๊ฐ€ ์กฐ๊ธˆ ๋‹ค๋ฅด๋‹ค. ๋‹จ์ˆœํžˆ ์ง€์ผœ๋ณธ๋‹ค, ๋ณด๋‹ค๋Š” `์—ฐ๋ฝ์„ ๊ธฐ๋‹ค๋ฆฐ๋‹ค`๋ผ๋Š” ๊ฒƒ์ด ๋” ์˜ณ์€ ํ‘œํ˜„์ผ ๊ฒƒ์ด๋‹ค. ๋งˆ์น˜ ์˜ท๊ฐ€๊ฒŒ ํ• ์ธ ํ–‰์‚ฌ ๋ฌธ์ž๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์†๋‹˜๊ณผ ๊ฐ™๋‹ค. ์˜ท๊ฐ€๊ฒŒ๋ฅผ ์ฃผ์‹œํ•˜๊ณ , ๊ด€์ฐฐํ•˜์ง€๋งŒ ๊ฒฐ๊ตญ ์˜ท๊ฐ€๊ฒŒ์—์„œ ๋ฌธ์ž๋ฅผ ๋ณด๋‚ด์ฃผ์–ด์•ผ ์†๋‹˜์€ ํ–‰๋™์„ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ท๊ฐ€๊ฒŒ๋ฅผ ๋“ค๋ฆด์ง€, .. 2024. 1. 27.
[iOS] TableViewCell์—์„œ layoutMarginsGuide ์‚ฌ์šฉ ํ…Œ์ด๋ธ”๋ทฐ์˜ Custom Cell์„ ์„ค์ •ํ•  ๋•Œ ์ฒ˜์Œ์— ์ œ์•ฝ์กฐ๊ฑด์„ ContentView์—๋งŒ ๋งž์ท„๋‹ค. private func configureCellConstraint() { NSLayoutConstraint.activate([ contentStackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), contentStackView.topAnchor.constraint(equalTo: contentView.topAnchor), contentStackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), contentStackView.bottomAnchor.constraint(e.. 2024. 1. 6.
[iOS] CoreData์—์„œ ํŠน์ • Entity ๋‚ด๋ถ€์— ์žˆ๋Š” Entity์˜ ํŠน์ •๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ณ  ์‹ถ์„ ๋•Œ(NSPredicate) ์ฝ”์–ด๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์—ฐ์Šตํ•˜๋‹ค๊ฐ€ ์ƒ๊ธด ์ผ์ด๋‹ค. ๋จผ์ € entity๋กœ๋Š” UserMO์™€ JokeMO ๋‘๊ฐœ๊ฐ€ ์žˆ๋‹ค. User์™€ Joke๋Š” Model๋„ ์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด User๋Š” Joke ๋ฐฐ์—ด์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๋•Œ๋ฌธ์— ํŠน์ •ํ•œ User์˜ ํŠน์ • ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ๊ฐ–๋Š” Joke๋งŒ ์„ ๋ณ„ํ•˜๊ณ  ์‹ถ์€ ๊ณผ์ •์—์„œ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค. func fetchWithPredicate(currentUser: User, currentCategory: Category) -> [Joke] { var jokes = [Joke]() let fetchRequest: NSFetchRequest = UserMO.fetchRequest() let idPredicate = NSPredicate(format: "id = %@", currentUs.. 2023. 12. 20.