์ „์ฒด ๊ธ€ 124

[Swift] iOS WidgetKit์˜ ๊ฐ€๋Šฅ ๋ฒ”์œ„์™€ ํ•œ๊ณ„: ์‹ค์‹œ๊ฐ„์„ฑ, ๋ฐ์ดํ„ฐ ๊ฐฑ์‹  ์ „๋žต

iOS ์œ„์ ฏ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ๊ณผ ํ•œ๊ณ„, ๊ทธ๋ฆฌ๊ณ  ํ™œ์šฉ ์‚ฌ๋ก€iOS ์œ„์ ฏ์€ ํ™ˆ ํ™”๋ฉด ๋˜๋Š” ์ž ๊ธˆ ํ™”๋ฉด์—์„œ ์•ฑ์˜ ํ•ต์‹ฌ ์ •๋ณด๋ฅผ ๋น ๋ฅด๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋œ ์ปดํฌ๋„ŒํŠธ์ด๋‹ค. WidgetKit์€ iOS 14 ์ดํ›„ ์ง€์†์ ์œผ๋กœ ํ™•์žฅ๋˜์–ด ์™”์ง€๋งŒ, ์—ฌ์ „ํžˆ ๋ช…ํ™•ํ•œ ์ œํ•œ์ด ์กด์žฌํ•˜๋ฉฐ, ์ด ํ•œ๊ณ„๋ฅผ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์€ ์œ„์ ฏ ๊ธฐํš·๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค. ์œ„์ ฏ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ1) ์ •์ /๋ฐ˜์ •์  ์ •๋ณด์˜ ์‹œ๊ฐํ™”์œ„์ ฏ์€ ์•ฑ์˜ ์ผ๋ถ€ ์ •๋ณด๋ฅผ ๊ฐ„๋‹จํ•œ UI๋กœ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.D-Day, ์บ˜๋ฆฐ๋” ์ผ์ •, ๊ธฐ๋…์ผ์šด๋™ ๊ธฐ๋ก ์š”์•ฝ(๊ฑธ์Œ์ˆ˜, ์นผ๋กœ๋ฆฌ ๋“ฑ HealthKit ๊ธฐ๋ฐ˜ ํ†ต๊ณ„)๋‰ด์Šค ํ—ค๋“œ๋ผ์ธ, ๋‚ ์”จ ์š”์•ฝ, ์ฃผ๊ฐ€ ๋“ฑ ๊ฐ„๋‹จํ•œ ์ˆ˜์น˜ ์ •๋ณดํ•  ์ผ ๋ชฉ๋ก ์ค‘ ์ผ๋ถ€ ํ•ญ๋ชฉ์นด์šดํŠธ๋‹ค์šด ๋˜๋Š” ํŠน์ • ๋‚ ์งœ๊นŒ์ง€ ๋‚จ์€ ์‹œ๊ฐ„์ด๋Ÿฌํ•œ ์ •๋ณด๋Š” ํƒ€์ž„๋ผ์ธ ๊ธฐ..

๐ŸŒ™ 2025.12.14

[Swift] D-Day ์œ„์ ฏ ๋งŒ๋“ค๊ธฐ (2)

