브라우저 기반 애플리케이션을 만들 때, 사용자가 만든 것과 상호 작용하기 위한 그래픽 유저 인터페이스 (GUI)를 제공합니다. 브라우저와 상호 작용하는 가장 일반적인 방법은 다양한 요소를 클릭하고 입력하는 것입니다. 개발자로서 마주한 도전은 이러한 작업을 언제 수행할 지 모른다는 점입니다!
[Event-driven programming](https://en.wikipedia.org/wiki/Event-driven_programming)은 GUI를 만들기 위해 수행할 프로그래밍 타입의 이름입니다. 이 구문을 조금 자세히 보면, 여기서 핵심 단어가 **event**라는 점을 볼 수 있습니다. Merriam-Webster에 따르면, 이벤트는 "something which happens"로 정의됩니다. 이 상황을 완벽하게 설명합니다. 응답이라는 건 어떤 코드가 수행될 지 알고 있지만, 언제 발생할 지 모릅니다.
실행하려는 코드 섹션을 출력할 방법은 함수를 만드는 것입니다. [procedural programming](https://en.wikipedia.org/wiki/Procedural_programming)으로 생각해보면, 함수는 순차적으로 호출됩니다. 이벤트 기반 프로그래밍에서도 마찬가지입니다. 다른 점이라고 하면 함수가 호출되는 **방식**입니다.
이벤트(버튼 클릭, 타이핑 등)를 제어하기 위해서, **event listeners**를 등록합니다. 이벤트 리스너는 이벤트 발생을 수신하고 응답하는 함수입니다. 이벤트 리스너는 UI를 갱신하고, 서버를 호출하거나, 또는 작업에 응답하는 모든 작업을 수행할 수 있습니다. [addEventListener](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener)를 사용하여 이벤트 리스너를 추가하고, 실행할 함수를 제공합니다.
> **NOTE:** 이벤트 리스너를 만드는 방법에는 여러 가지가 존재한다는 점을 강조하기에 충분합니다. 익명 함수를 사용하거나, 이름을 지어 만들 수 있습니다. `click` 속성을 설정하거나, `addEventListener`를 사용하는 등 다양한 단축으로 쓸 수 있습니다. 이 강의에서는 웹 개발자가 사용하는 가장 일반적인 기술인 `addEventLister`와 익명 함수에 초점을 맞출 것입니다. `addEventListener`가 모든 이벤트에서 작동하고, 이벤트 이름을 파라미터로 줄 수 있기 때문에 가장 유연합니다.
응용 프로그램을 만들 때 수신할 수 있는 [dozens of events](https://developer.mozilla.org/docs/Web/Events)가 있습니다. 기본적으로 사용자가 페이지에서 수행하는 모든 작업은 이벤트를 발생시키므로, 원하는 경험으로 많은 도움을 줍니다. 다행스럽게, 일반적인 이벤트만 필요합니다. 다음은 일반적 몇가지입니다 (게임을 만들 때 사용할 두 가지를 포함합니다):
어떻게 될 지 자주 보면서 개발하는 것이 가장 좋습니다. 애플리케이션을 시작합니다. 로컬로 애플리케이션을 호스팅하고 저장할 때마다 브라우저를 새로 고칠 [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer)라는 멋진 Visual Studio Code 확장이 있습니다.
'When you have eliminated the impossible, whatever remains, however improbable, must be the truth.',
'There is nothing more deceptive than an obvious fact.',
'I ought to know by this time that when a fact appears to be opposed to a long train of deductions it invariably proves to be capable of bearing some other interpretation.',
'I never make exceptions. An exception disproves the rule.',
'What one man can invent another can discover.',
'Nothing clears up a case so much as stating it to another person.',
'Education never ends, Watson. It is a series of lessons, with the greatest for the last.',
];
// store the list of words and the index of the word the player is currently typing
> **NOTE:** `document.getElementById`로 원할 때마다 코드에서 요소를 찾을 수 있습니다. 이러한 요소를 계속 참조할 예정이기 때문에 문자열 리터럴로 상수를 만들어 오타를 내지 않을 것입니다. [Vue.js](https://vuejs.org/) 혹은 [React](https://reactjs.org/)와 같은 프레임워크를 사용하면 코드를 centralizing으로 관리할 수 있습니다.
게임을 시작하려면, 플레이어가 시작을 누릅니다. 물론, 언제 시작을 누를지 알 수 없습니다. 여기에서 [이벤트 리스너](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener)가 작동됩니다. 이벤트 리스너를 사용하면 (이벤트) 발생을 수신하고 응답해서 코드를 실행할 수 있습니다. 해당 케이스의 경우에는, 사용자가 시작을 누를 때 코드를 실행하려 합니다.
- [Math.floor](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/floor)과 [Math.random](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/random)을 사용하면 `quotes` 배열에서 인용문을 무작위로 선택할 수 있습니다
- 플레이어가 현재 입력하고 있는 단어를 추적할 수 있도록 `quote`를 `words` 배열로 변환합니다
- 플레이어는 첫번째 단어부터 시작하므로, `wordIndex`는 0으로 설정합니다
- UI를 설정합니다
-`span` 요소 안에 각 단어를 포함하고 있는, `spanWords` 배열을 만듭니다
- 화면에서 단어를 강조하여 출력할 수 있습니다
- 배열을 `join`하여 `quoteElement`의 `innerHTML`로 갱신할 때 사용할 문자열을 만듭니다
- 플레이어에게 인용문을 출력합니다
- 첫 번째 `span` 요소의 `className`을 `highlight`로 설정하여 노란색을 강조합니다