괴담집 프로젝트에서 Howler.js 사용하기

작성일:2025. 7. 8.
수정일:2025. 7. 9.

Howler는 웹에서의 오디오 제어를 위한 라이브러리로 좋은 성능에 다양한 기능을 지원한다. 특히 괴담집 프로젝트에 필요한 fade효과나 loop효과 그리고 여러 소리에 대한 개별 제어등 딱 알맞는 라이브러리라고 생각된다.

이후에 업데이트할 때에는 공간음향같은 Howler.js에서 제공하는 특수효과도 사용하여 속삭임같은 무서운 음향효과를 구현할수도 있을것 같다는 생각이다.

기본 사용법#

Typescripttypescript

howler는 기본적으로 두가지 객체를 통해 소리를 로드하고 제어한다.

  • Howl: Howl은 개별 사운드에 대한 객체이며 해당 객체를 통해 각각의 소리를 제어할 수 있다.
  • Howler: Howler는 글로벌 제어를 위한 객체이며 전체 볼륨제어와 같은 전체 사운드에 대한 제어를 가능하게 한다.

React에서의 사용#

React TSXtsx

에셋을 불러오는 작업과 React의 리렌더링은 수많은 메모리 누수를 일으킬 수 있다. 따라서 사운드를 불러오기 위해선 useRef를 활용하는것이 가장 좋다.

useRef를 사용하지 않았을때의 문제#

❌ useRef 없이 일반 변수 사용:#

React TSXtsx

문제 시나리오:

  1. "재생" 클릭 → 소리 재생 시작
  2. setCount → 컴포넌트 리렌더링
  3. let sound = null 다시 실행 → 이전 Howl 인스턴스 참조 잃음
  4. "정지" 클릭 → sound는 null이라 에러!
  5. 오디오는 백그라운드에서 계속 재생 (제어 불가)

❌ useState 사용:#

React TSXtsx
  1. UI변경이 없어 리렌더링이 불필요 한데도 소리의 변경 때문에 리렌더링이 발생할 수 있음.
  2. UI와 무관한 값은 ref에 저장한다는 철학에 위배됨ㄴ

✅ useRef 사용 (올바른 방법):#

React TSXtsx

본격적인 사용을 위한 고민#

Howler.js를 잘 사용하기 위해서 그리고 앱에서 아무 문제 없도록 사용하기 위해서 React와 관련된 몇가지 문제를 생각해 보아야 한다.

  1. 인스턴스 문제
  2. 사운드의 캐싱 문제
  3. 중복 로딩 문제

보편적인 리엑트의 훅 혹은 context를 사용하게 되면 위와 같은 문제가 발생할 수 있다.

훅을 통해 관리하면 여러 인스턴스가 겹치거나 인스턴스에 대한 제어권을 놓치게 되는 상황이 발생할 수 있고 context의 경우엔 해당 context를 벗어나면 이미 다운로드해서 캐싱됬던 메모리를 잃게 되거나 각각의 컴포넌트가 별개의 캐시를 갖게 될수도 있다.

따라서 Class형식을 통해 싱글톤 패턴을 구현하여 추상화하고 추상화된 모듈을 훅을 통하여 접근할 수 있도록 하는게 좋을것이라고 판단된다.

Class를 통해 로직을

AudioManager 만들기#

Typescripttypescript

캐싱 문제와 인스턴스 문제를 해결하기 위해 싱글톤 패턴의 클래스를 하나 만든다. 클래스를 통해서 관련 기능들을 하나로 묶을 수 있고, private을 통해 보호할 수 있다.

캐싱 시스템 구현하기#

Typescripttypescript

오디오의 캐싱과 중복 로딩을 방지하기 위해 private으로 map자료구조의 변수를 선언해준다.

프리로드 기능#

Typescripttypescript

넘겨받을 에셋의 타입을 정의하고 해당 정보를 등록한다. 이때 존재한다면 이미 존재하는걸 반환해야 한다.

로직의 큰 구조는 먼저 캐시 혹은 로딩중인것 즉 메모리를 먼저 확인하여 현재 작업해야하는 에셋과 비교한 이후에 있다면 현재 저장된 데이터를 반환하고 그렇지 않다면 loadAudioAsset을 활용해 howl 객체를 만든다. 해당 객체가 load 되면 onload메소드를 통해 Promise의 결과값을 위한 resolve({howl,asset,loadedAt})을 반환한다.

제어 기능들#

Typescripttypescript

이제 기본적인 제어에 대한 구현은 완료 되었다. 실제로 이 모듈이 어떻게 사용될지는 구조를 조금 더 살펴보면서 정해야 할것으로 보인다.