사진첩 300GB, Claude Opus 5.5한테 영상으로 정리시키면 볼 만할까요?
맥 사진첩 300GB를 여행·월별 영상으로 바꿔 두려고 Claude Code와 Remotion으로 자동화를 돌렸습니다. 첫 결과물 49편은 사진이 0.4초마다 넘어가는 슬라이드쇼라 한 편도 쓸 수 없었습니다. 세션 모델을 Claude Opus 5.5로 바꾸고 레퍼런스 영상 한 편을 보여주자, Opus 5.5는 그 영상의 모션 문법을 읽어 지도 위 이동 경로·3D 카드 스택·하루 타임라인·통계 엔딩이 들어간 "기록 아카이브형" 템플릿을 직접 설계했고 첫 샘플에서 통과했습니다. 이어서 Opus 5.5 에이전트 4개가 여행 24편의 사진을 나눠 보고 스토리를 병렬로 썼는데, 집으로 보이는 위치와 Wi-Fi QR·쿠폰 바코드가 찍힌 사진까지 알아서 걸러냈습니다.

배경 — 사진첩을 지우기 전에 영상으로 남기고 싶었습니다
맥 사진 앱에 몇 년 치 사진과 영상이 300GB 넘게 쌓여 있었습니다. 다시 볼 일은 거의 없는데 지우기는 아깝습니다. 그래서 여행과 한 달 단위로 요약 영상을 만들어 유튜브에 일부공개로 올려두고, 원본은 정리하는 계획을 세웠습니다. 모든 사진을 보존하는 백업이 아니라 "다시 볼 만한 요약본"이 목표였습니다.
사진을 고르고 영상으로 편집하는 일은 수십 편 단위가 되면 사람이 할 수 없습니다. 그래서 Claude Code에게 전체 파이프라인을 맡겼습니다. 사진 라이브러리 조회는 osxphotos, 영상 렌더링은 React 코드로 영상을 만드는 Remotion을 썼습니다.
1차 시도 — 하룻밤에 49개, 그리고 "전부 쓰레기"
첫 번째 파이프라인은 이렇게 돌아갔습니다. 사진마다 붙은 GPS로 "집에서 15km 이상 떨어진 날"을 골라 여행 25개로 묶고, 나머지 평범한 날은 월별 17개로 묶었습니다. 이름 붙은 앨범 7개까지 합쳐 49편입니다. 각 영상은 사진을 몇 장씩 묶고, macOS 기본 TTS로 한 문장씩 내레이션을 붙이고, 그 위에 자막을 얹었습니다.
렌더링은 전부 성공했고 디코딩 오류도 0건이었습니다. 유튜브 업로드까지 끝냈습니다. 그리고 영상을 본 제 반응은 한 줄이었습니다. "사진이 0.5초 단위로 계속 바뀌고, 눈도 아프고, '그 사이 며칠이 지났다'만 무한 반복하다가 끝난다."

원인을 뜯어보니 모델이 멍청해서가 아니라 구조 문제였습니다.
- 컷 길이를 TTS 문장 길이가 정했습니다. 2초짜리 문장 하나에 사진 6장을 넣으면 한 장에 0.33초가 됩니다. 월별 영상의 사진 한 장 노출 시간 중앙값이 0.4초였습니다. "사진 최소 몇 초"라는 규칙이 코드 어디에도 없었습니다.
- 쓸 이야기가 없는 날에 억지로 내레이션을 붙였습니다. 평범한 한 달 사진에는 서사가 없으니 "그 사이, 며칠이 더 흘렀다" 같은 연결 문장만 반복됐습니다.
- 템플릿에 이전 프로젝트 흔적이 남아 있었습니다. 예전에 만든 전주 여행 영상 프로젝트를 복제해서 시작했는데, 타이틀 카드에
2025.09.26 - 09.27 · Jeonju가 하드코딩돼 있었습니다. 49편 전부 첫 화면에 "Jeonju"가 떴습니다. - 가장 큰 원인은 샘플을 안 보고 49편을 찍어낸 것입니다. 렌더링 성공, 디코딩 오류 0건은 "재생된다"는 뜻이지 "볼 만하다"는 뜻이 아닙니다.

