만들며 알게 된 것, 먹고 다닌 것.

· 식기(食記)

덕천동 평양집의 두부만둣국, 해장하러 갔는데 간이 세지 않아요

새벽까지 술을 마신 다음 날 점심에 친구와 속을 달래러 간 덕천동의 이북식 두부만두집이에요. 10,000원짜리 두부만둣국은 간이 세지 않고 맛있었어요. 벽에 붙은 사장님의 글도 재미있어요.

맑은 국물에 큼직한 만두와 송송 썬 파가 담긴 만둣국 한 그릇
· IT/개발

Apple Pencil 필기를 스도쿠 숫자로 바꾸는 입력 처리

DailySudoku에서 펜으로 쓴 숫자를 셀에 넣으려면 획을 tap과 필기로 나누고, 여러 획을 묶고, 모델 입력으로 바꾸고, 믿을 수 있을 때만 적용해야 해요. 각 단계의 기준값과 아직 검증하지 못한 부분을 기록해요.

· IT/개발

스도쿠 81칸을 VoiceOver와 TalkBack에 알리는 방법

DailySudoku 게임판은 화면에서는 뷰 하나지만 보조 기술에는 81개 칸을 따로 알려야 해요. iOS와 Android에서 칸의 위치·내용·선택 동작을 맞춘 방식과, 아직 실기기로 확인하지 못한 부분을 기록해요.

· IT/기술

광고 노출 이벤트를 세 플랫폼에서 같은 뜻으로 세는 규약

iOS의 로딩 완료, Android의 impression 통지, Web의 DOM 부착을 모두 ad_impression으로 보내면 플랫폼마다 세는 기준이 달라져요. 광고가 거치는 단계를 여섯으로 나누고, 어떤 신호를 노출 한 건으로 셀지 정한 규약이에요.

· IT/기술

일일 퍼즐 점수의 날짜와 리더보드 전송 손실 다루기

23시 50분에 시작해 0시 5분에 끝낸 판에서는 퍼즐 날짜, 전송 시각, 리더보드의 조회 구간이 서로 어긋나요. Game Center와 Play Games 문서로 세 값의 차이를 확인하고, 점수 전송을 어디까지 보장할지 고르는 기준을 정리해요.

· IT/개발

일일 퍼즐 ID에 생성기 버전이 필요한 이유

DailySudoku의 일일 퍼즐은 날짜에서 seed를 만들어 보드를 생성해요. 생성 방식이 바뀌면 같은 날짜에서 다른 보드가 나올 수 있는데, 날짜만 담은 ID로는 그 차이를 적을 수 없어요. 현재 구조와, ID에 날짜 정책과 생성기 버전을 넣자는 제안을 기록해요.

· IT/기술

위치 권한 없이 GeoIP 권역으로 광고 공급자 순서 정하기

지역마다 쓸 수 있는 광고 공급자가 다를 때 필요한 것은 좌표가 아니라 넓은 권역이에요. 동의를 먼저 확인하고, 서버가 IP로 추정한 권역 버킷만 받아 공급자 순서를 정하는 설계와 그 한계를 정리해요.

· IT/개발

광고 제거 일회성 구매의 권한을 유지하고 되돌리는 방법

광고 제거 상품은 한 번 사면 끝나는 것처럼 보이지만, 재설치, 대기 중인 결제, 환불을 거치면 구매 직후의 결과만으로는 보유 여부를 알 수 없어요. StoreKit 2와 Play Billing에서 현재 권한을 다시 읽어 캐시를 맞추는 구현과 남은 공백을 기록해요.

· IT/기술

검증 스크립트를 일부러 깨진 입력으로 검증하기

검사 스크립트가 종료 상태 0으로 끝났다고 해서 규칙을 검사했다는 뜻은 아니에요. 정상 샘플을 한 곳만 깨뜨린 사본을 넣어, 기대한 분류로 실패하는지 확인하는 방법과 Python 예제를 정리해요.

· IT/기술

감시자를 누가 감시하나: 사라진 예약 작업 찾기

예약 작업이 지워지면 오류도 남지 않아요. 기대하는 역할과 scheduler에 실제로 있는 객체를 대조하고, 마지막 성공 시각으로 경보를 거는 방법을 Kubernetes, GitHub Actions, Prometheus 문서와 함께 정리해요.

