이 글은 Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine에 제출하는 내용입니다.
제가 만든 것 (What I Built)
Calavera AI: the altar, the Soul Mirror naming a candle, and a calaverita card
Calavera AI는 Día de los Muertos(죽은 자들의 날)를 위한 안드로이드 앱으로, 가족이 잃어버린 사람들의 추억을 보관하고 이를 활용하여 각 사람에 대한 _calaverita literaria_를 작성합니다. 모든 작업은 휴대폰에서 실행되며, 사용자가 앱에 입력하는 어떤 정보도 외부로 유출되지 않습니다.
Calaverita literaria는 멕시코의 전통입니다. 이는 죽음이 누군가를 데려가는 상황을 마치 그 사람이 아직 살아있는 것처럼 묘사한 짧고 운율이 있으며 애정이 담긴(보통은 장난기 넘치는) 시입니다. 이 시들은 큰 소리로 읽히거나, 신문에 인쇄되거나, 매년 11월 제단에 놓입니다. 의도적으로 재미있습니다. 이것이 작동하는 이유는 구체적이기 때문입니다. 예를 들어, 매주 일요일 토르티야를 태우고 가스레인지를 탓했던 할머니와, 동네의 모든 라디오를 고쳐줬던 삼촌에게는 매우 다른 시가 쓰일 수 있습니다.
이 앱은 바로 그런 역할을 합니다. 사용자는 한 사람에 대한 작은 아카이브(그 사람이 어떤 사람이었는지, 가족들이 그 사람에 대해 들려주는 이야기, 남기고 간 물건의 사진)를 구축하고, 앱은 이를 세 가지 결과물로 변환합니다:
- 디지털 오프렌다 (Digital ofrenda). 가보품(묵주, 양초, 가장 좋아하는 컵 등)을 사진으로 찍으면 앱이 그것을 인식하고 전통적인 의미를 설명하며, 이 물건을 세 단의 제단(altar) 중 적절한 위치에 배치합니다: Cielo(천국), Tierra(지상), 또는 Inframundo(저승).
- 기억 아카이브 (Memory archive) 사용자가 의미별로 검색할 수 있습니다. 예를 들어, “춤추는 것을 좋아했던 사람”이라고 검색하면, 비록 그 단어를 직접 사용하지 않았더라도 적절한 이야기를 찾아줍니다.
- 그 기억들을 바탕으로 스페인어, 영어 또는 영어 번역이 포함된 스페인어로 작성된 Calaveritas입니다. 이 시들은 낭독하거나, 공유하거나, 저장할 수 있는 양피지 카드 형태로 제공됩니다.
'기계 속의 유령' 해석하기 (How I interpreted "Ghost in the Machine")
저는 이 주제를 생각할 수 있는 가장 부드러운 방식으로 문자 그대로 해석했습니다. 우리가 그리워하는 사람들은 우리가 계속해서 이야기하는 이야기 속에 살아있으며, 이곳에서는 그 이야기들이 어디로도 보내지지 않는 기계 안에 존재합니다. 여기서 '유령(ghost)'은 시가 누군가에게 되돌려주는 목소리이며, '기계(machine)'는 인터넷을 끈 상태에서 11월 1일 밤, 공동묘지에서 이 기능을 수행할 수 있는 휴대폰입니다.
프라이버시가 핵심인 이유
추억은 일반적인 의미의 데이터가 아닙니다. 그것은 우리가 누군가를 느끼는 방식 그 자체입니다. 가족만이 이해하는 농담, 아무도 말하지 않는 병, 손글씨 레시피 사진 같은 것들이죠. 당신은 어떤 회사도 할머니를 이용해 다음 모델을 훈련시키도록 원치 않을 것이며, 이를 막기 위해 프라이버시 정책에 의존해야 할 필요가 없습니다. 그래서 이 앱은 어떠한 것도 전송할 수 없도록 설계되었습니다:
- 계정이나 로그인 기능 없음;
- 서버, 분석(analytics), 충돌 보고기(crash reporter) 없음;
- 네트워크 접속은 Hugging Face에서 오픈 모델을 단 한 번 다운로드하는 것에 국한되며, 모든 파일은 게시된 SHA-256 값과 대조됩니다;
- 그 이후에는 앱 전체가 비행기 모드(airplane mode)로 작동합니다.
데모
이 영상은 안드로이드 에뮬레이터에서 실제로 실행되는 앱의 스크린샷으로 제작되었습니다. 음성 해설은 ElevenLabs 텍스트-음성 변환(text-to-speech) 기술을 사용하여 AI로 생성되었으며, 이 프로젝트에서 클라우드 서비스를 사용한 유일한 부분입니다. 앱 자체는 절대 그러지 않습니다.
직접 사용해 보세요: v1.0.1 릴리스 (arm64, 103 MB) 안드로이드 APK를 설치하세요. 첫 실행 시 휴대폰에 맞는 모델 팩을 추천하고 다운로드합니다(라이트 팩 기준 약 2.1 GB이므로 Wi-Fi 사용을 권장합니다). 로그인 과정은 없습니다. 좋은 테스트 경로는 다음과 같습니다:
- 아카이브(Archive) → 누군가를 기억하기: 사람을 추가하고 몇 가지 이야기를 기록합니다.
- 소울 미러(Soul Mirror): 물건의 사진을 찍거나 그림을 골라 제단에 놓습니다 (촛불이 효과적입니다).
- 칼라베리타스(Calaveritas): "스페인어 + 영어"를 골라 하나를 작성합니다. 그런 다음 낭송하고, 카드를 저장하며, 리듬 체크를 확인합니다.
- 아카이브(Archive) → 백업 및 복원: 암호화된 백업을 만들고 이를 복원합니다.
코드
💀 Calavera AI
오프라인으로만 작동하는 Día de los Muertos 동반자입니다. 소중한 물건을 스캔하여 오프렌다(ofrenda)를 꾸미고, 가족의 이야기를 기기 내 벡터 아카이브에 보관하며, 인터넷 연결 없이도 오픈 가중치 LLM이 그리워하는 사람들을 위한 전통적인 _calaverita literaria_를 작성해 줍니다.
DEV Hacktoberfest 2026 Open-Source AI Challenge, Week 4: _Ghost in the Machine_을 위해 제작되었습니다.
오프라인으로 작동해야 하는 이유
조상들의 기억은 사적입니다. Calavera AI의 모든 모델은 휴대폰 자체 CPU에서 실행됩니다: 사진, 이야기, 시는 기기를 벗어나지 않으며, 계정이 없고, 신호가 없는 묘지에서도 앱이 계속 작동합니다. 또한 API가 지원 종료되어도 고장 나지 않습니다.
파이프라인
📷 Soul Mirror ──────────┐ (입력 레이어)
SmolVLM / Gemma 4 vision│ 사진 → 512px → 이름 + 한 문장 → 문화적 배치
▼
...
GitHub에서 보기
MIT 라이선스. Expo SDK 58, React Native 0.88 (New Architecture, Hermes), TypeScript이며 약 130개의 소스 파일로 구성되어 있습니다. README에 전체 아키텍처와 빌드 지침이 포함되어 있습니다.
제작 과정
오픈 소스 요소들
| 작업 | 오픈 모델 / 프로젝트 | 휴대폰 용량 |
|---|
| 시 작성 | Gemma 2 2B Instruct (Q4_K_M), 또는 더 큰 휴대폰의 경우 Gemma 4 E2B (Q4_0) | 1.7 GB / 2.8 GB |
| ... | | |
| 모든 가중치(weights)는 Hugging Face의 GGUF 파일입니다. 나머지 모든 것은 Expo와 React Native로 구성되어 있습니다. | | |
아키텍처
📷 영혼 거울 (Soul Mirror) ─────────── 사진 → 512px → 비전 모델 → 이름 + 한 문장
│ → 문화 지식 기반 → 시엘로 (Cielo) / 티에라 (Tierra) / 인프라문도 (Inframundo)
▼
...
코드는 다음과 같은 구조를 따릅니다: 기능별로 하나의 폴더(models, engine, mirror, ofrenda, memories, profiles, verse, tributes, backup)가 있으며, 라우팅 파일들은 얇은 래퍼(wrapper) 역할을 합니다. SQLite나 디스크에서 읽어오는 모든 데이터에는 TanStack Query를 사용하며 (비행기 모드에서도 동일하게 작동하도록 networkMode: 'always' 설정), 다운로드 진행률이나 스트리밍 시의 시 같은 실시간 상태에는 zustand를 사용합니다.
1. 장치 확인 및 모델 선택
오프라인으로 2B 모델을 실행할 수 있는 휴대폰은 편안한 수준부터 간신히 가능한 수준까지 다양합니다. 따라서 첫 화면에서는 아무것도 다운로드하기 전에 휴대폰의 사양을 측정합니다:
- 메모리 (Memory): 앱이 휴대폰의 총 RAM 용량을 읽습니다. 5.4 GiB 미만일 경우 Ofrenda Lite를 권장합니다 (Gemma 2 2B 쓰기, SmolVLM 500M 보기, 총 2.1 GB). 5.4 GiB 이상일 경우 Ofrenda Plus를 권장합니다 (다중 모드(multimodal) Gemma 4 E2B가 쓰기와 보기를 모두 담당하며, 3.2 GB입니다).
- 저장 공간 (Storage): 다운로드하기 전에 누락된 바이트와 추가 여유 공간 300 MB를 확인하고, 충분하지 않을 경우 얼마나 확보해야 하는지 정확히 알려줍니다.
- 사용자 선택: 권장 사항은 기본값일 뿐 강제적인 제한이 아닙니다. 나중에 패키지를 변경하거나 사용하지 않는 것을 제거할 수 있습니다.
화면에 표시되는 이름들은 의도적으로 "Gemma 2 2B Q4_K_M"와 같은 기술 용어로 되어 있지 않습니다. 사람들은
휴대폰 연결로 2기가바이트를 다운로드하는 데는 시간이 걸리며, 아무도 설정 화면에 40분 동안 앉아있지 않을 것입니다. 제 첫 번째 버전은 앱 내부에서 다운로드되었습니다. 최소화하자마자 안드로이드가 프로세스를 멈추게 했고 다운로드는 중단되었습니다.
그래서 저는 모든 파일을 안드로이드 자체의 서비스인 DownloadManager(Play 스토어와 Chrome이 사용하는 것과 동일)에 전달하는 작은 로컬 Expo 모듈을 Kotlin으로 작성했습니다. 이를 통해 많은 것을 무료로 얻었습니다:
- 앱 최소화 상태 또는 종료 상태에서도 계속 작동합니다. 다운로드 도중에 앱을 재설치하여 테스트해 보았는데도 안드로이드는 계속 다운로드했고, 앱이 다시 실행되었을 때 다운로드를 재연결(ID가 저장됨)하고, 완료된 파일을 확인한 후 패키지로 전환했습니다.
- 병렬로 작동합니다. 네 개의 파일 모두 동시에 다운로드되어 테스트 환경에서 걸리는 시간을 40분 이상에서 약 10~15분으로 단축시켰습니다.
- 시스템 알림을 표시하고, 자체적으로 Wi-Fi 또는 연결 상태를 기다리며, 추가 권한이 필요 없습니다.
이 기능을 사용해 볼 때 알아두면 좋은 두 가지 놀라운 점:
- DownloadManager는 파일 전체를 미리 할당하므로,
.part 파일의 크기가 진행 상황에 대해 아무것도 알려주지 않습니다. 진행률은 대신 DownloadManager 자체의 바이트 카운트에서 나옵니다.
- 안드로이드 11 이상에서는 앱 전용 저장소(shared storage)의 폴더에만 쓸 수 있으며, 이는 앱에 사적이고 제거 시 삭제됩니다. Expo의 파일 API로는 그곳에 파일을 생성할 수 없기 때문에, 이 모듈은
.part에서 최종 이름으로 원자적 리네임(atomic rename) 작업도 수행합니다.
크기 확인 및 Hugging Face가 공개한 해시값에 대한 SHA-256 확인을 통과할 때까지 아무것도 사용되지 않습니다.
3. 소울 미러(The Soul Mirror): 가보를 이름 지어주는 비전 모델
The Soul Mirror camera pointed at an heirloom
The Soul Mirror looking at a candle on the phone, naming it and placing it on the Inframundo tier
사진은 512px로 축소됩니다 (이미지 토큰 감소, 속도 향상 및 작은 썸네일 유지). 그런 다음 비전 모델에게 무엇을 보는지 질문합니다. 모델은 객체 이름만 지정합니다. 이 모델이 전통을 지어내도록 하고 싶지 않았기 때문에, 17개의 오프렌다 요소로 구성된 작은 **문화적 지식 기반(cultural knowledge base)**이 어디에 배치되고 그 이유를 결정합니다:
- 초상화나 묵주(rosary)는 **시엘로(Cielo)**로 갑니다.
- 판 데 무에르토(pan de muerto), 설탕 해골(sugar skull) 또는 가장 좋아하는 음료는 **티에라(Tierra)**로 갑니다.
- 양초, 금잔화(cempasúchil), 코팔(copal), 물, 소금은 **인프라문도(Inframundo)**로 갑니다.
- 개인적인 모든 것(모자, 기타, 도구 등)은 티에라(Tierra) 위의 *레쿠에르도 페르소날(recuerdo personal)*입니다.
스페인어 이름은 항상 옆에 영어 번역("Las velas · Candles")과 그 요소가 무엇을 의미하는지에 대한 문장과 함께 제공됩니다. 그런 다음 스캔된 내용은 기억(memory)으로 저장되어 시에서 언급될 수 있습니다.
The altar with two candles on the Inframundo tier, and the details of one heirloom