Javascript30과 VanillaJS

Javascript 30은 Wes Bos가 강의하는 Vanilla JS만을 이용하여 30개의 프로젝트를 만드는 프로그램이다. 프레임워크, 컴파일러, 라이브러리 등이 없는 순수한 자바스크립트인 Vanilla JS로 완벽한 결과물을 만들 수 있다. 그래도 JS를 접한지 1년이 넘어가고, 나름 만들어본 프로젝트도 많았지만 Day 1을 시작하며 한참을 반성했다.

Javscript30 시작하기

Javascript 30 사이트에서 강의를 제공하고, 유튜브에서도 똑같은 강의가 올라와 있어서, 굳이 가입할 필요가 없다.

제작자가 올린 Github의 JavaScript30 프로젝트를 fork하여 시작해도 되고, 코드만 다운받아도 된다.

Course를 공부하는 방법은 간단하다. 각 프로젝트마다 index-START.html 파일과 index-FINISHED.html 파일이 있는데, START로 문제를 해결하고, FINISHED로 모범답안을 참고하면 된다.

Day 1 - Javascript Drum Kit

START

이제 index-START.html를 드럼 킷으로 만들어보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>JS Drum Kit</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="keys">
<div data-key="65" class="key">
<kbd>A</kbd>
<span class="sound">clap</span>
</div>
<div data-key="83" class="key">
<kbd>S</kbd>
<span class="sound">hihat</span>
</div>
<div data-key="68" class="key">
<kbd>D</kbd>
<span class="sound">kick</span>
</div>
<div data-key="70" class="key">
<kbd>F</kbd>
<span class="sound">openhat</span>
</div>
<div data-key="71" class="key">
<kbd>G</kbd>
<span class="sound">boom</span>
</div>
<div data-key="72" class="key">
<kbd>H</kbd>
<span class="sound">ride</span>
</div>
<div data-key="74" class="key">
<kbd>J</kbd>
<span class="sound">snare</span>
</div>
<div data-key="75" class="key">
<kbd>K</kbd>
<span class="sound">tom</span>
</div>
<div data-key="76" class="key">
<kbd>L</kbd>
<span class="sound">tink</span>
</div>
</div>

<audio data-key="65" src="sounds/clap.wav"></audio>
<audio data-key="83" src="sounds/hihat.wav"></audio>
<audio data-key="68" src="sounds/kick.wav"></audio>
<audio data-key="70" src="sounds/openhat.wav"></audio>
<audio data-key="71" src="sounds/boom.wav"></audio>
<audio data-key="72" src="sounds/ride.wav"></audio>
<audio data-key="74" src="sounds/snare.wav"></audio>
<audio data-key="75" src="sounds/tom.wav"></audio>
<audio data-key="76" src="sounds/tink.wav"></audio>

<script></script>
</body>
</html>

FINISHED

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>JS Drum Kit</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="keys">
<div data-key="65" class="key">
<kbd>A</kbd>
<span class="sound">clap</span>
</div>
<div data-key="83" class="key">
<kbd>S</kbd>
<span class="sound">hihat</span>
</div>
<div data-key="68" class="key">
<kbd>D</kbd>
<span class="sound">kick</span>
</div>
<div data-key="70" class="key">
<kbd>F</kbd>
<span class="sound">openhat</span>
</div>
<div data-key="71" class="key">
<kbd>G</kbd>
<span class="sound">boom</span>
</div>
<div data-key="72" class="key">
<kbd>H</kbd>
<span class="sound">ride</span>
</div>
<div data-key="74" class="key">
<kbd>J</kbd>
<span class="sound">snare</span>
</div>
<div data-key="75" class="key">
<kbd>K</kbd>
<span class="sound">tom</span>
</div>
<div data-key="76" class="key">
<kbd>L</kbd>
<span class="sound">tink</span>
</div>
</div>

<audio data-key="65" src="sounds/clap.wav"></audio>
<audio data-key="83" src="sounds/hihat.wav"></audio>
<audio data-key="68" src="sounds/kick.wav"></audio>
<audio data-key="70" src="sounds/openhat.wav"></audio>
<audio data-key="71" src="sounds/boom.wav"></audio>
<audio data-key="72" src="sounds/ride.wav"></audio>
<audio data-key="74" src="sounds/snare.wav"></audio>
<audio data-key="75" src="sounds/tom.wav"></audio>
<audio data-key="76" src="sounds/tink.wav"></audio>

<script>
function removeTransition(e) {
if (e.propertyName !== "transform") return;
e.target.classList.remove("playing");
}

function playSound(e) {
const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
const key = document.querySelector(`div[data-key="${e.keyCode}"]`);
if (!audio) return;

key.classList.add("playing");
audio.currentTime = 0;
audio.play();
}

const keys = Array.from(document.querySelectorAll(".key"));
keys.forEach((key) =>
key.addEventListener("transitionend", removeTransition)
);
window.addEventListener("keydown", playSound);
</script>
</body>
</html>

Day 1이라서 무심코 봤다가 큰 코 다쳤다. 우선 audio 태그를 다뤄본 적이 거의 없어 js에서 플레이시키는 방법도 몰랐다.

또한 getElementsbyClassName, getElementById에 익숙해져서 querySelector에서 data-key 속성으로 DOM 객체를 다루는 것도 쉽지 않았다.

이번에 완전히 새로 배운 것은 classList이다. DOM 객체에 class를 부여하고(add), 삭제(remove)할 수도 있다. 예를 들어 keyplaying이라는 class를 부여하면, css에 작성된 .playing 효과가 나타나고, 원할 때 remove로 삭제할 수 있다.

그리고 transitionend라는 event가 있는 것도 처음 알았다. 변형이 끝났을 때의 이벤트를 어떻게 처리할까 하다가 저런 사소한 이벤트의 제어도 순수하게 가능한게 신기했다.

그렇게 Day 1이 끝났다.