Wear OS 워치페이스를 Google Play에 출시해봤어요 - WFF, AAB, 두 번의 리젝
핵심 요약
- 2026년부터 Wear OS 워치페이스는 WFF(선언적 XML)가 필수이고, AAB에는 코드 없이 리소스만 들어가요.
- 소스가 없어도 AGP가
R클래스를 dex로 넣어 거부되니,minify는 켜고shrinkResources는 꺼야 해요. watch_face_info.xml의Editable기본값이false라 선언을 빠뜨리면 편집 버튼이 사라지고, 리뷰어는 기능이 없다며 리젝해요.- Play Console에는 사전 체크리스트가 없으니 WFF validator, bundletool, Memory Footprint Evaluator를 제출 전에 직접 돌려보세요.
워치페이스 프로젝트를 Google Play에 실제로 출시까지 완료했어요. Watch Face Studio를 쓰지 않고 자체 DSL에서 WFF XML을 생성하는 파이프라인이라서, 스토어 요구사항과 AAB 구조를 처음부터 끝까지 다 만져봐야 했습니다.
2026년은 워치페이스를 올리기에 꽤 재미있는 시기예요. 1월부터 WFF(Watch Face Format)가 모든 Wear OS 기기의 워치페이스 설치에 필수가 됐고, 9월 15일부터는 Wear OS 앱의 64비트 요구사항도 적용됐습니다. 문서는 다 있는데, 실제로 올려보면 문서에 안 나오는 곳에서 막혀요. 이 글은 그 막힌 지점들의 기록입니다.

