오디오 플레이리스트 완전 정리
단일 곡 재생, 체크박스 연속 재생, ended 이벤트와 confirm 재생 반복을 한 번에 정리합니다.
<audio id="audio" controls></audio>
<script>
const audioFiles = ["media/Aegukga.mp3", "media/MoonGlow.mp3", "media/EmbraceableYou.mp3"];
let currentIndex = -1;
let audio = null;
function play(index) {
audio = document.getElementById("audio");
audio.src = audioFiles[index];
audio.play();
currentIndex = index;
}
function pause(index) {
if (audio == null) return;
if (currentIndex != index) return;
audio.pause();
}
function startPlay() {
playIndex = -1;
songs = document.getElementsByClassName("song");
for (let i = 0; i < songs.length; i++) {
if (songs[i].checked == true) {
playIndex = i;
audio.src = songs[i].value;
audio.play();
audio.onended = playNext;
return;
}
}
}
</script>
오디오 파일들은 세 가지 흐름을 보여 줍니다. 첫 번째는 표에서 한 곡을 재생/중지하는 방식, 두 번째는 체크된 곡을 끝날 때마다 다음 곡으로 넘기는 방식, 세 번째는 곡이 끝나면 confirm으로 다시 재생할지 묻는 방식입니다.
- audioFiles 배열은 재생할 파일 목록입니다.
- currentIndex는 현재 재생 중인 곡 번호입니다.
- checkbox.song은 연속 재생할 곡 선택 상태입니다.
- audio.onended는 곡이 끝났을 때 다음 동작을 연결합니다.
첫 번째 예제는 테이블의 각 행에 재생 버튼과 중지 버튼을 둡니다. play(index)는 배열에서 파일 경로를 골라 audio.src에 넣고 play합니다.
| 변수 | 역할 | 예시 |
|---|---|---|
| audioFiles | 파일 경로 배열 | media/Aegukga.mp3 |
| currentIndex | 현재 곡 번호 | 0, 1, 2 |
| audio | audio 요소 | document.getElementById("audio") |
| play(index) | 곡 재생 | audio.play() |
pause 함수는 audio가 null이면 아무것도 하지 않고, 현재 재생 중인 곡 번호와 버튼의 index가 다르면 멈추지 않습니다. 다른 곡의 중지 버튼으로 현재 곡을 멈추는 혼동을 막는 구조입니다.
- 오디오가 아직 준비되지 않았으면 return합니다.
- currentIndex와 index가 다르면 return합니다.
- 같은 곡이면 audio.pause()를 호출합니다.
두 번째 예제는 class="song"인 체크박스를 모두 가져와 처음 체크된 곡을 재생합니다. 이후 곡이 끝나면 onended로 playNext가 호출됩니다.
songs = document.getElementsByClassName("song");
for (let i = 0; i < songs.length; i++) {
if (songs[i].checked == true) {
playIndex = i;
audio.src = songs[i].value;
audio.play();
audio.onended = playNext;
return;
}
}
playNext는 현재 곡 다음 인덱스로 이동하고, 그 곡이 체크되어 있으면 재생합니다. 체크되어 있지 않으면 다시 playNext를 호출해 다음 체크 곡을 찾습니다.
| 상황 | 처리 |
|---|---|
| 마지막 곡 종료 | audio.onended = null 후 return |
| 다음 곡 체크됨 | src 변경 후 play |
| 다음 곡 체크 안 됨 | playNext 재호출 |
| 선택 곡 없음 | startPlay가 아무 곡도 재생하지 않음 |
ended 이벤트는 재생이 끝난 순간 실행됩니다. 연속 재생에서는 다음 곡으로 넘기는 트리거이고, confirm 예제에서는 다시 재생할지 묻는 트리거입니다.
- audio.onended = playNext는 함수 참조를 등록합니다.
- 모든 곡이 끝나면 onended를 null로 바꿔 반복 호출을 막습니다.
- confirm 예제에서는 사용자가 확인을 누르면 audio.play()를 다시 호출합니다.
- 취소를 누르면 아무 동작도 하지 않고 종료됩니다.
confirm("다시할까요?")는 확인이면 true, 취소면 false를 반환합니다. 원문 예제는 true일 때 같은 audio를 다시 play합니다.
audio.onended = function () {
let res = confirm("다시할까요?");
if (res == true) {
audio.play();
}
};
체크박스의 value에는 실제 오디오 파일 경로가 들어갑니다. startPlay와 playNext는 이 value를 audio.src에 넣어 재생합니다.
| 곡 | value | 용도 |
|---|---|---|
| 애국가 | media/Aegukga.mp3 | 체크 시 재생 목록 포함 |
| Moon Glow | media/MoonGlow.mp3 | 체크 시 재생 목록 포함 |
| Embraceable You | media/EmbraceableYou.mp3 | 체크 시 재생 목록 포함 |
| cheek.wav | media/cheek.wav | 확장 가능한 효과음 파일 |
오디오 예제에서 상태 변수는 현재 곡과 전체 곡 목록을 기억합니다. 상태가 없으면 어떤 버튼이 어떤 곡을 멈춰야 하는지, 다음 곡이 무엇인지 알기 어렵습니다.
- currentIndex는 단일 재생 테이블에서 현재 곡을 구분합니다.
- playIndex는 체크박스 연속 재생에서 현재 곡 위치입니다.
- songs는 checkbox 요소들의 HTMLCollection입니다.
- audio는 실제 재생을 담당하는 audio 요소입니다.
| 개선 | 이유 |
|---|---|
| 선택 곡 없음 안내 | startPlay가 조용히 끝나는 문제를 막습니다. |
| 재귀 대신 반복문 | 체크 안 된 곡이 많아도 흐름이 명확합니다. |
| 현재 곡 표시 | 사용자가 어떤 곡이 재생 중인지 알 수 있습니다. |
| 정지 버튼 추가 | 연속 재생을 중간에 멈출 수 있습니다. |
| ended 이벤트 정리 | 다른 재생 모드와 충돌을 줄입니다. |
- audio 요소 id가 스크립트와 일치합니다.
- audioFiles 배열 경로가 실제 파일 위치와 맞습니다.
- play(index)는 currentIndex를 갱신합니다.
- pause(index)는 다른 곡 버튼이면 무시합니다.
- startPlay는 첫 번째 체크된 곡을 찾아 재생합니다.
- 마지막 곡 후 onended를 null로 바꿉니다.
| 실수 | 문제 | 해결 |
|---|---|---|
| audio가 null인데 pause 호출 | 아직 재생한 곡이 없어 오류나 무의미한 동작이 됩니다. | audio == null이면 return합니다. |
| 다른 곡 중지 버튼으로 현재 곡 중지 | 사용자 의도와 다르게 재생이 멈춥니다. | currentIndex와 index를 비교합니다. |
| 선택 곡이 없을 때 안내 없음 | 버튼을 눌러도 아무 일도 안 일어난 것처럼 보입니다. | 체크된 곡이 없으면 메시지를 출력합니다. |
| onended 정리 누락 | 모든 곡 이후에도 핸들러가 남습니다. | 마지막 곡에서 audio.onended = null로 정리합니다. |
| 파일 경로 오류 | 플레이어는 보이지만 재생되지 않습니다. | value와 audioFiles 경로를 실제 파일 위치에 맞춥니다. |
핵심 한 줄 요약
Tags
'php' 카테고리의 다른 글
| localStorage 실습 앱 완전 정리 (0) | 2026.07.17 |
|---|---|
| 웹 스토리지 실습 완전 정리 (0) | 2026.07.17 |
| Canvas 그림판 완전 정리 (0) | 2026.07.16 |
| JS 비디오 제어 · watchPosition 완전 정리 (0) | 2026.07.16 |
| JS Geolocation 완전 정리 (0) | 2026.07.16 |
왕진 블로그

댓글