태그 안드로이드위젯RemoteViews앱 개발디버깅
전체 글 보기

안드로이드

안드로이드 위젯: 미리보기가 된다고 위젯이 되는 건 아니었다

안드로이드 위젯을 네 번 연달아 깨진 채로 내보냈습니다. 미리보기는 멀쩡했고 빌드도 통과했는데, 홈 화면에 올리면 죽었습니다.

2026년 8월 16일 3분

안드로이드 위젯을 손보다가 같은 버그를 네 번 연달아 내보냈습니다. 빌드는 매번 통과했고, 위젯 고르기 화면의 미리보기도 멀쩡했습니다. 그런데 홈 화면에 올리면 “위젯을 사용할 수 없음” 이 떴습니다.

미리보기와 실제는 다른 것을 실행합니다

안드로이드 위젯을 다룰 때 이게 가장 중요한 사실입니다.

위젯 고르기 화면에 보이는 그림은 previewLayout레이아웃만 펼쳐서 그린 것입니다. 반면 홈 화면에 올린 위젯은 거기에 더해 provider 코드가 실제로 돌아갑니다. 값을 채우고 색을 입히고 클릭을 연결하는 그 코드요.

그래서 provider 쪽 문제는 미리보기로 절대 안 잡힙니다. 저는 이걸 모른 채로 “미리보기 잘 나오네” 를 통과 신호로 썼습니다.

첫 번째 원인: 쓰면 안 되는 태그

RemoteViews 는 아무 뷰나 못 그립니다. @RemoteView 라는 표시가 붙은 클래스만 펼칠 수 있습니다.

그런데 우리가 흔히 쓰는 <View> 에는 그 표시가 없습니다. 저는 진행 막대의 빈 칸을 만들려고 이렇게 썼습니다.

<View
    android:layout_width="0dp"
    android:layout_weight="1" />

이 한 줄 때문에 위젯이 통째로 안 떴습니다. <include> 도 마찬가지로 안 됩니다.

⚠️ 여기서 중요한 건 aapt 도 gradle 도 이걸 못 잡는다는 점입니다. 컴파일은 아무 불평 없이 끝납니다. 실기기에 올려야 드러납니다.

두 번째 원인: 없는 메서드를 부르고 있었다

태그를 고치고 다시 내보냈습니다. 미리보기가 정상으로 돌아왔길래 끝난 줄 알았습니다.

여전히 홈에서는 죽었습니다.

이번엔 코틀린 쪽이었습니다.

views.setFloat(id, "setLayoutWeight", ratio)

RemoteViews 의 setInt / setFloat문자열로 받은 이름을 나중에 찾아서 부릅니다. 그리고 View 에는 setLayoutWeight 라는 메서드가 없습니다. 그래서 위젯을 화면에 붙이는 바로 그 순간에 터집니다.

비율을 주고 싶으면 <clip> 을 쓰고 setImageLevel(0..10000) 로 채우면 됩니다. 이건 실제로 있는 메서드입니다.

제가 반복한 실수

두 원인은 층이 다릅니다. 하나는 레이아웃이고 하나는 provider 코드입니다.

그런데 저는 두 번 다 증상 문구가 같다는 이유로 같은 층만 다시 봤습니다. 레이아웃을 고치고 “허용된 태그만 남았다” 를 근거로 통과라고 보고했는데, 그건 첫 번째 층에 대한 답이었지 두 번째 층에 대한 답이 아니었습니다.

증상이 같아도 원인이 같다는 보장은 없습니다. 특히 실패 지점이 “화면에 안 뜬다” 처럼 뭉뚱그려진 경우에는요.

그래서 세는 것을 만들었습니다

문서에 적어두는 것으로는 안 막힙니다. 컴파일이 통과해버리니까요.

그래서 검사기를 하나 만들었습니다.

pnpm widget:check

하는 일은 두 가지입니다.

  • 위젯 레이아웃의 모든 태그를 허용 목록과 대조합니다
  • 코틀린에서 setLayoutWeight 같은 없는 메서드를 부르는지 봅니다

⚠️ 그리고 검사기가 진짜로 잡는지 되돌려서 확인했습니다. <View> 를 다시 넣어보고 종료 코드 1이 나오는 것을 봤습니다. 안 그러면 통과만 하고 아무것도 안 세는 검사기가 됩니다.

주석 안의 <View> 는 오탐이라 주석을 먼저 지우고 셉니다. 이것도 실제로 한 번 걸려서 알았습니다.

안드로이드 위젯 데이터는 앱이 돌 때만 갱신됩니다

같은 작업에서 위젯 하나만 비는 일도 있었습니다. 전체 목록 위젯은 멀쩡한데 오늘 목록 위젯만 텅 비었습니다.

원인은 데이터가 갱신되는 시점이었습니다. 위젯이 읽는 파일은 앱이 실행될 때만 새로 써집니다. 백그라운드 작업은 같은 파일을 다시 읽을 뿐이고요.

그래서 자정이 지나면 어제 데이터가 그대로 남습니다. 오늘 위젯은 날짜를 확인하지 않고 시간만 봤기 때문에, 어제 항목을 전부 “이미 지난 것” 으로 걸러내고 빈 목록이 됐습니다. 전체 위젯은 그 필터가 없어서 멀쩡해 보였고요.

날짜 확인을 넣었고, 데이터가 낡았을 때는 이렇게 바꿨습니다.

앱을 열면 오늘 일정을 불러와요

“비어있어요” 와 “못 불러왔어요” 는 사용자가 할 행동이 다릅니다. 앞은 쉬면 되고 뒤는 앱을 열어야 합니다. 아무 설명 없이 비어 있으면 그냥 고장으로 읽힙니다.

정리하면

  • 위젯 미리보기는 레이아웃만 확인해 줍니다. provider 코드는 안 돌립니다
  • RemoteViews 에서 <View><include> 는 못 씁니다. 빈 칸은 <ImageView>
  • setInt / setFloat 의 메서드 이름은 실행할 때 찾습니다. 오타나 없는 이름은 컴파일에 안 걸립니다
  • 컴파일이 통과하는 종류의 실수는 세는 것을 만들어야 막힙니다

어디까지 확인한 것인가

2026년 8월 16일, Expo SDK 56 (RN 0.85) 안드로이드 앱에서 겪은 일입니다. 빌드는 로컬 gradle, 확인은 삼성 실기기에서 했습니다.

⚠️ 검사기가 막아주는 건 제가 이미 겪은 오답들뿐입니다. RemoteViews 에서 못 쓰는 메서드가 이 셋만 있는 건 아닐 겁니다. 새로 걸리면 그때 목록에 추가하는 식으로 두었습니다.

이전 글 작심삼일을 검색하는 사람들이 고치는 법만 찾지는 않습니다