2026년 기준 알아야 할 규칙
- WFF 필수 - 2026년 1월부터 모든 Wear OS 기기에서 워치페이스 설치에는 WFF(선언적 XML)가 필요해요. 렌더링 코드를 앱에 넣는 옛 방식은 신규 설치에서 막힙니다.
- 64비트 요구 (9월 15일~) - 네이티브 코드를 포함한 Wear OS 앱은 64비트 버전도 제공해야 해요. 다만 WFF 워치페이스는
hasCode="false"라 네이티브 코드가 없어서 이 요구사항의 직접 대상은 아니었습니다. 네이티브 바이너리(.so)를 포함하는 일반 Wear 앱 쪽에서 신경 써야 하는 요구사항이에요. - 아이콘 규격 WO-G4 - 2026년 7월 15일부터 적용. 워치페이스 전용 앱 아이콘은 워치페이스를 원형으로, 가장자리까지 꽉 차게 표시해야 하고 워치페이스 외의 텍스트/기기 프레임을 넣으면 안 됩니다.
- 타겟 API - Wear OS 앱은 API 35+ 타겟이 필요해요(폰 앱은 36).
targetSdk를 명시하지 않으면 최종 매니페스트에서minSdk와 같은 값으로 처리될 수 있는데, 이 경우 Play 요구사항에 걸립니다.
Play Console에는 체크리스트가 없어요
착각하기 쉬운데, Play Console 어디에도 "워치페이스 요구사항 체크리스트" 같은 화면은 없습니다. 실제 플로우는 이래요:
- Setup → Advanced settings → Form factors에서 Wear OS를 추가
- 안내에 따라 Wear OS 스크린샷과 AAB를 테스트 트랙에 업로드
- Advanced settings로 돌아가 Wear OS Manage → 배포 동의
- 릴리스 만들 때 폼 팩터 드롭다운에서 Wear OS only 선택,
wear:트랙으로 출시
요구사항 체크는 이 UI가 아니라 심사 과정에서 일어나요. 사전에 검증하려면 구글이 공개한 별도 도구들을 로컬에서 돌려야 합니다(아래에서 다룹니다).
AAB의 구조가 일반 앱과 다릅니다
WFF 워치페이스의 AAB는 코드가 아니라 리소스의 묶음이에요. 실제로 들어간 것:
AndroidManifest.xml-hasCode="false",uses-feature android.hardware.type.watchres/raw/watchface.xml- WFF 씬: 시침/텍스트/Transform 표현식, 5개 팔레트의<Flavors>프리셋, 컴플리케이션 슬롯res/raw-round/,res/raw-notround/- 기기 화면 모양별 레이아웃 변형res/xml/watch_face_info.xml-Editable,MultipleInstancesAllowed,Provider선언res/xml/watch_face_shapes.xml- 지원하는 화면 모양 목록
이 구조에서 두 군데가 실제로 리젝을 만들었습니다.
첫 번째 함정: 코드가 없는데 dex가 생겨요
처음 빌드한 AAB를 bundletool로 검증했더니 거부됐어요. 메시지는 "Watch face with minSdk >= 33 cannot have dex files".
이상한 게, 이 프로젝트는 소스가 한 줄도 없습니다. hasCode="false"인데 왜 dex가 있을까 했더니, AGP가 생성한 R 클래스를 dex로 컴파일해서 넣고 있었어요. 소스가 없어도 R은 항상 생기니까요.
해결은 반직관적이었습니다:
buildTypes {
all {
isMinifyEnabled = true // dex를 "난독화"가 아니라 "제거"에 씀
isShrinkResources = false // 켜면 WFF 리소스가 날아감
}
}
minify를 켜면 R8이 dex를 비워서 검증을 통과하고, shrinkResources를 켜면 리소스 수축기가 WFF XML을 쓸모없다고 판단해서 지워버려서 꺼야 해요. "최적화 켜기 + 리소스 최적화 끄기"라는 조합은 겪어보기 전엔 나오기 어려운 답이었습니다.
두 번째 함정: 같은 사유로 두 번 리젝
vc2(1.1.0)를 올렸더니 리젝됐어요. 사유는 "Wear 앱 기능이 설명된 대로 작동하지 않음". 스토어 등록정보에 "5개 팔레트, 3개 커스터마이징 가능한 컴플리케이션 슬롯"을 적어뒀는데, 리뷰어가 그 기능을 못 찾았다는 뜻입니다.
1차 원인으로 짐작한 건 watch_face_shapes.xml이었어요. CIRCLE만 선언돼 있었는데, 리뷰에 쓰인 기기나 구성이 비원형이면 피커에 워치페이스 자체가 안 뜹니다. RECTANGLE을 추가하고 vc3을 올렸죠.
그런데 같은 사유로 또 리젝.

다시 뜯어보니 실제 원인은 watch_face_info.xml이었어요. 커스터마이징 가능한 워치페이스는 <Editable value="true"/>를 선언해야 하는데, 이 속성의 기본값이 false입니다. 선언이 없으면 Wear OS가 시계에서 "Edit(편집)" 버튼 자체를 숨겨요. 결과적으로 리뷰어가 커스터마이징 화면에 접근할 수 없었던 거예요. 형태 선언 문제는 곁가지였고 이게 주 원인이었습니다.
vc4(1.1.2)에서는 이렇게 고쳤습니다:
watch_face_info.xml에<Editable value="true"/>추가MultipleInstancesAllowed를true로 - Flavors 사용 시 validator가 요구했던 설정- 모든 컨피규레이션 요소에
screenReaderText추가 (TalkBack 접근성. 단ComplicationSlot에는 선언 불가 - 공식 validator가 거부합니다) watch_face_shapes.xml에CIRCLE+RECTANGLE모두 선언
이 버전이 승인돼서 지금 Play에 라이브로 있습니다.

리뷰어가 못 본 화면
참고로 리뷰어에게 안 보였던 게 이런 화면이에요 - 5개 팔레트 프리셋입니다. AAB에는 분명 들어있었는데 Editable 선언이 없어서 리뷰어가 이 화면에 도달할 수 없었어요.