목표 — 사진이 "읽히는" 영상, 그리고 샘플 1편 먼저
두 번째 시도에서는 목표를 바꿨습니다. 첫째, 사진 한 장이 최소 2~3초는 보여야 합니다. 둘째, 억지 내레이션 대신 사진에 이미 들어 있는 정보(날짜, 시간, GPS 위치, 장수)로 이야기를 만듭니다. 셋째, 한 편을 먼저 만들어 제가 보고 OK한 다음에만 나머지를 만듭니다.
방향을 고를 때 Claude가 세 가지 스타일(비트싱크 몽타주, 스토리형 VLOG, 기록 아카이브형)을 제안했고, 저는 아카이브형을 골랐습니다. 여기에 Threads에서 본 뉴스레터 홍보 애니메이션 한 편을 레퍼런스로 줬습니다. 카드가 쌓이고, 숫자가 카운트업되고, 헤드라인 한 단어에 포인트 색이 들어가는 모션 그래픽 스타일입니다.
구현 흐름 — Opus 5.5가 레퍼런스 한 편을 템플릿으로 옮기기까지
이 단계부터 세션 모델을 Claude Opus 5.5로 바꿨습니다. Opus 5.5는 레퍼런스 영상을 1초 간격 프레임 시트로 뽑아 장면 구성·전환·타이포 규칙을 읽은 뒤, 그걸 사진 아카이브에 맞게 번역했습니다. 레퍼런스의 "뉴스 카드 더미"는 "여행 사진 폴라로이드 더미"로, "이번 주 소식 105건" 카운터는 "사진·영상 65컷" 카운터로 바뀌었습니다.
영상은 6개 장면으로 구성됩니다.
- 오프닝 — 여행 사진 30장이 폴라로이드처럼 쏟아져 쌓이고, 오른쪽 위에서
PHOTOS & CLIPS 000 → 065가 카운트업됩니다. 더미가 흐려지며 뒤로 빠지면 "이틀, 고성." 제목이 뜹니다. - 지도 — 사진 GPS를 2km 단위로 묶어 방문 장소를 뽑고, OpenStreetMap 타일을 받아 어두운 톤으로 다시 칠한 지도 위에 주황 점선 경로를 그립니다. 핀이 튀어나올 때마다 시간과 장소 라벨이 붙고, 이동 거리가
0 → 52km로 올라갑니다. - DAY 챕터 — 큰 "DAY 1" 타이틀과 날짜. 하루짜리 여행이면 이 장면은 자동으로 빠집니다.
- 카드 스택 — 하루 10컷 안팎을 사진 카드로 만들어 오른쪽에서 3D로 날아와 쌓이게 합니다. 한 컷은 2.4초이고, 영상 클립은 카드 안에서 그대로 재생됩니다. 왼쪽에는 컷마다 한 줄 캡션과
03 / 10진행 바가 바뀝니다. - 하루 타임라인 — 그날의 주요 순간을 시간순 카드로 정리합니다.
- 엔딩 — 전체 65컷 그리드로 줌아웃한 뒤 기간·사진·영상·이동 거리 통계가 카운트업되고 엔드카드로 끝납니다.
이야기는 사람이 아니라 "스토리 JSON"이 담당합니다
영상 코드와 이야기를 분리한 게 핵심입니다. Remotion 컴포넌트는 장면 규칙만 알고, 어떤 사진을 어떤 캡션으로 보여줄지는 여행마다 JSON 하나로 정합니다. Claude는 날짜·시간이 라벨로 붙은 콘택트시트를 직접 보고 이 JSON을 씁니다.
{
"title": ["이틀, ", "고성", "."],
"map": {
"headline": ["설악을 넘어 ", "동해", "로."],
"stops": [
{ "lat": 38.0775, "lon": 128.186, "time": "09.08 10:07", "label": "인제 설악로" },
{ "lat": 38.3385, "lon": 128.5158, "time": "09.09 18:21", "label": "송지호" }
]
},
"days": [{
"label": "DAY 1", "date": "9월 8일 월요일",
"headline": ["바다 앞에 ", "책상", "을 폈다."],
"cards": [{ "sid": "4937", "time": "12:01", "place": "토성면", "cap": "맹그로브 고성 도착" }]
}]
}
제목·헤드라인을 [앞, 강조, 뒤] 세 조각으로 나눈 건 레퍼런스처럼 한 단어에만 포인트 색을 넣기 위해서입니다. 파이썬 빌더(build_archive.py)가 이 JSON을 받아 지도 이미지 합성, 썸네일 생성, 장면별 프레임 계산을 끝내면 Remotion은 그 결과 파일 하나만 읽어 렌더링합니다.


지도 대신 달력 — 한 곳에 머문 날을 위한 분기
모든 여행이 이동을 하지는 않습니다. 판교 한 건물에서 오리엔테이션만 듣고 온 날에 지도 핀 하나를 띄우면 허전합니다. 그래서 장소 클러스터 사이 최대 거리가 5km 미만이면 지도 대신 달력 장면을 씁니다. 그달 달력에서 해당 날짜 칸에 사진 썸네일이 튀어 들어가고, "첫 사진 → 마지막 사진" 시간 바가 채워지는 방식입니다. 이 판단은 스크립트가 GPS로 먼저 추천하고, Claude가 콘택트시트를 보고 최종 결정합니다.