์•ฑ์—์„œ ์ž…๋ ฅํ•œ ์„ค์ •๊ฐ’์„ ์œ„์ ฏ์— ๋ฐ˜์˜ํ•˜๊ธฐ ์ง€๋‚œ ๊ธ€์—์„œ๋Š” ๊ธฐ๋ณธ์ ์ธ D-Day ์œ„์ ฏ UI ๊ตฌ์„ฑ๊ณผ SwiftUI ๊ธฐ๋ฐ˜์˜ WidgetKit ๋™์ž‘ ๊ตฌ์กฐ๋ฅผ ์ •๋ฆฌํ•ด๋ดค๋‹ค.์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ๋ฉ”์ธ ์•ฑ์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ D-Day ์ •๋ณด๋ฅผ ์œ„์ ฏ์— ๋ฐ˜์˜ํ•˜๋Š” ์ „์ฒด ํ๋ฆ„์„ ๊ตฌํ˜„ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.ํ•ต์‹ฌ์€ ๋‹ค์Œ ์„ธ ๊ฐ€์ง€๋‹ค.โ‘  App Group์„ ์ด์šฉํ•œ ๋ฐ์ดํ„ฐ ๊ณต์œ  (์ง€๋‚œ ๋ธ”๋กœ๊ทธ ๊ธ€์— ์žˆ์Œ)- App Group ๊ธฐ๋ฐ˜์˜ SharedStore ์„ค๊ณ„- D-Day ์„ค์ •๊ฐ’ ๋ชจ๋ธ ์ •์˜โ‘ก ๋ฉ”์ธ ์•ฑ ViewController์—์„œ ์„ค์ •๊ฐ’ ์ €์žฅโ‘ข Widget TimelineProvider์—์„œ ํ•ด๋‹น ๊ฐ’์„ ๋ถˆ๋Ÿฌ์™€ ํ‘œ์‹œ App Group ๊ธฐ๋ฐ˜์˜ SharedStore ์„ค๊ณ„์œ„์ ฏ๊ณผ ๋ฉ”์ธ ์•ฑ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์„œ๋กœ ๋…๋ฆฝ๋œ ํ”„๋กœ์„ธ์Šค์—์„œ ๋™์ž‘ํ•œ๋‹ค.๋”ฐ๋ผ์„œ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ..

๐ŸŒ™ 2025.12.01

[Swift] D-Day ์œ„์ ฏ ๋งŒ๋“ค๊ธฐ (1)

iOS์—์„œ '์œ„์ ฏ'์ด๋ผ๋Š” ๊ฐœ๋…์€ ์ƒ๊ฐ๋ณด๋‹ค ์˜ค๋ž˜๋๋‹ค.๋‹ค๋งŒ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋…ธ์ถœ๋˜๋Š” ๋ชจ์Šต๊ณผ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋‹ค๋ฃจ๋Š” ๊ธฐ์ˆ  ์Šคํƒ์€ ํฌ๊ฒŒ ๋‘ ๋ฒˆ ๋ฐ”๋€Œ์—ˆ๋‹ค.์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์œ„์ ฏ์˜ ํ๋ฆ„์„ ๊ฐ„๋‹จํžˆ ์งš๊ณ , ์™œ ์ง€๊ธˆ์€ SwiftUI ๊ธฐ๋ฐ˜์˜ WidgetKit์œผ๋กœ ๊ฐœ๋ฐœํ•ด์•ผ ํ•˜๋Š”์ง€๋ฅผ ์ •๋ฆฌํ•œ ๋’ค,์˜ˆ์ œ๋กœ D-Day ์œ„์ ฏ์„ ๊ตฌํ˜„ํ•˜๋Š” ์ˆœ์„œ๋ฅผ ๋‹จ๊ณ„๋ณ„๋กœ ์‚ดํŽด๋ณด๋ ค๊ณ  ํ•œ๋‹ค. iOS ์œ„์ ฏ์˜ ๋ณ€ํ™”์™€ WidgetKit์˜ ๋“ฑ์žฅ1. Today Extension ์‹œ์ ˆ(iOS 8 ~ iOS 13)์ดˆ๊ธฐ ์œ„์ ฏ์€ Notification Center์˜ Today View์— ์กด์žฌํ–ˆ๋‹ค.์ด ๋•Œ์˜ ์œ„์ ฏ์€- Today Extension ์ด๋ผ๋Š” ๋ณ„๋„์˜ ํƒ€๊นƒ์œผ๋กœ ๊ตฌํ˜„- UIKit + AutoLayout + Storyboard ๊ธฐ๋ฐ˜- ์•ฑ๊ณผ์˜ ์—ฐ๋™๋„ ์ง€๊ธˆ๋ณด๋‹ค ์ œ์•ฝ์ด ๋งŽ๊ณ , UI ์ž์œ ๋„๋Š”..

๐ŸŒ™ 2025.11.28

