본문 바로가기
IT_알토르/기술 및 코드과제

6. JavaScript 기초 (2)

by jys275 2025. 3. 9.

비동기에 대해 배울 것 : 개발 공부 처음 할 때 듣는 언어 절차지향이라는 것이 있을 것 : 한줄한줄 차례대로 해석 : 근데, 게임을 예시로 들면 내가 움직일 때 다른 사람이 못 움직이지 않음 : 이러한 예시를 들었을 때, 소스가 2개 이상 실행될 때를 비동기라고 함 : 이렇게 비동기로 개발을 해야 하는 경우가 생김 : 타자 게임을 제작할 예정인데, 단어 일치 여부를 확인하는 match 소스와 counting 소스 두 가지가 진행될 예정임

 

h1은 텍스트를 크게 보여줌 : 아래는 초안

 
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Typing Game</title>
<link rel="stylesheet" href="typing.css">
</head>
<body>
<div class="game-title">
<h1>Typing Game</h1>
</div>
<div class="word-display">
단어
</div>
<input type="text" class="word-input">
<div class="game-info">
<p>점수 : <span class="score">0</span></p>
<p>남은시간 : <span class="time">0</span></p>
</div>
</body>
</html>
<script src="typing.js"></script>
 

js도 불러오는 것이 가능

 
</html>
<script src="typing.js"></script>
 

근데 이걸 html 어디에서 불러오는지에 따라 매우 큰 차이점이 존재한다 : html 소스 직전에 넣거나 html 소스 마지막에 넣거나 : html 내용이 표시되기도 전에 js가 실행되어 오류가 발생하는 등 : 위는 보통 html 소스가 실행되고 js가 실행되는 게 일반적이라 저렇게 적음 : 하지만 이것도 단점이란 게 존재 : js 소스가 많으면 실행되는데 즉, 페이지가 로딩되는데 매우 오래 걸림 : 장점은 버그가 발생할 일이 없다는 것

 

자바스크립트 기본 문법 이해하기 - Array

Array, 배열이란 여러 개의 값을 하나의 변수에 저장할 수 있는 자료구조이며, 번호(index)로 각 요소에 접근할 수 있으며, 0부터 시작하는 인덱스를 가진다.

 

이제부터 파일 생성 후 js 개발자가 되었다고 가정하고 구현해 보자 : apple banana orange mango 단어와 10초 간격, 점수 1점씩 +로 할 것 : 단어 보이게 하는 기능부터 : 변수에 배열도 넣을 수 있음 : 배열을 사용해 보자 : 접근하는 방법은 인덱스를 사용해서 접근하면 될 것

 

console.dir(wordDisplay)을 통해서 오브젝트 형태를 볼 수 있는데, 여기서 '단어'라는 텍스트가 어디 property안에 적혀있을지 확인 : innerText에 있음 : wordList 인덱스 0에 접근하면 아래와 같은 화면 출력

입력값이 일치하는지, 엔터키를 감지하는지 알고 싶음 : addEventListener, onKeyDown 등 사용

 

근데, 구글링을 해보면 '$'를 사용하는 JS 내용도 있을 것 : JS 중에 Jquery라고 하는 툴, 문법이 존재함 : 이걸 따로 다운받아 사용하면 '$'를 사용할 수 있음 : 근데, 이건 사용하지 않기로 : Jquery가 나온 목적은 비교적 옛날에 모든 웹브라우저에서 호환되게 도와주는 역할이었음 : 근데, 추후에 여러 웹브라우저 회사들이 HTML, CSS, JS를 해석하는 기준을 모두 똑같이 하자고 협의함 : '웹표준' : developer.mozilla.org : 그럼 이제 Jquery 사용할 이유가 없어짐

 

일치여부, 점수, 시간 구현

 
const wordDisplay = document.querySelector(".word-display");
const wordInput = document.querySelector(".word-input");
const score = document.querySelector(".score");
const time = document.querySelector(".time");

let wordList = ['apple', 'banana', 'orange', 'mango'];
let count = 0;
let time_left = 10;

wordDisplay.innerText = wordList[count];
time.innerText = 10;

