Android 개발/Jetpack Compose

버튼 소리 직접 심었다면 Compose 1.12에서 두 번 울립니다

stackD 2026. 9. 19. 18:00
반응형

 

혹시 clickable 뒤에 LocalView.current.playSoundEffect(SoundEffectConstants.CLICK) 한 줄을 손으로 심어두셨나요? 그 코드, 젯팩 컴포즈(Jetpack Compose) 1.12로 올리는 순간 버튼이 "틱틱" 두 번 울립니다.

 

요지 한 줄: 컴포즈 인터랙션 사운드가 1.12부터 기본으로 켜지면서, 수동으로 소리를 넣어둔 코드가 이제 골칫거리가 됩니다.

 

자동 동작이 어떻게 바뀌는지, 어떻게 끄는지, 그리고 릴리스 노트 한 줄에 숨은 진짜 파괴적 변경(breaking change)까지 순서대로 짚어볼게요.

 

XML은 틱, Compose clickable은 조용했던 손삽입의 역사

기존 XML View 는 버튼을 누르면 시스템이 알아서 "틱" 소리를 냈습니다. 근데 Modifier.clickable 은 그동안 아무 소리도 안 냈어요. Modifier.clickable 에서 클릭 소리가 안 나는 문제는 코틀린 슬랙 같은 데서도 꾸준히 올라오던 불편이었다고 합니다.

 

그래서 XML 화면을 컴포즈로 옮기고 나면 "어? 터치음이 사라졌네" 하는 상황이 자주 생기거든요. 다들 어떻게 때웠냐면, 이런 식으로 손수 심었죠.

 

val view = LocalView.current
Box(
    modifier = Modifier.clickable {
        view.playSoundEffect(SoundEffectConstants.CLICK)
        onClick()
    }
)

 

여기서 하나 알아두실 게, playSoundEffect 는 시스템 설정(설정 > 소리 > 터치음)을 존중합니다. 사용자가 터치음을 꺼두면 이 코드가 있어도 소리는 안 나요. 컴포즈 터치음이 시스템 설정에 연동돼 있다는 이야기입니다. 뒤에서 다시 나오니 기억해두시면 좋겠어요.

 

 

Compose 1.12 변경점, clickable이 스스로 소리를 내는 방식

컴포즈 1.12부터는 컴포넌트 인터랙션, 그러니까 클릭이나 포커스 이동 같은 동작에 자동 사운드 이펙트가 기본으로 붙습니다. 그동안 조용하던 clickable 이 이제 스스로 시스템 클릭음을 재생하게 됐어요.

 

타임라인부터 정리하자면, 1.12.0-alpha03 이 2026년 5월 19일에 나왔고, 베타 BOM 은 대체로 1.12.0-beta02 로 이어졌습니다. 정식 1.12.0 은 7월 현재 진행 중인 것으로 보여요. 아직 안정판이 아니라서, 뒤에 나올 새 API 이름이나 시그니처는 정식 릴리스 노트에서 다시 확인하시는 게 안전합니다.

 

여기서 헷갈리기 쉬운 부분이 하나 있는데요. "소리 켜졌다는데 왜 조용하지?" 싶을 수 있습니다. 에뮬레이터거나, 무음 모드거나, 터치음을 꺼둔 기기라면 안 들려요. 앞서 말한 시스템 설정 종속 때문이지 버그가 아니더라고요.

 

SoundEffectOnInteraction 옵트아웃, 켤 팀과 끌 팀 나누기

전 앱에 소리가 깔리는 게 반갑지 않은 팀도 분명 있죠. 그래서 1.12에는 SoundEffectOnInteraction 이라는 새 Composable 이 들어와서, 컴포넌트나 특정 영역 단위로 자동 사운드를 끌 수 있게 됐습니다.

 

다만 이 SoundEffectOnInteraction 의 정확한 파라미터와 패키지 위치는 알파·베타 사이에서 바뀔 여지가 있어요. 코드로 박아두기보다는, 정식 문서에서 시그니처를 확인한 다음 적용하시는 게 낫습니다. 제가 지금 시그니처를 단정해서 적어두면 정식판에서 어긋날 수 있으니까요.

 

