๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ 123

[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

[Swift] Privacy Masking(Privacy Screen) ๊ตฌํ˜„ํ•˜๊ธฐ

iOS์—์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์•„๋ž˜์—์„œ ์œ„๋กœ ์Šค์™€์ดํ”„๋ž˜ ์•ฑ ์ „ํ™˜๊ธฐ(App Switcher)๋ฅผ ์—ด๋ฉด,์‹œ์Šคํ…œ์ด ํ˜„์žฌ ์•ฑ์˜ ํ™”๋ฉด ์Šค๋ƒ…์ƒท์„ ์ž๋™์œผ๋กœ ์ฐ์–ด ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ˜•ํƒœ๋กœ ๋ณด์—ฌ์ค€๋‹ค.๋ฌธ์ œ๋Š” ์ด๋•Œ ๋ฏผ๊ฐ ์ •๋ณด๊ฐ€ ๊ทธ๋Œ€๋กœ ๋…ธ์ถœ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค.์˜ˆ๋ฅผ ๋“ค์–ด ํ—ฌ์Šค ๋ฐ์ดํ„ฐ, ์‚ฌ์šฉ์ž ํ”„๋กœํ•„, ๋ฉ”์‹œ์ง€ ๋“ฑ์€ ๋ณด์•ˆ์ƒ ๊ทธ๋Œ€๋กœ ๋…ธ์ถœ๋˜๋ฉด ๊ณค๋ž€ํ•˜๋‹ค.์ด๋ฒˆ ๊ธ€์—์„œ๋Š”,์ „ํ™˜๊ธฐ๋กœ ์ด๋™ํ•  ๋•Œ ์•ฑ ํ™”๋ฉด ๋Œ€์‹  ๋””ํดํŠธ ๋กœ๊ณ  ํ˜น์€ ์›ํ•˜๋Š” UI๋ฅผ ๊ตฌ์„ฑํ•˜์—ฌ ํ•ด๋‹น ๋ทฐ๊ฐ€ ๋ณด์ด๋„๋ก ๊ฐ€๋ฆฌ๋Š” ๋ฐฉ๋ฒ•์„ UIKit ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค. (๋งˆ์ง€๋ง‰์— ๊ฐ„๋žตํ•˜๊ฒŒ SwiftUI๋„ ์žˆ์Œ) ๋™์ž‘ ์›๋ฆฌ์•ฑ์ด active → inactive ๋˜๋Š” background ์ƒํƒœ๋กœ ์ „ํ™˜๋˜๋ฉด,iOS๋Š” ํ˜„์žฌ ์œˆ๋„์šฐ๋ฅผ ๋ Œ๋”๋งํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ž๋™์œผ๋กœ ์บก์ณํ•œ๋‹ค.์ด ์Šค๋ƒ…์ƒท์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๊ต์ฒดํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•  ์ˆ˜ ์—†๊ณ ,"..

๐ŸŒ™ 2025.10.19