wordInput.addEventListener("keydown", function(){
if (event.code === "Enter"){
// 사용자의 입력값 <-> 보여지고 있는 값
// 사용자의 입력값 : wordInput.value
// 보여지고 있는 값 : wordDisplay.innerText
if (wordInput.value === wordDisplay.innerText){
count++;
wordDisplay.innerText = wordList[count]
wordInput.value = "";
score.innerText = count;
}
}
})

// setInterval(실행될 함수, 몇초)
let timeInterval = setInterval(function(){
// 카운팅다운
time_left--;
time.innerText = time_left;

if(time_left === 0){
clearInterval(timeInterval)
}
}, 1000)
 

 

근데, 중요한 포인트는 apple ~ orange 등 하나씩 맞추고 통과해도 남은 시간이 초기화되지 않고 계속 줄어듦 : 비동기로 진행 중인 것 : JS function 두 가지가 동시에 실행되고 있는 것 : JS에서 제공하는 몇몇 함수 같은 경우 비동기 가지고 실행됨 : setInterval은 비동기 방식이구나

 

이걸 초기화 해보자 : 초기화 시점을 찾아보자 : 일치하는지 확인하는 부분인 addEventListener 내부

 
if (wordInput.value === wordDisplay.innerText){
count++;
wordDisplay.innerText = wordList[count]
wordInput.value = "";
score.innerText = count;
time.innerText = 10;
}
 

time.innerText = 10; 하면 되지 않을까? : 안됨 : 단순히 보이는 시간을 바꾸는 것뿐 : 즉, time_left도 10으로  초기화해야 할 것 : 근데 '10'이라는 숫자가 너무 반복되기 때문에 아래 변수 추가

 
const DEFAULT_TIME = 10;
 

 

근데 마지막 문자인 mango 이후에 undefined가 표시되는 것이 맘에 들지 않음 : 입력을 막도록 구현하자 : 즉, mango가 끝이라는 것을 어떻게 표현해야 할까?

 
// count의 값이 wordList 배열의 사이즈와 일치하는지 체크
if (count === wordList.length){
// input 태그의 값을 입력을 못하게 disable 처리
wordInput.disable = true;
// 카운팅 다운 정지
clearInterval(timeInterval)
// 뒤에 있는 소스를 더 이상 진행하지 않게
return false;
}

 

더보기
// 클래스가 word-display인 태그를 잡아서 박스에 넣음
const wordDisplay = document.querySelector(".word-display");
// 클래스가 word-input인 태그를 잡아서 박스에 넣음
const wordInput = document.querySelector(".word-input");
// 클래스가 score인 태그를 잡아서 박스에 넣음
const score = document.querySelector(".score");
// 클래스가 time인 태그를 잡아서 박스에 넣음
const time = document.querySelector(".time");
// 기본 시간을 DEFAULT_TIME 변수에서 관리하기 위해
const DEFAULT_TIME = 10;

 

// wordList 박스에 배열 형태 가지고 문자열 값을 저장
let wordList = ['apple', 'banana', 'orange', 'mango'];
// count 변수는 #1. wordList에 있는 값에 접근하기 위해서
// #2. score 보여지는 부분에 사용
let count = 0;
// 카운트 다운 되는 숫자를 저장하기 위한 박스
let time_left = DEFAULT_TIME;

 

// 기본값을 선언, 단어가 보여지는 부분에 wordList 배열의 첫번째 값을 넣어줌
wordDisplay.innerText = wordList[count];
// 기본값을 선언, 시간 초가 DEFAULT_TIME 변수에 들어가 있는 값으로 보여지게
time.innerText = DEFAULT_TIME;

 