판단 기준은 이렇게 잡으시면 됩니다.

 

  1. 무음 UI 를 의도한 디자인 시스템 팀이라면 영역 단위로 꺼두는 게 맞습니다.
  2. 폼·설정 화면처럼 터치 피드백이 도움 되는 곳은 기본값을 그대로 두는 게 낫습니다.
  3. 전역으로 다 끄는 건 부담이 크니, 정말 필요한 화면만 골라서 끄는 걸 추천드리고 싶네요.

 

"기본으로 소리가 나는 게 UX 개선이냐"는 건 사실 논쟁적입니다. 무음을 전제로 설계한 앱엔 원치 않는 변화일 수 있으니, 팀 성격 보고 결정하시면 되겠습니다.

 

 

안드로이드 터치 사운드 이중 재생과 숨은 메인 스레드 변경

이제 도입부의 그 "틱틱" 대목입니다. 대부분의 글은 "이제 소리 난다"에서 끝나는데, 진짜 위험한 건 수동으로 playSoundEffect 를 심어둔 프로젝트예요. 자동 사운드에 수동 사운드가 겹쳐서 클릭 한 번에 소리가 두 번 나는 겁니다.

 

그래서 업그레이드 시 1순위 작업은 딱 하나입니다. 프로젝트 전체에서 playSoundEffect(SoundEffectConstants.CLICK) 를 전수 검색해서, 자동 재생과 겹치는 자리를 지우는 거예요. 이걸 안 하면 사용자 귀에 바로 티가 납니다.

 

그리고 릴리스 노트 한 줄에 묻혀 있는 진짜 폭탄이 하나 더 있어요. 시맨틱 클릭 리스너가 이제 메인 스레드에서 호출돼야 한다는 변경입니다. 백그라운드 스레드에서 클릭을 트리거하던 일부 UI 테스트가 이것 때문에 깨질 수 있습니다. 소리 문제보다 이게 CI 를 빨갛게 물들이는 조용한 원인이 될 수 있어요. 시맨틱 클릭 리스너 관련 메인 스레드 테스트 실패가 뜬다면 여기부터 의심하시면 됩니다.

 

 

포커스 내비게이션 사운드와 접근성은 별개 얘기

이 사운드가 단순 클릭음만 얘기하는 게 아니라는 점도 짚고 싶어요. 키보드나 D-pad, 접근성 도구로 포커스를 이동할 때 나는 피드백에서도 의미가 있습니다. TV 나 차량 환경처럼 화면을 직접 안 만지는 상황에선 이 포커스 이동 피드백이 값어치를 하는 것 같아요.

 

그리고 자주 헷갈리는 건데, 이건 햅틱(LocalHapticFeedback)과 완전히 다른 사안입니다. 검색하면 진동 피드백 글이 잔뜩 섞여 나오는데, 1.12에서 바뀌는 건 사운드 쪽이고 햅틱 기본값은 그대로더라고요.

 

솔직히 팀에 따라선 "지금 올릴 이유"가 약할 수도 있습니다. 소리 하나 얻자고 메인 스레드 강제 때문에 테스트를 뜯어고치는 비용이 더 클 수 있으니까요. 그건 각자 상황 보고 저울질하시면 됩니다.

 

정리하면 세 가지예요. clickable 이 스스로 소리를 내기 시작했고, 수동 코드가 있으면 이중 재생부터 걷어내야 하고, 메인 스레드 변경 때문에 CI 를 점검해야 합니다. 기본값이 바뀌었을 때 제일 먼저 발목 잡는 코드는, 그동안 부지런히 손으로 채워둔 바로 그 한 줄입니다. 업그레이드 브랜치를 파기 전에 playSoundEffect 부터 전수 검색해두는 것, 저 같으면 딱 그 순서로 손대겠습니다.

 

반응형
LIST