[iOS] WKWebView์—์„œ์˜ ์Šคํฌ๋กคโˆ™Bounceโˆ™SafeArea ๋™์ž‘

ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์•ฑ์„ ๊ฐœ๋ฐœํ•˜๋‹ค ๋ณด๋ฉด ์›น๋ทฐ์—์„œ ์Šคํฌ๋กค์ด ํŠ€๊ฑฐ๋‚˜,ํ‚ค๋ณด๋“œ๊ฐ€ ์˜ฌ๋ผ์˜ฌ ๋•Œ ๋ ˆ์ด์•„์›ƒ์ด ๊นจ์ง€๊ฑฐ๋‚˜,iOS Safari์™€ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ์ž์ฃผ ๋งž๋‹ฅ๋œจ๋ฆฌ๊ฒŒ ๋œ๋‹ค.ํŠนํžˆ iOS์˜ WKWebView๋Š” ์•ˆ๋“œ๋กœ์ด๋“œ WebView, ๋ธŒ๋ผ์šฐ์ € Safari์™€ ๋™์ž‘ ๋ฐฉ์‹์ด ๋ชจ๋‘ ๋‹ฌ๋ผ์„œ๊ธฐ๋Šฅ ํ•˜๋‚˜๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ๋„ ๋งŽ์€ ์ฃผ์˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.์ด๋ฒˆ ๊ธ€์—์„œ๋Š” WKWebView์˜ ์Šคํฌ๋กค ๋™์ž‘๊ณผ ๊ด€๋ จํ•ด ๊ฐ€์žฅ ๋งŽ์ด ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋“ค์„ ์ •๋ฆฌํ•˜๋ ค๊ณ  ํ•œ๋‹ค. WKWebView ์Šคํฌ๋กค์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ webView.scrollView- WKWebView ์ž์ฒด๋Š” ์Šคํฌ๋กค์„ ํ•˜์ง€ ์•Š๋Š”๋‹ค.- ๋‚ด๋ถ€์˜ UIScrollView๊ฐ€ ๋ชจ๋“  ์Šคํฌ๋กคโˆ™๋ฐ”์šด์Šคโˆ™์ปจํ…์ธ  inset ์กฐ์ •์„ ๋‹ด๋‹นํ•œ๋‹ค.- ๊ทธ๋ž˜์„œ ๋Œ€๋ถ€๋ถ„์˜ ์Šคํฌ๋กค ์กฐ์ž‘โˆ™์„ค์ •์€ ์ด ๊ฐ์ฒด์— ๋Œ€ํ•ด ์ด๋ฃจ์–ด์ง„๋‹ค.webView...

๐ŸŒ™ 2025.11.17

[Swift] Swift Concurrency ์™„์ „ ์ •๋ณต

