진재명의 블로그

글.

만들면서 알게 된 것들을 적어 둡니다.

iOS와 소프트웨어, 그리고 덜어내는 일에 대한 기술 노트와 짧은 생각. 부산에서.

IT/기술

macOS 27에서 끊긴 Time Capsule 백업, TimeCapsuleSMB로 되살린 기록

macOS 27은 AFP 클라이언트를 제거해 Time Capsule을 Time Machine 대상으로 쓸 수 없습니다. 4세대 Time Capsule에 TimeCapsuleSMB로 SMB3 Samba를 올린 절차와, 설치 전에 꺼야 할 NBNS·텔레메트리 설정을 정리합니다.

IT/개발

READY_FOR_REVIEW는 «제출됨»이 아니다: App Store Connect 제출을 멱등하게 만들기

응답이 유실되면 재실행이 중복 제출로 거부되어, 복구용 재시도가 오히려 확실한 실패가 됐습니다. 멱등 가드를 붙였더니 이번엔 그 가드가 세 가지 방향으로 배신했습니다.

IT/개발

UMP가 ATT를 직접 부른다: 프레임워크 바이너리로 확인한 순서 계약

AdMob IDFA 설명 메시지를 게시하려다 막혔습니다. 어느 쪽이 requestTrackingAuthorization을 부르는지 공식 문서에 없어서 UMP 프레임워크 바이너리를 읽었고, 거기서 앱과 SDK가 일회성 프롬프트를 두고 경합한다는 걸 확인했습니다.

IT/개발

경고 주석은 있는데 대조는 없었다: ITSAppUsesNonExemptEncryption 두 원천 검증

수출 규정 선언은 Info.plist와 제출 선언 파일 두 곳에 있습니다. 어긋나면 자동 제출이 멈추는데, 「한쪽만 고치지 말 것」이라는 경고 주석만 있고 실제로 대조하는 코드는 없었습니다.

IT/개발

@Suite(.serialized)로는 못 막는다: Swift Testing 병렬 실행과 전역 NotificationCenter

CI에서만 죽는 테스트 하나를 쫓다 45분 hang의 원인을 두 번 진단했습니다. 첫 진단은 hang만 고쳤고, 진짜 원인은 전역 NotificationCenter를 구독하는 뷰와 병렬 실행이 만든 격리 결함이었습니다.

IT/개발

이미 만료된 Task.sleep은 throw하지 않는다: 버전당 1회 리뷰 요청 지키기

AppStore.requestReview(in:)는 실패를 알려주지 않는데 게이트는 버전당 1회입니다. 같은 설계를 iOS와 Android에 옮겼더니 Swift Concurrency와 Kotlin의 취소 의미론 차이로 iOS에만 결함이 남았습니다.

IT/개발

Apple Pencil 손글씨 숫자 입력: PencilKit·Core ML reject 설계

PencilKit stroke를 스도쿠 숫자 입력으로 바꿀 때 필요한 tap·ink 세션 분류, 28×28 전처리, confidence reject, 비동기 추론 계약을 DailySudoku 구현으로 살펴봅니다.

IT/개발

픽셀보다 계약: UIKit·Jetpack Compose 스도쿠 보드 접근성

하나의 9×9 커스텀 보드를 VoiceOver와 TalkBack이 탐색할 수 있는 81개 셀로 바꾸고, 위치·값·선택·오류·입력 동작을 두 플랫폼에 매핑하는 기준을 정리합니다.

IT/기술

iOS·Android·Web 광고 노출: loaded·rendered·impression 구분법

광고 SDK의 load·impression·paid callback과 Web 가시성 신호를 분리해, 자동 수집과 수동 로깅이 중복되지 않는 이벤트 계약을 정리합니다.

IT/기술

Game Center·Play Games 리더보드: 날짜 경계·제출 신뢰성

퍼즐 날짜, 점수 제출 시각, 플랫폼 표시 구간을 분리하고 best-effort 보류와 durable outbox 사이에서 리더보드 전달 보장을 선택하는 방법을 정리합니다.

IT/개발

같은 날, 같은 퍼즐: generatorVersion이 있는 PuzzleIdentity 설계

같은 seed를 재현하는 것과 같은 퍼즐을 영구히 식별하는 것은 다르다. DailySudoku의 날짜·시간대·난이도·생성기 흐름을 바탕으로 generatorVersion, 마이그레이션, 롤백 계약을 정리합니다.

IT/기술

위치 권한 없이 광고를 지역화하기: GeoIP와 Provider Chain 설계

OS 위치 권한 없이 동의 상태와 GeoIP 힌트로 광고 Provider Chain을 구성하고, 실패를 안전하게 흡수하는 방법을 정리합니다.

IT/개발

일회성 광고 제거 IAP: StoreKit 2·Play Billing에서 구매와 권한 분리하기

결제 완료 콜백을 영구 권한으로 착각하지 않고, 앱 시작·다른 기기·pending·환불 뒤에도 광고 제거 상태를 다시 맞추는 StoreKit 2와 Play Billing 계약을 정리합니다.

IT/기술

검증 스크립트가 성공을 거짓말할 때: Negative Control과 Mutation으로 자기검증하기