· IT/기술

Rust 공유 코어 7편: 테스트와 CI를 층별로 나누기

Rust 테스트가 통과해도 iOS 링크, Android 릴리스의 ABI, Web 배포 빌드의 Wasm 로딩은 따로 깨질 수 있어요. 도메인 검사는 Rust에 모으고, 클라이언트는 변환과 연결만 검사하고, CI는 산출물을 새로 만들어 확인하는 구성을 정리해요.

· IT/기술

Rust 공유 코어 6편: Web에서 Wasm 패키지로 쓰기

모바일에서 쓰는 Rust 규칙을 Web에서도 쓰려면 WebAssembly로 컴파일해서 패키지로 내놓아요. Rust와 Web이 맡을 일의 구분, Next.js에서 초기화할 자리와 상태, 액션 단위의 호출 계약, 타입 변환을 확인하는 fixture를 정리해요.

· IT/기술

Rust 공유 코어 5편: Android에 .so로 넣을 때 확인할 것

Kotlin 바인딩을 생성했다고 Android 통합이 끝난 것은 아니에요. ABI별 .so를 배치하는 방법, Gradle 빌드에 Rust 컴파일을 잇는 방법, 16 KB 페이지 조건과 release 배포물에서 확인할 항목을 Android 문서를 바탕으로 정리해요.

· IT/기술

Rust 공유 코어 4편: iOS에 XCFramework로 전달하기

Rust 테스트가 통과해도 iOS 앱에서 링크가 된다는 보장은 없어요. 기기용과 시뮬레이터용 정적 라이브러리를 XCFramework로 묶고, Swift Package로 전달하고, 로컬과 CI가 같은 순서로 빌드하게 만드는 방법을 문서 기준으로 정리해요.

· IT/기술

Xcode UI 테스트와 automationmodetool의 범위

무인 Mac에서 Xcode UI 테스트가 인증 창 앞에서 멈출 때, automationmodetool이 해결하는 것과 TCC 권한처럼 해결하지 못하는 것을 구분해요. 상태 조회 출력과 장비 준비 순서를 함께 정리해요.

· IT/기술

Rust 공유 코어 3편: UniFFI 생성 코드는 adapter 뒤에

UniFFI는 Rust의 함수와 타입에서 Swift와 Kotlin 호출 코드를 만들어 줘요. 무엇을 공개하고 생성된 타입을 어디까지 쓸지는 앱이 정해야 해요. 생성 코드를 adapter 뒤에 두는 구조와 플랫폼별로 챙길 것, 생성 파일의 관리 방식을 정리해요.

· IT/기술

macOS의 DevToolsSecurity와 무인 CI의 디버거 인증

Mac에서 디버거를 붙이면 암호를 묻는 창이 뜨고, 사람이 없는 CI에서는 그 창에서 작업이 멈춰요. DevToolsSecurity가 바꾸는 인증 규칙을 macOS 27.0.1에서 직접 읽어 확인하고, 상태 확인 명령과 CI 구성 방법을 정리해요.

· IT/기술

한글 파일 이름의 자모가 풀어지는 이유와 NFC 정규화

macOS에서 만든 한글 파일 이름이 다른 환경에서 자모가 풀어져 보이거나 다른 이름으로 취급되는 것은 유니코드 정규화 형태가 달라서예요. NFD와 NFC의 코드 포인트를 직접 검산하고, convmv와 코드로 NFC에 맞추는 방법을 정리해요.

· IT/기술

Rust 공유 코어 2편: 경계를 넘는 API를 크게 잡기

Rust 엔진을 Swift, Kotlin, TypeScript에서 부를 때에는 내부에 알맞은 타입과 바깥에서 다루기 쉬운 타입이 달라요. 셀 단위의 작은 함수보다 액션 단위의 큰 함수를 내놓고, DTO와 오류와 버전을 계약으로 관리하는 설계를 정리해요.

· IT/기술

Rust 공유 코어 1편: 무엇을 공유하고 어디서 끊을지

iOS, Android, Web을 함께 만들면 같은 규칙을 세 번 구현하게 돼요. Rust로 공유할 범위를 결과가 같아야 하는 도메인 규칙으로 좁히고, 코어와 바인딩과 앱의 세 층으로 나누는 설계를 스도쿠를 예로 설명해요.