리액트 오디오 컴포넌트 만들기 with 타입스크립트 & 리코일

Chocolajin·2023년 3월 13일
0

배움

목록 보기
1/5

결과물

완성코드

import { atom, useRecoilState } from 'recoil';
import myAudio from './assets/myAudio.mp3'; 
import { useEffect, useRef } from 'react';

//배경음악 플레이, 일시정지
const playState = atom<boolean>({
  key: 'playState',
  default: false,
});

function AudioPlayer () {
  const myRef = useRef<HTMLAudioElement>(null);
  const [play, setPlay] = useRecoilState(playState);
  // 재생
  const start = () => {
    if (myRef.current) {
      myRef.current.play()
    }
    setPlay(true);
  };
  // 일시 정지
  const stop = () => {
    if (myRef.current) {
      myRef.current.pause()
    }
    setPlay(false);
  };

  useEffect(() => {
    if (!myRef.current) return;
    if (play) {
      myRef.current.play();
    } else myRef.current.pause();
  }, [play]);

  return (
    <>
      <h1>AudioPlayer</h1>
      <audio ref={myRef} src={myAudio} controls loop></audio>
      <br /> 
      <br />
      {play ?
        // 일시정지 버튼
        (<button onClick={stop}>
          일시정지
        </button>) :
        // 재생 버튼
        (<button onClick={start}>
          재생
        </button>)
      }
    </>
  )
}

export default AudioPlayer ;

과정

프로젝트 생성

  • my-app 이란 이름의 타입스크립트기반 프로젝트 생성
    npx create-react-app my-app --template typescript

  • 리코일 설치
    npm install recoil

오디오 파일 들고오기

오디오 파일을 들고오려면 세 단계가 필요하다.

  1. 타입스크립트 선언 파일 d.ts을 만든다.
  2. mp3 형식의 모듈을 선언(declare) 한다.
  3. 컴포넌트에서 mp3파일을 불러온다.

코드와 함께 자세히 보자.

파일이름.d.ts 파일 생성

Audio라는 이름의 d.ts파일을 만든다.

타입스크립스 선언파일이란?

모듈 선언

위에서 생성한 Audio.d.ts 파일에 다음의 코드를 작성한다.

declare module "*.mp3" {
  const value: string;
  export default value;
}

파일명이 mp3로 끝나는 새로운 모듈을 선언하겠다는 뜻

참고 : 타입스크립트 + 웹팩 환경에서 mp3 파일 임포트(import) 하는 방법

mp3파일 불러오기

import myAudio from './assets/myAudio.mp3';

myAudio라는 이름으로 './assets/myAudio.mp3' 이 경로에 있는 음원 파일을 들고 온다.

리코일 사용

RecoilRoot

recoil 상태를 사용하는 컴포넌트는 부모 트리 어딘가에 나타나는 RecoilRoot 가 필요하다. 루트 컴포넌트가 RecoilRoot를 넣기에 가장 좋은 장소다.

import { RecoilRoot } from 'recoil';

function App() {
  return (
    <RecoilRoot>
      <AudioPlayer />
    </RecoilRoot>
  );
}

AudioPlayer컴포넌트의 부모루트에 RecoilRoot를 임포트하고
<RecoilRoot></RecoilRoot>로 감싸준다.

리코일 공식 문서 : 리코일 시작

atom

import { atom } from 'recoil';

const playState = atom<boolean>({
  key: 'playState',
  default: false,
});

playState 라는 이름으로 atom 선언. boolean타입.
재생true중인지 일시정지false 중인지 상태를 나타낼 값이다.

useRecoilState

import { useRecoilState } from 'recoil';

const [play, setPlay] = useRecoilState(playState);

playState값을 읽고(play) 쓰기(setPlay) 위해 useRecoilState함수에 playState를 넣어준다.

ref

Ref와 DOM

import { useRef } from 'react';

const myRef = useRef<HTMLAudioElement>(null);

미디어의 재생을 관리할 때 Ref는 render 메서드에서 생성된 DOM 노드나 React 엘리먼트에 접근하는 방법을 제공한다.

myRef라는 이름으로 useRef를 쓰겠다. 타입은 <HTMLAudioElement>로 선언해주면 오디오를 쓰겠단소리다.

Ref에 접근하기

render 메서드 안에서 ref가 엘리먼트에게 전달되었을 때, 그 노드를 향한 참조는 ref의 current 어트리뷰트에 담기게 됩니다.
Ref 객체의 current 라는 프로퍼티를 사용하면 DOM 노드를 참조할 수 있다.

재생

  const start = () => {
    if (myRef.current) {
      myRef.current.play()
    }
    setPlay(true);
  };

ref의 값은 노드의 유형에 따라 다른데 여기서는 오디오에 쓰였기때문에 play(), puase() 에 접근 할 수 있다.

myRef(내가 지어준이름)의 current(useRef프로퍼티)의 play()를 실행

일시정지

  const stop = () => {
    if (myRef.current) {
      myRef.current.pause()
    }
    setPlay(false);
  };

useEffect

import { useEffect } from 'react';

  useEffect(() => {
    if (!myRef.current) return;
    if (play) {
      myRef.current.play();
    } else myRef.current.pause();
  }, [play]);

return

<audio ref={myRef} src={myAudio} controls loop></audio>

audio 태그에 ref를 사용하여 play()/pause()로 재생/일시정지를 통제한다.
src에 불러온 오디오 파일을 넣는다.
controls는 기본 플레이어 제어패널을 보이도록 한다. 없으면 보이지 않는다.
loop는 재생이 끝나고 반복 재생 여부를 설정한다.

그 외에도 다양한 속성이 있다.

{play ?
  // 일시정지 버튼
  (<button onClick={stop}>
    일시정지
  </button>) :
// 재생 버튼
(<button onClick={start}>
    재생
  </button>)
}

play가 true이면 재생중이라는 뜻이므로 일시 정지 버튼이 보이도록 하고, 버튼을 누르면(onClick) 일시정지 함수(stop)가 실행되게 한다.

play가 false면 일시정지중이라는 뜻이므로 재생 버튼이 보이도록 하고, 버튼을 누르면(onClick) 재생 함수(start)가 실행되게 한다.

적절한 아이콘로 꾸미면 멋진 재생버튼이 될 것 같다.

배운점

  1. 타입스크립트에서 오디오 파일을 불러올땐 d.ts파일을 만들어 mp3 형식의 모듈을 선언(declare) 하고 파일을 불러오는 방법

  2. 리코일 사용 할 때 부모루트에 리코일 선언하기, atom, useRecoilState 사용 방법

  3. ref와 Ref에 접근하는 방법

  4. audio 태그의 여러가지 속성

profile
뱁새 개발자 황새 따라잡다

1개의 댓글

comment-user-thumbnail
2023년 11월 24일

브라우저에서 autoplay를 막아놨다는 에러가 자꾸 떠서 이 글 보고 따라했는데 성공했어요 감사합니다! ㅠㅠ

답글 달기