검증 스크립트가 실제 결함을 탐지하는지 Negative Control과 입력 Mutation으로 확인하고, baseline과 실패 계약을 CI에 고정하는 방법을 정리합니다.

IT/개발

재시도 Cron은 자기 죽음을 알릴 수 없다: Watch the Watcher 설계

기록된 job ID와 live scheduler 상태를 대조하고, 작업의 존재·실행·성공·업무 진척을 분리해 사라진 재시도 작업을 찾는 최소 운영 계약을 정리합니다.

IT/기술

Rust 공통 모듈을 크로스플랫폼에서 공유하기 - 7편. 테스트와 CI로 같은 결과 보장하기

Rust 공통 모듈이 iOS·Android·Web에서 같은 결과를 내도록 cargo test, golden fixture, 플랫폼별 CI job 분리, release checklist를 어떻게 나눌지 정리합니다.

IT/기술

Rust 공통 모듈을 크로스플랫폼에서 공유하기 - 6편. WebAssembly로 Web에 배포하기

Rust 공통 모듈을 WebAssembly로 빌드해 Web 앱의 도메인 엔진으로 쓰는 구조를 wasm-bindgen, wasm-pack, browser 초기화 경계, FFI 계약, fixture 공유 기준으로 정리합니다.

IT/기술

Rust 공통 모듈을 크로스플랫폼에서 공유하기 - 5편. Android 네이티브 라이브러리 패키징

Rust 공통 모듈을 Android 앱에 넣을 때 ABI별 .so, Gradle task, UniFFI adapter, 16 KB page size 검증을 release artifact 기준으로 정리합니다.

IT/기술

Rust 공통 모듈을 크로스플랫폼에서 공유하기 - 4편. Apple 플랫폼과 XCFramework

Rust 공통 모듈을 iOS 앱에서 쓰기 위해 static library, XCFramework, Swift Package, UniFFI binding을 같은 release unit으로 묶고 Xcode와 CI에서 재현하는 기준을 정리합니다.

IT/기술

automationmodetool, Xcode UI 테스트의 Automation Mode 암호 프롬프트 정리

macOS에서 Xcode UI 테스트가 Automation Mode 암호 프롬프트에 막힐 때 automationmodetool이 정확히 무엇을 해결하는지 정리한다. TCC/PPPC 권한과 구분해 CI 러너 부트스트랩 위치까지 다룬다.

IT/기술

Rust 공통 모듈을 크로스플랫폼에서 공유하기 - 3편. UniFFI로 iOS와 Android 연결하기

Rust 공통 모듈을 iOS와 Android에서 함께 쓰기 위해 UniFFI 바인딩을 설계하고, generated binding을 adapter 뒤에 숨기는 구조와 모바일 런타임 고려사항을 정리합니다.

IT/기술

macOS 디버깅 권한 오류와 DevToolsSecurity -enable 작동 방식

macOS에서 디버깅 도구를 사용하거나 CI/CD 러너를 빌드할 때 마주치는 디버깅 권한 팝업을 차단하고, DevToolsSecurity가 내부 인증 데이터베이스를 어떻게 조작하는지 상세히 분석합니다.

IT/기술

Mac에서 Windows로 보낸 한글 파일명이 깨지는 이유: 자소 분리(NFD) 현상과 convmv 해결책

macOS에서 한글 파일명이 자소 분리(NFD)되어 Windows에서 깨지는 원인과 convmv를 사용한 해결 방법을 정리합니다.

IT/기술

Rust 공통 모듈을 크로스플랫폼에서 공유하기 - 2편. FFI 경계와 API 설계

Rust 공통 모듈을 크로스플랫폼에서 안전하고 효율적으로 호출하기 위해 FFI 경계를 잡고 API를 설계하는 구체적인 실무 전략을 정리합니다.

IT/기술

Rust 공통 모듈을 크로스플랫폼에서 공유하기 - 1편. 어디까지 Rust로 묶을 것인가

iOS·Android·Web에서 Rust 공통 모듈을 공유할 때 도메인 엔진의 경계를 어떻게 잡을지 정리한다. 무엇을 sudoku-core에 넣고 무엇을 플랫폼에 남길지, UniFFI·WASM 바인딩 계층과 앱 adapter 구조까지 다룬다.

IT/기술

iOS 런타임 폰트 등록, CTFontManagerRegisterFontsForURL 실무 정리

iOS에서 CTFontManagerRegisterFontsForURL로 폰트를 런타임 등록하는 방법. UIAppFonts와의 차이, PostScript name 확인, 저장 위치와 해제 시점을 정리한다.

IT/기술

Swift Package Registry, Git URL 의존성 이후를 준비하는 방법

SwiftPM의 Git URL 의존성을 넘어 scope.package-name 식별자 기반 Package Registry로. iOS 팀이 도입 전에 봐야 할 CI 속도, 의존성 재현성, 사내 패키지 배포, 패키지 서명, Xcode 설정을 정리한다.

IT/뉴스

WWDC26, iOS 개발자가 먼저 봐야 할 변화들

App Intents·Foundation Models·Core AI·Xcode 27까지, iOS 개발자 관점에서 먼저 봐야 할 WWDC26의 변화들.

광고Coupang Partners

이 사이트는 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.