제출 전에 돌려본 공식 검증 도구 3종
제출 전에 서로 다른 문제를 잡아낼 수 있는 공식 도구를 세 가지 돌렸어요:
- WFF validator - XML이 WFF 스키마를 만족하는지.
res/raw,raw-round,raw-notround세 변형을 각각 검사해야 해요 - bundletool -
build-apks로 AAB → APK 변환이 되는지 + dex 유무 같은 패키지 규칙 - Memory Footprint Evaluator - Play가 실제로 쓰는 도구. ambient 10MB / active 100MB 한도를 검사
이 외에 AOD 모드는 저희가 따로 프리플라이트를 만들어서, 하루 10분 간격 × 텍스트 크기/시간 형식 조합 288개를 샘플링해 밝은 픽셀 비율을 재봤어요. 공식 한도가 최대 15%인데 실측 최대는 3.36%가 나왔습니다 - 공식 기준 대비 꽤 여유 있는 값이었어요.
배포 자동화에서 마지막으로 남은 수동 단계
업로드는 서비스 계정으로 play-publish.ts 스크립트를 만들어 자동화했어요 - AAB 업로드, 등록정보 갱신, wear:internal/wear:production 트랙 릴리스까지 됩니다.
그런데 한 번 리젝된 앱은 API 커밋이 changesNotSentForReview=true로 떨어져요. 심사 요청이 자동으로 안 가고, Play Console → Publishing overview에서 "Send changes for review"를 수동으로 한 번 눌러야 합니다. 완전 자동화를 노렸는데 마지막 클릭 하나가 남았어요.
정리하면
- WFF 워치페이스의 AAB는 코드가 아니라 리소스 묶음 - 그래서 dex가 있으면 오히려 거부됨
watch_face_info.xml의Editable은 기본값이 false - 선언 빠뜨리면 시계에서 Edit 버튼이 사라지고, 리뷰어는 기능이 없다고 판단함watch_face_shapes.xml에 선언 안 된 화면 모양의 기기에서는 피커에 아예 안 뜸- Play Console에는 사전 체크리스트가 없어서, 제출 전에 공식 검증 도구를 직접 돌려보는 게 실질적인 대비책
- 두 번 리젝된 뒤 vc4로 승인. 두 리젝의 문구는 같았지만 원인은 달랐어요
워치페이스를 올릴 계획이라면 Editable과 shapes부터 확인해보세요. 저희는 여기서 심사 사이클을 꽤 많이 소모했어요.
이 글에서 다룬 AAB 구조와 심사 과정을 거쳐 출시된 최종 워치페이스는 Google Play의 Ridgeline입니다.
사용한 도구
- JDK 17 + Gradle 8.9 + bundletool (
~/toolchains에 별도 구성 - 시스템 java가 JDK 8이라 AGP 8을 못 돌림) - Google 공식 WFF validator + Memory Footprint Evaluator (github.com/google/watchface)
scripts/play-publish.ts- 서비스 계정으로 AAB 업로드/릴리스, dry-run 지원- AOD 발광 픽셀 프리플라이트 - 288 조합 샘플링
참고
- WFF 문서 - 2026년 1월부터 필수 명시
- Wear OS 앱 품질 가이드 - 아이콘 규격 WO-G4 포함
- 64비트 요구사항 안내 - 2026년 9월 15일부터
- Play Console 워치페이스 게시 절차
자주 묻는 질문
Q. Watch Face Studio로 만들어도 같은 함정이 있나요?
Watch Face Studio가 패키징을 처리하기 때문에, 이 글에서 겪은 수동 AAB 구성 과정의 dex 문제를 직접 만날 가능성은 낮아요. 다만 Editable/커스터마이징 선언과 스토어 등록정보의 기능 설명 일치는 어느 도구를 쓰든 리뷰에서 걸릴 수 있습니다.
Q. 유료 워치페이스라서 더 까다로운가요? 결제/판매자 설정은 별개고, 심사 자체는 기능 동작과 품질 기준 중심이었어요. 리젝 사유도 기능이 설명대로 작동하지 않는다는 내용이었습니다.