// input 태그에 keydown이라고 하는 이벤트가 발생하는지 감시자 추가
// keydown 이벤트가 발생하면 function 안에 작성된 소스가 실행
wordInput.addEventListener("keydown", function(){
// event라고 하는 오브젝트 안에 code의 값이 Enter인지 체크
if (event.code === "Enter"){
// 사용자의 입력값 <-> 보여지고 있는 값 일치하는지 체크
// 사용자의 입력값 : wordInput.value
// 보여지고 있는 값 : wordDisplay.innerText
if (wordInput.value === wordDisplay.innerText){
// count의 값을 1 증가 시킴
count++;

 

// count의 값이 wordList 배열의 사이즈와 일치하는지 체크
if (count === wordList.length){
// input 태그의 값을 입력을 못하게 disable 처리
wordInput.disable = true;
// 카운팅 다운 정지
clearInterval(timeInterval)
// 뒤에 있는 소스를 더 이상 진행하지 않게
return false;
}

 

// 다음 단어가 디스플레이 되도록
wordDisplay.innerText = wordList[count]
// 사용자가 input 태그에 작성항ㄴ 값을 빈값으로 덮어씌움
wordInput.value = "";
// score 안에 text 값을 count 값으로 덮어씌움
score.innerText = count;
// 시간을 디폴트 시간이 보이게끔 처리
time.innerText = DEFAULT_TIME;
// 남은 시간을 초기화
time_left = DEFAULT_TIME;
}
}
})

 

// setInterval(실행될 함수, 몇초)은 비동기가지고 실행
// 1초에 한번씩 함수가 실행
let timeInterval = setInterval(function(){
// 카운팅다운, 남은 시간을 1초씩 감소
time_left--;
// 시간 보여지는 부분에 time_left에 있는 값 덮어씌우기
time.innerText = time_left;

 

// 남은시간이 0이 되는 경우
if(time_left === 0){
// setInterval을 종료
clearInterval(timeInterval)
}
}, 1000)

API에 대해 알아보자 : 맥주와 소주가 적힌 호출벨이 있다고 하자 : 클라이언트와 서버가 존재할 때, 서버가 이 호출벨 형식이 있을 때 원하는 것을 누르면 클라이언트인 너한테 해당 서비스를 제공할게 : 하는 게 API임 : 서버가 어떤 특정한 이벤트, 서비스를 버튼화 해놓고 클라이언트에게 제공해 주고 클라이언트가 원하는 것을 누르면 제공해 주는 것이 API : 비트코인 매수, 매도 등

 

이걸 컴퓨터에서 자세히 이해해 보면 : Bithumb API를 예시로

웹 API의 버튼은 어떻게 구현되어 있나? : 서버와 클라이언트가 HTML, 여러 데이터를 주고받는 것이 HTTP라고 했었음 : 이 HTTP 기능을 이용해서 API를 구현한 것 : 위의 order_currency, payment_currency가 소주 맥주 예시를 바탕으로 보면, 어떤 회사의 소주 맥주인지 자세히 선택할 수 있는 것과 유사 : 아래 Example Response는 오브젝트와 같은 형태이지만 HTML태그는 아님 : 그럼 뭘까? : 'JSDN'이라고 하는 데이터를 구조화시켜 놓은 데이터 형태임 : 오브젝트는 아님 : 요즘 웹 API 반응은 대부분이 JSDN 형태임 : 반대로 HTML 같이 태그로 감싸져 있는 형태를 가지고 있으면 XML일 것

 

클라이언트가 서버한테 요청을 보내는 시점은 보통 페이지가 이동되는 시점이었음 : 근데, 페이지가 이동되지 않으면서 요청을 보내는 방법이 있음 : 페이지 이동 없이 백 단에서 뒤에서 보내는 것 : AJAX 통신 : 예전 네이버 실시간 검색과 같은 느낌 : 위에서 구현한 게임에서 setInterval 같이 1초에 한 번씩 요청을 보내는 등 

 

이 AJAX 통신을 직접 해볼 것

 
<script>
.then(function(res){
return res.json();
})
.then(function(result){
console.log(result);
})
</script>
 

위는 api 요청을 result 가지고 가져온 것

 

하나 더 이론적 얘기 : JS는 setInterval처럼 애초에 비동기인 경우가 있음 : 이러한 경우 때문에, 동기로 작동시키고 싶은데 비동기로 작동되어 문제가 발생하는 경우가 상당히 많음 : 예시로 아래와 같은 경우

 
<script>
.then(function(res){
console.log("A");
return res.json();
})
.then(function(result){
console.log(result);
})
</script>

console.log("B");
 