async/await๋ถ€ํ„ฐ actor๊นŒ์ง€, ๋™์‹œ์„ฑ์˜ ์ง„์งœ ๋™์ž‘ ์›๋ฆฌSwift 5.5 ์ดํ›„ ๋“ฑ์žฅํ•œ Concurrency(๋™์‹œ์„ฑ)๋Š” iOS ๊ฐœ๋ฐœ์˜ ํŒจ๋Ÿฌ๋‹ค์ž„์„ ์™„์ „ํžˆ ๋ฐ”๊ฟ”๋†“์•˜๋‹ค.์ด์ „์—๋Š” ์ฝœ๋ฐฑ, completion handler, GCD(DispatchQueue)๋กœ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ œ์–ดํ–ˆ์ง€๋งŒ,์ด์ œ๋Š” ์–ธ์–ด ์ˆ˜์ค€์—์„œ ์•ˆ์ „ํ•˜๊ณ  ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋น„๋™๊ธฐ๋ฅผ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.์ด๋ฒˆ ๊ธ€์—์„œ๋Š” async/await, Task, actor๋ฅผ ์ค‘์‹ฌ์œผ๋กœ"Swift ๋™์‹œ์„ฑ์ด ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”๊ฐ€"๋ฅผ ์‹ค๋ฌด ๊ฐœ๋ฐœ์ž ๊ด€์ ์—์„œ ์ •๋ฆฌํ•˜๋ ค๊ณ  ํ•œ๋‹ค. ์™œ Concurrency์ธ๊ฐ€?๊ธฐ์กด GCD ๊ธฐ๋ฐ˜ ์ฝ”๋“œ์˜ ๋ฌธ์ œ์ ์€ ๋ช…ํ™•ํ•˜๋‹ค.DispatchQueue.global().async { let data = fetchData() DispatchQueue.ma..

๐ŸŒ™ 2025.11.11

iOS ์›น๋ทฐ ์ƒ๋‹จ ๋…ธ์น˜ ๋Œ€์‘ํ•˜๊ธฐ

iPhone X ์ดํ›„ ์ถœ์‹œ๋œ ๊ธฐ๊ธฐ๋“ค์€ ๋ชจ๋‘ ๋…ธ์น˜(Notch) ์˜์—ญ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.์ด ์˜์—ญ์€ ์ƒํƒœ๋ฐ”(Status Bar)์™€ ์„ผ์„œ ํ•˜์šฐ์ง• ๋•Œ๋ฌธ์— ํ™”๋ฉด์˜ ์•ˆ์ „ ํ‘œ์‹œ ์˜์—ญ(SafeArea)์ด ๋‹ฌ๋ผ์กŒ์Œ์„ ์˜๋ฏธํ•œ๋‹ค.์•ฑ์„ ์›น๋ทฐ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์„ฑํ–ˆ๋‹ค๋ฉด, ์ด ์ฐจ์ด๋ฅผ ๋ช…ํ™•ํžˆ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์œผ๋ฉด ์›น ์ฝ˜ํ…์ธ ๊ฐ€ ๋…ธ์น˜์— ๊ฐ€๋ ค์ง€๊ฑฐ๋‚˜ ์ƒ๋‹จ์ด ์ž˜๋ฆฌ๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.์ด๋ฒˆ ๊ธ€์—์„œ๋Š” WKWebView ๊ธฐ๋ฐ˜ ์•ฑ์—์„œ ์ƒ๋‹จ ๋…ธ์น˜ ์•ˆ์ „์˜์—ญ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •๋ฆฌํ•˜๋ ค๊ณ  ํ•œ๋‹ค. ๋ฌธ์ œ ์ƒํ™ฉ - ์›น๋ทฐ๋ฅผ ์ „์ฒด ํ™”๋ฉด์œผ๋กœ ์ฑ„์šฐ๊ธฐwebView.snp.makeConstraints { $0.edges.equalToSuperview()}์ด๋ ‡๊ฒŒ ํ•˜๋ฉด iPhone 15 Pro์™€ ๊ฐ™์€ ๊ธฐ๊ธฐ์—์„œ ์›น ์ฝ˜ํ…์ธ ๊ฐ€ ๋…ธ์น˜ ์˜์—ญ ๋ฐ‘์œผ๋กœ ๋“ค์–ด๊ฐ€ ๋ฒ„๋ฆฐ๋‹ค.๊ฒฐ๊ณผ์ ์œผ๋กœ H..

๐ŸŒ™ 2025.11.07

[Swift] Actor, isolated, nonisolated

Swift Concurrency๊ฐ€ ๋„์ž…๋œ ์ดํ›„,actor์™€ isolated, nonisolated ํ‚ค์›Œ๋“œ๋Š” ๋น„๋™๊ธฐ ์•ˆ์ „์„ฑ์˜ ํ•ต์‹ฌ ๊ฐœ๋…์œผ๋กœ ์ž๋ฆฌ ์žก์•˜๋‹ค.ํ•˜์ง€๋งŒ ์ด ํ‚ค์›Œ๋“œ๋“ค์ด ์ •ํ™•ํžˆ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๊ณ , ์–ธ์ œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ํ˜ผ๋™ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.์ด๋ฒˆ ๊ธ€์—์„œ๋Š” 'Actor ๊ฒฉ๋ฆฌ(Actor Isolation)'์˜ ๊ฐœ๋…์„ ์ค‘์‹ฌ์œผ๋กœ ๋ช…ํ™•ํžˆ ์ •๋ฆฌํ•˜๊ณ ์ž ํ•œ๋‹ค. Actor๋ž€ ๋ฌด์—‡์ธ๊ฐ€? actor๋Š” '๋ฐ์ดํ„ฐ ๊ฒฝ์Ÿ(Data Race)'์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•œ ์ผ์ข…์˜ "์ƒํƒœ ๋ณดํ˜ธ ๊ฐ์ฒด"์ด๋‹ค.ํด๋ž˜์Šค์™€ ์œ ์‚ฌํ•˜์ง€๋งŒ, actor๋Š” ๋‚ด๋ถ€ ์ƒํƒœ์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ์ž๋™์œผ๋กœ ์ง๋ ฌํ™”ํ•œ๋‹ค.์ฆ‰, ํ•œ ์‹œ์ ์— ํ•˜๋‚˜์˜ task๋งŒ ๊ทธ ์ƒํƒœ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.actor Counter { private var value = 0 func increm..

๐ŸŒ™ 2025.10.28

[Swift] iOS ์ƒ์ฒด์ธ์ฆ ๊ถŒํ•œ์€ '๊ฑฐ๋ถ€' ์ƒํƒœ๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์—†๋‹ค?

๊ถŒํ•œ์ด ์žˆ๋Š”๋ฐ ์™œ ์•ˆ๋ผ์š”?์•ฑ์—์„œ FaceID๋‚˜ TouchID ์ธ์ฆ์„ ์‹œ๋„ํ•  ๋•Œ,์ผ๋ถ€ ์‚ฌ์šฉ์ž ํ™˜๊ฒฝ์—์„œ OS ํŒ์—…์ด ๋œจ์ง€ ์•Š๊ฑฐ๋‚˜, canEvaluatePolicy๊ฐ€ ์‹คํŒจํ•˜๋Š” ๊ฒฝํ—˜์ด ์žˆ๋‹ค.ํŠนํžˆ ์•„๋ž˜์™€ ๊ฐ™์€ ์ƒํ™ฉ์ด ํ˜ผ๋™์„ ์ค€๋‹ค.์‚ฌ์šฉ์ž๊ฐ€ ์ฒ˜์Œ์œผ๋กœ ์ƒ์ฒด ์ธ์ฆ ์„ค์ •์„ ํ•˜์ง€ ์•Š์€ ์ƒํƒœ์‚ฌ์šฉ์ž๊ฐ€ ์„ค์ •์—์„œ ์ƒ์ฒด ์ธ์ฆ์„ ๊บผ ๋‘” ์ƒํƒœ์‚ฌ์šฉ์ž๊ฐ€ ๊ถŒํ•œ์„ ๊ฑฐ๋ถ€ํ•œ ์ƒํƒœ๊ธฐ๊ธฐ ์ž์ฒด์— ์ƒ์ฒด ์ •๋ณด(์ง€๋ฌธ/์–ผ๊ตด)๊ฐ€ ๋“ฑ๋ก๋˜์–ด ์žˆ์ง€ ์•Š์€ ์ƒํƒœ์ด ์ค‘ ์–ด๋–ค ๊ฒฝ์šฐ๋“  iOS๋Š” ๊ฐœ๋ฐœ์ž์—๊ฒŒ "๊ฑฐ๋ถ€๋จ"์ด๋ผ๋Š” ๋ช…ํ™•ํ•œ ์ƒํƒœ๋ฅผ ์•Œ๋ ค์ฃผ์ง€ ์•Š๋Š”๋‹ค.๊ฒฐ๊ตญ, ์šฐ๋ฆฌ๋Š” OS ์ •์ฑ… ์•ˆ์—์„œ ์ƒํƒœ๋ฅผ "์ถ”์ •"ํ•ด์•ผ ํ•œ๋‹ค.Apple์˜ ์„ค๊ณ„ ์ฒ ํ•™๊ณผ ์‹ค์ œ ์ฝ”๋“œ๐Ÿคฆ๐Ÿป‍โ™€๏ธ LAContext์˜ ํ•œ๊ณ„let context = LAContext()var error: NSError?context.can..

๐ŸŒ™ 2025.10.26