블로그 목록
apps

expo-audio로 앱에 사운드 붙이기 — expo-av 걷어내고 효과음·배경음 재생하기

버튼 탭에 효과음 하나 넣으려고 오디오 라이브러리를 찾다가 알게 됐다. 늘 쓰던 expo-av가 SDK 53부터 deprecated 됐고, 오디오는 expo-audio, 비디오는 expo-video로 쪼개졌다는 것.

expo-avAudio.Sound.createAsync는 명령형이라 로딩·재생·언로드를 직접 챙겨야 했다. 언로드를 깜빡하면 사운드 인스턴스가 쌓여서 메모리가 새기도 했고. expo-audio는 훅 기반이라 이 뒷정리를 알아서 해준다.

설치

npx expo install expo-audio

app.json에 플러그인도 넣어준다. 마이크 권한이 필요 없는 재생 전용이면 옵션은 비워도 된다.

{
  "plugins": ["expo-audio"]
}

효과음 재생

핵심은 useAudioPlayer 훅이다. 소스를 넘기면 플레이어를 만들어주고, 컴포넌트가 언마운트될 때 알아서 해제한다.

import { useAudioPlayer } from 'expo-audio';
import { Pressable, Text } from 'react-native';

export default function TapButton() {
  const player = useAudioPlayer(require('./assets/pop.mp3'));

  const onPress = () => {
    player.seekTo(0); // 연타해도 처음부터 다시 재생
    player.play();
  };

  return (
    <Pressable onPress={onPress}>
      <Text>탭</Text>
    </Pressable>
  );
}

여기서 seekTo(0)가 포인트다. play()만 부르면 이미 끝까지 재생된 사운드는 다시 안 울린다. 효과음은 연타되는 경우가 많으니 매번 커서를 앞으로 되감아줘야 소리가 난다. 이거 몰라서 "왜 한 번만 나오지" 하고 한참 봤다.

배경음 반복 재생

배경음은 화면 상태를 구독해서 반복 여부를 켜준다. useAudioPlayerStatus로 재생 상태도 읽을 수 있다.

import { useAudioPlayer, useAudioPlayerStatus } from 'expo-audio';
import { useEffect } from 'react';

function Bgm() {
  const player = useAudioPlayer(require('./assets/bgm.mp3'));
  const status = useAudioPlayerStatus(player);

  useEffect(() => {
    player.loop = true;
    player.volume = 0.4;
    player.play();
  }, [player]);

  return null;
}

무음 스위치에서도 소리 내기

iOS는 기기 무음 스위치가 켜져 있으면 앱 사운드도 막는다. 게임 효과음처럼 무음이어도 나와야 하는 소리는 오디오 모드를 따로 잡아준다.

import { setAudioModeAsync } from 'expo-audio';

await setAudioModeAsync({ playsInSilentMode: true });

정리

expo-av에서 넘어오는 마이그레이션은 생각보다 간단했다. createAsync + 수동 unloadAsync 패턴을 useAudioPlayer 훅 하나로 바꾸니 언로드 코드가 통째로 사라졌다. 효과음은 seekTo(0) 되감기, 배경음은 loop, iOS 무음은 playsInSilentMode — 이 셋만 기억하면 대부분 커버된다.