24편 스토리를 4개 에이전트가 병렬로 — 개인정보까지 알아서 걸렀습니다
샘플이 통과한 뒤 나머지 여행 24편은 Opus 5.5 서브에이전트 4개에게 57편씩 나눠 맡겼습니다. 각 에이전트는 날짜·시간 라벨이 붙은 콘택트시트를 보고 사진을 고르고, 캡션과 헤드라인을 쓰고, 지도형과 달력형 중 하나를 고른 뒤 빌드 스크립트로 검증까지 마쳤습니다. 에이전트 하나가 57편을 끝내는 데 2~4분이 걸렸습니다.
인상적이었던 건 제가 규칙으로 다 적어주지 않은 판단입니다. 여러 여행에 반복해서 나오고 아침 출발·밤 귀가 시각에 찍힌 GPS 클러스터를 "집으로 보인다"며 지도 경로에서 뺐고, 가족 식사가 반복되는 동네는 시 단위로만 표기했습니다. 그렇게 경유지가 하나만 남은 여행은 스스로 달력형으로 바꿨습니다. 카드에서는 Wi-Fi 비밀번호가 적힌 안내판, 공유기 QR 라벨, 기프트 쿠폰 바코드, 남의 명함, 사용자명이 보이는 터미널 화면이 찍힌 사진을 제외했고, 그 목록을 결과 보고에 남겼습니다.
결과
- 고성 워케이션 2일, 사진 44장·영상 21개(65컷) → 카드 20장으로 추린 89초 영상 1편. 첫 샘플에서 "괜찮다"로 통과했습니다.
- 사진 한 장 노출 시간은 1차 0.4초에서 2.4초로 늘었습니다. 내레이션 없이도 날짜·장소·캡션만으로 흐름이 읽힙니다.
- 나머지 여행 24편의 스토리 JSON은 Opus 5.5 에이전트 4개가 병렬로 작성해 전부 빌드 검증을 통과했고, 같은 방식으로 앨범 7편도 진행 중입니다.
배운 점
"렌더링 성공"과 "볼 만한 영상"은 다른 검증입니다. 1차 때도 디코딩 검사는 49편 전부 통과했습니다. 영상 배치 작업이라면 가장 불리한 케이스(사진이 제일 많은 편) 1개를 먼저 뽑아 사람이 보고, OK가 난 뒤에 나머지를 돌려야 합니다. 49편을 다시 만드는 비용이 샘플 1편을 기다리는 비용보다 훨씬 큽니다.
Opus 5.5가 잘한 것, 그래도 사람이 해야 했던 것. Opus 5.5가 가장 크게 기여한 부분은 레퍼런스 프레임을 읽고 그 문법을 사진 아카이브라는 전혀 다른 소재로 옮긴 것, 지도 타일 워터마크·세로 사진 회전 같은 문제를 스틸 이미지로 직접 확인하며 고친 것, 그리고 병렬 에이전트로 24편을 쓰면서 개인정보 판단까지 해낸 것입니다. 다만 1차 49편(다른 Claude 모델로 제작)과 비교하면 모델만 바뀐 게 아니라 레퍼런스와 "샘플 먼저" 원칙도 함께 바뀌었습니다. "무엇이 좋은 영상인가"는 여전히 사람이 레퍼런스로 알려줘야 했습니다.
작은 함정들. 사진 앱에서 뽑은 JPEG는 EXIF 회전값만 있고 픽셀은 누워 있는 경우가 많아, Remotion에서 그대로 쓰면 세로 사진이 옆으로 눕습니다. 빌드 단계에서 회전을 픽셀에 굽는 게 안전합니다. 무료 지도 타일 중에는 키 없이 호출하면 워터마크가 박히는 곳도 있어서 OpenStreetMap 타일을 받아 직접 색을 입혔고, 화면 구석에 출처 표기를 넣었습니다. 집 위치는 영상에 찍지 않도록 경로에서 뺐습니다.
다음 액션
- 나머지 여행·앨범 31편을 아카이브형으로 다시 렌더링하고, 기존 슬라이드쇼 영상과 교체합니다.
- 서사가 약한 월별 영상 17편은 지도 대신 달력 그리드 중심 버전으로 따로 샘플을 만들어 봅니다.
- 전체 교체와 검토가 끝나면 그때 원본 정리를 진행합니다. 사진 앱의 삭제는 스크립트로 되돌리기 어려워서, 이 단계는 자동화하지 않고 직접 확인하며 할 계획입니다.