고칠 시간이 없었던 사진 액자
요약
Google Photos API 변경으로 작동이 어려워진 Raspberry Pi 기반 사진 액자 프로젝트를 AI 에이전트의 도움을 받아 Immich와 연동하여 성공적으로 재구축한 과정을 설명합니다. 아키텍트, 개발자, QA 등 여러 전문 에이전트를 활용해 복잡하고 안정성이 요구되는 시스템 구축 및 배포 과정을 자동화했습니다.
핵심 포인트
- AI 에이전트는 복잡한 시스템의 로드맵 작성부터 테스트까지 전 과정에 도움을 줍니다.
- 여러 AI 에이전트가 협업하며 개발하는 방식은 인간의 개입 없이도 높은 수준의 안정성을 확보할 수 있습니다.
- 자동화된 배포 및 버전 관리(리베이스, 푸시, 태그)는 엄격한 검증 절차와 문서화된 계획을 통해 이루어져야 합니다.
7년 동안 진행된 Raspberry Pi 프로젝트, 기능을 잃어버린 Google API, 그리고 AI 에이전트가 매일 벽에 걸린 곳에서 작동하게 만든 방법.
photoframe은 Henric Andersson의 Raspberry Pi 프로젝트로, Google Photos에서 무작위 사진을 가져와 액자처럼 보여줍니다. 이 소프트웨어는 훌륭합니다. 그런데 2025년에 Google이 Photos Library API를 앱 스스로 업로드한 사진으로만 축소했고, 라이브러리를 읽어야 하는 액자는 읽을 것이 아무것도 없게 되었습니다.
저는 Immich를 셀프 호스팅(self-host)하고 있습니다. 제 사진들은 이미 그곳에 있습니다. 따라서 해결책은 종이 위에서는 명확했습니다: photoframe에게 Immich와 대화하는 법을 가르치는 것.
하지만 이 해결책은 제 달력상으로는 명확하지 않았습니다. 저는 너무 바빠서 완전히 새로운 사진 서비스를 구축하고, 이를 위한 API를 만들고, Pi Zero, Pi 3B+, Pi 4, Pi 5에서 앱을 테스트하고, 800x480부터 1920x1080까지의 디스플레이에서 확인한 다음, 벽에 걸린 물건이 필요로 하는 안정성 제어 장치를 구축하는 일은 불가능했습니다. AI가 없다면 그 목록은 공상에 지나지 않습니다. 하지만 AI 덕분에 이 액자는 트러블 없이 매일 작동하고 있습니다.
여기에 그것이 어떻게 이루어졌는지, 에이전트들이 제가 지시한 것 이상으로 나아간 부분들을 포함하여 설명합니다.
시작점
원래 코드(Upstream)에는 이미 Python 3 브랜치가 있었습니다. Henric의 커밋 내용은
마지막 지점은 프로젝트의 CLAUDE.md에 대문자로 쓰인 규칙이었습니다. “Immich 기능에 대해 기존 라우트를 절대 수정하지 마라.” 작업은 역할극처럼 진행되었습니다. 아키텍트 에이전트가 단계별 로드맵을 작성했고, 제가 승인했으며, 개발자 에이전트가 구축하고, QA 에이전트가 테스트했습니다. 이 로드맵들 자체에도 “승인되지 않은 git 커밋을 하지 마라” 및 “구현 전에 제품 관리자(사용자)의 승인이 필요하다”와 같은 규칙들이 있었습니다. 저는 제품 관리자였습니다.
QA 에이전트의 첫 번째 기준선 보고서는 “치명적인 실패가 확인됨”으로 시작했습니다. 좋습니다. 그게 임무니까요.
한편, 개발자 에이전트는 server.py의 Flask 오류 처리가 도움이 필요하다고 판단하고 핸들러를 추가했습니다. 그것은 규칙에서 건드리지 말라고 한 기존 파일이었습니다. 뒤따르는 커밋 제목은 “승인되지 않은 변경 사항 되돌리기”였습니다. 규칙 파일은 경계가 어디인지 알려주었습니다. 그 되돌리기가 바로 경계를 만든 것이었습니다.
너무 멀리 나간 푸시
2026년 4월, 저는 실제 출시를 위해 돌아왔고, 자동화된 세션이 제가 여전히 교훈적이라고 생각하는 무언가를 했습니다. 한 번의 실행으로 Python 3 브랜치를 master에 리베이스하고, master를 푸시하고, v3.0.0 태그와 릴리스를 생성했으며, dev 브랜치를 만들고, Raspberry Pi 이미지 빌더를 포크했습니다. 이 모든 것이 Pi에서 테스트된 적은 없었습니다. 또한 그 과정에서 상위 프로젝트로 향하는 열려 있던 풀 리퀘스트(pull request)를 해당 브랜치를 삭제함으로써 닫았습니다.
이러한 단계들 중 어느 하나가 자체로는 이상하지 않습니다. 하지만 함께 합쳐지니, 아무도 실행해 본 적 없는 출시였습니다.
답은 에이전트를 모호하게 신뢰하지 않는 것이 아니었습니다. 그것은 손상 평가 테이블과 마지막으로 알려진 좋은 커밋(last known good commit)으로 마스터를 리셋하는 서면화된 롤아웃 계획, 그리고 그 이후 모든 것이 통과해야 하는 하나의 관문이었습니다:
Pi 하드웨어에서 테스트될 때까지는 아무것도 푸시되거나, 태그가 지정되거나, 릴리스되거나, 상위 프로젝트로 전송되지 않는다.
풀 리퀘스트(Pull Request)가 릴리스 플로우의 검증 게이트 역할을 했습니다. Pi Zero W와 1366x768 노트북 패널을 장착한 기기가 rc1 태그가 붙은 4월 18일 이전에 전체 이미지를 실행했습니다. 그 규칙은 이 프로젝트에서 다른 어떤 것보다도 스스로를 증명해냈습니다. 저는 왜 그러한 규칙이 프롬프트(prompt) 대신 메커니즘에 존재해야 하는지에 대해 Prompts Are Requests. Hooks Are Law.에서 글을 썼습니다.
현재 기능
- 하드웨어에 맞춰진 Immich. 프레임은 먼저 Immich에게 미리보기 이미지를 요청하고,
/proc/meminfo와 ImageMagick의 제한이 Pi가 처리할 수 있다고 판단할 때만 전체 크기 또는 원본 크기로 확대됩니다. HEIC 파일도 작동합니다. 웹 UI에는 앨범 이름을 직접 입력하는 대신 앨범 선택기가 있습니다. - tvservice 없이 디스플레이 지원. 시스템에
tvservice가 있으면 이를 사용합니다. 그렇지 않으면, 프레임은 건강 검사 및 안전 기본값을 갖춘 framebuffer (fbset,/sys/class/graphics)으로 폴백(fallback)합니다. Bookworm 데스크톱 이미지에서는 lightdm을 중지시켜 화면 독점권을 가질 수 있게 합니다. - 메모리. 800x480 패널을 구동하는 Pi 3B+에서, 메모리 부족 수정(out-of-memory fix)은 최대 메모리를 약 1061 MB에서 약 494 MB로 줄였습니다.
- 네트워크 문제. 다운로드는 지수 백오프(exponential backoff)와 지터(jitter)를 사용하여 재시도하며, 5초에서 60초 사이의 간격으로 총 6번 시도하고, 영구적인 HTTP 오류는 일시적인 오류와 분리하여 처리합니다. 만약 앨범 새로고침이 실패하면, 프레임은 마지막 정상 앨범 목록을 유지하고 화면이 비어지는 대신 1분 후에 다시 시도합니다.
- 깔끔한 종료. SIGTERM과 SIGINT는 화면에 사진이 정지된 상태로 남기는 대신 디스플레이를 비웁니다. 자격 증명(Credentials)은 더 이상 로그에 표시되지 않습니다.
- 실제 이미지. pi-gen의 포크(fork)가 헤드리스 라이트(headless Lite) 이미지를 빌드합니다. 이 이미지를 플래시하고, 부팅 파티션의
wifi-config.txt에 와이파이 정보를 넣으면 SSH 연결 없이 프레임이 작동합니다. CI는 QEMU 환경에서 해당 이미지를 빌드합니다. 또한 원래 사진 액자에서 넘어오는 사람들을 위한 마이그레이션 스크립트도 있습니다.
원래 프로젝트의 마스터와 비교했을 때, 포크(fork)는 65개 파일을 건드리며, 4,563줄이 추가되고 1,618줄이 삭제되었습니다. GitHub 기준으로 현재까지 40개의 병합된 풀 리퀘스트(pull request)와 29개의 닫힌 이슈가 있습니다.
지루해질 때까지 검토하기
v3.0.0-rc2는 10월 1일자로 태그되었습니다. 이 수정 요청 풀 리퀘스트는 독립적인 리뷰어에게 네 번이나 거쳐갔고, 매번 통과할 때마다 '나중에 처리하겠다'는 코멘트가 아닌 커밋으로 답변을 받았습니다. Pi 4를 1920x1080 모니터에 연결하여 무려 약 17시간 동안 작동했습니다.
현황
여전히 릴리스 후보(release candidate)이며, 이슈 트래커는 남아있는 문제들을 솔직하게 보여주고 있습니다. 네트워크가 없는 상태에서 재시작하면 캐시된 사진이 표시되지 않습니다. KMS 환경에서는 회전 기능이 작동하지 않습니다. Immich의 v3 API 지원은 구현되었지만 3.1 버전을 기다리고 있습니다. 설정 백업 및 복원, 그리고 이미지 우선순위 지정(최근, 촬영 날짜별, 즐겨찾기) 기능들은 열려있는 풀 리퀘스트에 올라와 있습니다. 또한, 지난 4월부터 열린 Python 3 관련 작업이 업스트림으로 돌아가도록 제안하는 풀 리퀘스트도 있습니다.
이러한 문제들이 제가 벽에 걸어둔 액자가 매일 제 역할을 하는 것을 막지는 못합니다.
차이를 만든 것은 모델이 저보다 빠르게 파이썬을 작성하는 것이 아니었습니다. 그것은 모델 주변의 규칙들, 즉 건드려서는 안 되는 경로(route), 만약 건드리더라도 되돌리는 방법(revert), 그리고 실제 Pi에서 작동하기 전까지는 배포되지 않도록 하는 게이트(gate)였습니다. 이 모든 것은 에이전트가 가서는 안 될 곳으로 가는 것을 지켜보면서 얻은 것입니다. 이것은 에이전트를 사용하는 비용이 아닙니다. 그것은 노력입니다.
코드는 github.com/dev-brewery/photoframe에 있습니다. Immich를 실행하고 서랍 속에 Pi가 있다면, rc2 이미지는 릴리스 페이지에서 찾을 수 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기