콘솔에서 A가 먼저 뜰까 B가 먼저 뜰까? : B가 먼저 나타나는 경우가 대부분일 것 : fatch 또한 비동기로 작동되어 동시에 실행되게 되는데, 시간상 API를 가져오고 console.log("A");를 실행하기 전에 console.log("B");가 실행되는 경우가 많을 것이기 때문에

 

그럼 비동기로 실행되는 함수를 동기로 실행하고 싶음 : 두 가지 방법이 존재 : 첫 번째는 promise, 두 번째는 async await : 후자는 추후에 배울 것이니 전자부터 자세히

 

promise? : 위의 코드에서 '. then'이 promise 문법임 : "~ 이거 끝난 다음에 진행하고 싶어" : 즉, 위의 코드를 자세히 이해해 보면 아래와 같음

 
<script>
// API 요청
// 응답값이 함수의 첫번째 argument 매개변수에 값이 들어온다
.then(function(res){
return res.json(); // json : res라는 이름을 가진 응답값을 오브젝트 형태로 바꾸는
}) // 이 return이 다음 value로 리턴이됨 : 다음 function이 받을 수 있음 : 괄호안에 아무렇게 적어도 되는데, 이 받는 곳 변수를 result라고 지은 것 뿐
.then(function(result){
console.log(result);
})
</script>
 

 

 

그럼 이제 단어 맞추기 게임에 random-word API를 사용해서 할 수 있을까?

 
.then(function(response){
return response.json();
})
.then(function(result){
console.log(result);
})


const wordDisplay = document.querySelector(".word-display");
const wordInput = document.querySelector(".word-input");
const score = document.querySelector(".score");
const time = document.querySelector(".time");
const DEFAULT_TIME = 10;

let wordList = result;
let count = 0;
let time_left = DEFAULT_TIME;
 

result가 정의되어있지 않다고 표시됨 : fetch 소스가 끝나지도 않았으니 result가 정의되어있지 않을 것 : 그럼 어떻게 할까? : 무식하게 .then(function(result){ }) 사이에 js 소스코드 전체를 넣으면 해결

 

기능은 잘 되는데 word-display 클래스 안의 '단어'라는 텍스트가 나타났다가 랜덤 단어가 나타남 : API 통신 속도에 의한 문제임 : 이걸 해결하기 위해 보통 로딩바를 사용함 : 즉, 우리가 보는 보통 로딩화면은 이런 API 통신을 기다리는 등의 문제가 있었던 것 : '단어'라는 텍스트를 그냥 'Loading...'이라고 적는 방법도 있을 것

 

게임 시작 버튼을 만들어보자 : onclick 속성값은 무엇? : input 태그가 클릭되면 실행되게 할 함수 : 이름 지은 해당 함수는 js에서 사용

 
<input type="button" value="Game Start" class="start" onclick="gameStart()">
 

이제 js에서 function gameStart(){ } 내에 소스코드 넣으면 될 것

 

자바스크립트 DOM 조작 이해하기

문서 객체 모델(Document Object Model)에서 Document는 HTML 문서를 의미 : 이 문서는 웹페이지에 접속할 때 쓰는 브라우저에 보내는 주문서임 : 그리고 HTML은 여러 요소와 구조가 설계도처럼 표현되어 있음 : 브라우저는 안의 HTML 요소를 실제 제품 즉, input 태그라고 하면 <input type="" ~~> 라고 적혀있는 것이 실제로 빈칸으로 입력받게 할 수 있게 제작하는 것 : 즉, HTML이란 주문서를 가지고 브라우저란 공장들이 그 설계를 실체로 만들어낸 게 DOM

개발자 도구에서 위에 보이는 부분이 DOM이고, 아래 Console로 DOM에 접근 및 조작이 가능

 

HTML에 작성된 구조에 따라서 제품들이 배치되고, 추가 명령을 보내서 속성이나 디자인, 배치 등을 조작할 수 있도록 된 상태를 DOM이라고 할 수 있음 : 이 DOM을 사용해서 원하는대로 웹 화면을 보여주고, 필요에 따라 JS로 DOM을 조작할 수도 있음 : 즉, JS로 제어할 수 있는 대상 : 이건 DOM이 API를 가지고 있기 때문 : input 태그에는 value라는 버튼이 있는 것과 같이

 

