[안드로이드] PC의 사진을 케이블 한 번으로 액자에 보내기 — 동기화 도구를 바이브코딩으로 만들기
서두
지난 글에서 액자 앱까지 완성했다. 그런데 앱은 어디까지나 기기에 저장된 사진을 보여줄 뿐이다. 새 사진은 어떻게 들어가나?
선택지를 정리하면 이렇다:
| 방법 | 자동화 | 계정 | 문제 |
|---|---|---|---|
| 구글포토 연동 | 완전 자동 | 필요 | 2025년 4월 구글이 개인 앱의 라이브러리 읽기 API를 차단 — 연동 앱들이 대량 사망 |
| Syncthing류 폴더 동기화 | 완전 자동 | 불필요 | 폰에 앱 설치·페어링 필요, 폰의 로컬 폴더만 가능 |
| 탐색기 드래그앤드롭 | 수동 | 불필요 | 매번 어떤 파일이 새 건지 사람이 기억해야 함 |
| 케이블 + 자작 도구 | 반자동 | 불필요 | 이 글의 주인공 |
나는 PC의 특정 폴더에 사진을 넣고, 케이블 연결 후 아이콘 더블클릭 한 번이면 끝나는 방식을 택했다. 구글포토에서 내려받은 사진, 폰에서 옮긴 사진, 카메라 사진 — 어디서 온 것이든 결국 PC 폴더에 모이니까, 그 폴더만 액자로 흘려보내면 된다.
요구사항은 네 가지:
- 증분 동기화 — 이미 보낸 사진은 건너뛰고 새 것만 (매번 300장을 다시 보내면 몇 분 걸린다)
- 한글 파일명 생존 — 우리나라 가족 사진은 이름에 한글이 있다
- 즉시 반영 — 복사 후 액자에 바로 나타나야 한다
- 안전장치 — "전체 삭제" 같은 위험한 동작엔 확인 절차
STEP 1. 기본 동기화 스크립트
프롬프트 1
파워셸 스크립트를 만들어줘. 기능: - C:\액자사진 폴더의 이미지(jpg/jpeg/png/webp, 하위폴더 포함)를 adb push로 태블릿 /sdcard/PhotoFrame 폴더로 복사 - adb는 C:\android-sdk\platform-tools\adb.exe - 시작 시 adb devices로 태블릿 연결을 확인하고, 연결 안 됐으면 "케이블 연결 + USB 디버깅 허용" 안내 후 종료 - 진행 상황을 콘솔에 한국어로 출력
바이브코딩으로 만든 도구는 30줄이면 충분하다. 그런데 이대로는 두 가지가 부족하다 — 새 파일 판별과, 복사 후 액자가 눈치채는 것.
STEP 2. 증분 동기화 — "이미 보낸 것"을 기억하기
프롬프트 2
증분 동기화를 추가해줘: - .pushed.tsv 파일에 (보낸 파일명, 크기)를 탭으로 기록 - 실행 시 소스 폴더의 파일을 (파일명, 크기)로 대조해서 이미 보낸 것은 건너뛰고 새 것만 push - 소스의 하위폴더는 평평하게(flat) 태블릿으로 보내고, 같은 이름인데 크기가 다른 파일은 이름 뒤에 _2, _3을 붙여 충돌 회피 - 보낼 게 없으면 "새 사진이 없습니다"라고 알리고 종료
매니페스트 방식의 장점은 기기 쪽 목록을 읽을 필요가 없다는 것(빠르다). 단점은 나중에 나온다 — 기억해두자.
STEP 3. 즉시 반영 — 여기서 하루를 태운 함정
파일을 복사만 하면 액자는 모른다. 액자 앱은 "사진 목록을 다시 읽어라"는 신호가 필요하다. PC에서는 이렇게 보내면 된다:
adb shell am broadcast -a com.handy.photoframe.REFRESH그런데 이 명령이 안드로이드 8에서는 아무리 날려도 안 먹는다. 8.0부터 암시적 브로드캐스트가 차단됐기 때문이다. 매니페스트에 receiver를 등록해도, 기기가 잠자는 동안에는 전달이 안 된다. 나는 이거 하나 때문에 "복사는 됐는데 액자에는 사진이 안 떠"의 상태로 꽤 오래 헤맸다.
프롬프트 3
해결책을 적용해줘: 1. 앱 쪽: RefreshReceiver는 매니페스트 등록을 유지하되, 브로드캐스트를 받으면 즉시 재스캔 + 현재 사진 새로 표시 2. 도구 쪽: push가 끝나면 브로드캐스트를 명시적 컴포넌트로 발송: adb shell am broadcast -a com.handy.photoframe.REFRESH -n com.handy.photoframe/.RefreshReceiver (안드로이드 8+에서는 -n으로 수신자를 정확히 지정해야 전달된다)
이제 복사 끝나자마자 액자 화면에 새 사진이 뜬다. 밤 11시~아침 7시 야간 모드라면 아침 7시부터 나타난다(액자 앱이 밤에는 렌더링을 안 하기 때문).
STEP 4. 사용자 경험 — 아이콘 하나로
.bat 파일로 감싸 더블클릭 실행 가능하게 하고, 바로가기를 작업표시줄에 고정한다.
프롬프트 4
실행 마무리를 다듬어줘: - 끝나면 콘솔이 닫히지 않게 "종료하려면 Enter" 대기 - 연결 실패 시 원인별로 다른 안내: 케이블 뽑힘 / unauthorized(태블릿에서 허용 필요) - 사용법.txt 파일도 만들어줘: 폴더에 사진 넣기 → 케이블 연결 → 아이콘 더블클릭
STEP 5. 액자 비우기 — 위험한 기능은 더 조심히
사진을 통째로 갈아끼우고 싶을 때가 있다. 이때 필요한 건 "전부 지우기"인데, 실수로 눌렀다가 가족 사진이 통째로 날아가면 재앙이다.
프롬프트 5
'액자 비우기' 스크립트를 만들어줘. 안전 요건: 1. 태블릿의 /sdcard/PhotoFrame 안의 이미지 개수를 세서 보여주고 2. "지우려면 Y를 직접 입력" 확인을 받는다 (그 외 입력은 취소) 3. 지우는 대상은 /sdcard/PhotoFrame 폴더뿐 — DCIM 같은 보관용 폴더는 절대 손대지 않는다 (경로를 하드코딩하지 말고 PhotoFrame 폴더 안에서만 작업) 4. 삭제 후 동기화 기록(.pushed.tsv)도 함께 초기화한다 (안 그러면 같은 이름·크기의 사진을 나중에 다시 넣을 때 "이미 보냈음"으로 스킵돼서 액자에 영원히 안 뜬다!) 5. 삭제 완료 후 REFRESH 신호 전송
4번이 은근한 함정이다. 매니페스트를 같이 안 지우면, "비우고 → 같은 사진 다시 넣기"가 조용히 실패한다.
실전에서 배운 것들
- adb pull은 한글을 깨뜨리고, adb push는 의외로 잘 간다 — 반대 방향으로 갈 때 문제가 생긴다면 전송 경로(명령줄 인수)에 한글을 직접 쓰지 말았는지 보자. 스크립트 파일 안에 넣어두면 인코딩 문제가 사라진다.
- 안드로이드 8+의 암시적 브로드캐스트 차단 — 도구와 앱이 "묵시적으로 통신"하려 하면 반드시 명시적 컴포넌트(-n)로.
- 매니페스트(증분 기록)는 상태다 — 이를 지우는 연산(비우기)이 있으면 매니페스트도 같이 지워야 일관성이 유지된다.
- 위험한 동작에는 타이핑 확인 — 버튼 한 번보다 "Y 입력"이 실수를 확실히 막는다.
- 동기화 방향은 한쪽으로 — PC → 태블릿 일방향(추가만)이면 실수가 적다. 양방향 동기화는 "PC에서 지운 사진이 액자에서도 사라지는" 의미까지 생각해야 한다. 나는 추가만 하는 방식을 택했다.
마무리 — 시리즈 완결
이로써 웅진북클럽 태블릿이 완전히 재탄생했다:
- 오딘으로 순정 펌웨어 부활 (1편)
- 바이브코딩으로 액자 앱 개발 (2편)
- PC 동기화 도구로 사진 공급선 확보 (3편, 이 글)
폰도, 구글 계정도, 구독료도 없이. 있던 것은 케이블과 무료 도구뿐이다.