아무튼 DOM 안에는 각종 node들이 트리 구조로 들어있음

node란 모든 HTML 요소라고 이해하면 됨 : 그럼 node의 기능이란? : HTML 요소에서 공통적으로 볼 수 있는 기능들은 다수가 node의 속성 또는 기능이라고 보면됨 : 또한 이 node는 클릭 등의 이벤트가 가해지는 EventTarget이기 때문에 요소들은 모두 addEventListener 등의 기능 또한 갖고 있음 : 해당 '기능'들이라는 것이 모든 DOM 요소에 버튼으로 달려가지고 JS로든 뭐든 조작이 가능해지는 것, img는 src 같은 속성, API, 버튼들이 추가로 달려있는 것 : 그래서 결국 이런 API들로 구성되어 있기 때문에 'HTML이나 XML문서를 실체로 나타내는 API'라고 표현하기도 함 : 즉, HTML 요소들을 선택해서 딱 필요한 데만 바꾸는, 페이지를 다 다시 불러오는 게 아닌 이런 일련의 행위들이 모두 DOM을 조작하는 것이었음

 

ECMA 문법이 무엇인지?

ECMA 문법은 ECMAScript(ECMA-262) 라는 표준에서 정의된 JavaScript의 문법과 기능을 의미함 : JavaScript는 ECMAScript 표준을 따르는 프로그래밍 언어이며, 이 표준이 발전하면서 새로운 기능들이 추가됨 : ECMAScript는 ECMA International(국제 표준 기구) 에서 정의한 스크립트 언어 표준 : 즉, JavaScript의 기본 문법과 동작을 정한 공식 규격 : JavaScript, JScript, ActionScript 등 여러 언어가 ECMAScript 표준을 따름 : 모든 브라우저(JavaScript 엔진)는 ECMAScript 표준을 구현하여 동작

그 중 ECMA6(ECMAScript6, ES6)는 2015년에 발표된 ECMAScript 표준의 6번째 버전으로, JavaScript의 큰 개선을 가져온 중요한 업데이트라고 할 수 있음

 

ECMA6 문법에 어떤 것들이 있는지 훑어보기

1. let과 const (새로운 변수 선언 방식)
ECMA5까지는 var만 사용했지만, ES6에서는 let과 const가 추가되었다.

 
let name = "철수";
name = "영희"; // 재할당 가능
 
const age = 25;
age = 30; // 오류 발생 (const는 변경 및 재할당 불가능)
 

 

2. 화살표 함수 (=>)

 
// 기존 함수 선언 방식
function add(a, b) {
return a + b;
}

// 화살표 함수로 변환
const add = (a, b) => a + b;
 
console.log(add(2, 3)); // 5
 

 

3. 클래스 (class)

객체 지향 프로그래밍을 쉽게 할 수 있도록 클래스 문법이 추가됨.

 
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}

sayHi() {
console.log(`안녕하세요! 저는 ${this.name}입니다.`);
}
}

let user = new Person("철수", 25);
user.sayHi(); // 안녕하세요! 저는 철수입니다.
 

 

4. 모듈 (import / export)

파일을 나누어 관리할 수 있음.

 
// math.js (내보내기)
export const add = (a, b) => a + b;

// main.js (가져오기)
import { add } from './math.js';
console.log(add(3, 4)); // 7

 

5. Promise (비동기 프로그래밍)

비동기 작업을 더 쉽게 처리할 수 있도록 Promise가 추가됨.


.then(function(res) {
console.log("A"); // 첫 번째 then 실행
return res.json(); // 비동기적으로 JSON 데이터로 변환
})
.then(function(result) {
console.log(result); // 두 번째 then 실행 (res.json()의 결과 출력)
})

'IT_알토르 > 기술 및 코드과제' 카테고리의 다른 글

8. Next.js  (0) 2025.03.29
7. React 기초  (0) 2025.03.20
5. HTML/CSS 소스코드 만들어보기  (0) 2025.03.04
4. JavaScript 기초 (1)  (0) 2025.02.27
3. CSS 기초  (0) 2025.02.24