
0. 들어가기에 앞서
오늘부터는 프런트엔드의 꽃인 JavaScript 정리를 할 예정이다. 사실 강의는 이벤트 리스너에서 종료된 상태이지만, 충분히 일주일의 내용을 돌아볼 수 있다. 그리고 지난 주 HTMl/CSS 편과 다르게 직접 과제로 제출한 코드도 리뷰해볼 예정이다.
1. JavaScript란
동적인 웹 페이지를 작성하기 위해 사용되는 언어라고 정의되어 있다. 여기서 동적Dynamic이라는 단어는 무엇일까? 반대로는 정적Static이 있다. 실행 중 내용이 변경될 수 있는 것을 동적이라고 표기한다. 종이와 태블릿의 차이 정도라고 비유하는데, 종이는 잉크로 한번 쓰면 고치기 어렵지만 태블릿은 전자잉크로 언제든지 다시 고칠 수 있기 때문이다.

웹 표준 프로그래밍 언어이며, 모든 웹 브라우저에서 기본적으로 JavaScript를 지원하기 때문에 사용이 쉽다. HTML와 CSS만이 있으면 기본적으로 웹페이지는 인코딩 되며 정해지기 때문에, 정적이라고 할 수 있지만 이 JS 덕분에 동적인 웹사이트가 만들어질 수 있는 것이다.
여기서 자바스크립트를 인터프리팅 언어라고 하는데, 이에 관해서는 나중에 또 특별편으로 찾아보겠다. JS라는 언어가 얼마나 유연하고 이상한 언어인지는 거기서 다루고자 한다.
이전에 HTML/CSS/JavaScript에 대해서 이야기하며 JS를 일종의 도면, 설계도, 청사진 같은 것이라고 이야기했는데 말 그대로다. 많은 홈페이지가 "목적"을 다루기 위해서는 JS의 도움이 필요하다. 특히 Ajax(Asynchronous JavaScript and XML)의 등장으로 서버와의 통신이 가능해지면서 그 영향력은 줄어들지 않고 있다.
지금부터는 JavaScript의 핵심 개념들- 제어문, 변수, 배열, 함수, 객체에 대해서 설명하겠다.
간단한 입출력 함수
그 전에, 데이터를 입력 및 출력하는 것을 지원하는 입출력 메서드를 간단히 톺아보고 간다. 이들은 정말 기초적인 것으로, 데이터를 브라우저(클라이언트)에서 받거나 미리 입력한 내용을 출력하기 위해서 있다. 특히 console.log는 개발자라면 많이 사용하게 된다.

연습문제로는 confirm과 prompt, document.write를 사용하는(그리고 이어서 나오는 if 제어문과 함께) 문제를 받았다.
var isCard = confirm('카드로 결제합니까?');
if(isCard) {
var cardNum = prompt('카드번호를 입력하세요.','xxxx-xxxx-xxxx-xxxx');
if(cardNum) { var msg = '카드번호 : ' + cardNum; }
}
else {
var msg = '카드로 결제하지 않습니다';
}
document.write(msg);
보다시피 confirm은 true or false를 다루는 데이터 입력 메서드다. 확인을 누르면 true를, 취소를 누르면 false를 반환한다.

그리고 카드로 결제한다고 누를 경우 prompt로 입력을 요구한다. 아주 예전에(2000년대) 홈페이지에는 당신의 생일을 입력하세요하고 결과로 이상한 걸 출력해주는 장난감 사이트가 많았다.

이렇게 하여 카드번호를 입력하면 출력되는 형태의 연습문제였다. 그러고보면 요즘은 alert 같은 것도 Toast Message 같은 것으로 예쁘고 편하게 만드는 경우가 많아졌다.
2. Variable- 변수
변수란, 메모리 내에 저장되어 불러와지는 임시 기억 장소이다. 식별자 등으로 명명하여 사용하는, JS 기본적인 개념 중 하나다. 이전에 일지에서 관련 내용을 정말 깔끔하게 정리해놔서, 스코프 등의 개념에 대한 설명을 제외해 키워드들에 대해서 다시 읊고, 그림으로 다시 정리하겠다.
var
var A; 와 같이 사용한다. 기본 변수의 디폴트인, Variable의 준말인 var이다. 현재는 사용되지 않는데, 스코프 문제에 의해서 사용되고 있지 않다. var의 스코프-영향을 끼치는 범위-는 함수 스코프로, function(){} 안에서는 계속 그 변수가 존재하고 있다는 뜻이 된다.
재할당(변수의 값을 다시 할당하는 것), 재선언(같은 변수명으로 다시 선언하는 것), 전역객체 속성 등의 장점이 많지만 현재로서는 그것이 단점들에 가깝기 때문에 사용되지 않고, let과 const로 나뉘어졌다.
let
let A; 와 같이 사용한다. var 이후 새로 탄생한 변수 중 하나로, var의 역할을 const와 함께 둘로 나눴다고 봐도 된다. 재선언은 불가능하나 재할당은 가능한, 변할 수 있는 값에 사용한다. 스코프가 블록 스코프이기 때문에, {} 안에서만 영향을 끼친다. 따라서 변수 오염의 위험이 var보다 없다.

const
const A; 와 같이 사용한다. var 이후 새로 탄생한 변수 중 하나로, var의 역할을 let과 함께 둘로 나눴다고 봐도 된다. 재선언도 재할당도 불가능한, 그야말로 상수 값에 사용한다. 오염되지 않고자 하는 값에 주로 사용하며, 스코프가 let과 마찬가지로 블록이기 때문에 {} 안에서만 영향을 끼친다. let과 달리 자체 성질로 변수 오염은 없으나, 라이브러리끼리 부딪히거나 혹은 코드끼리 부딪히는 등의 문제가 없다.

지역변수? 전역변수?
변수는 전역변수와 지역변수로 나눌 수 있다. 전역 변수는 script 전체에 영향을 끼치는 변수이며, 지역 변수는 일부분에만 영향을 끼치는 변수이다. 지역변수는 함수 스코프와 블록 스코프로 좁혀진다. 현재는 블록 스코프 정도가 선호되고 있는데, 블록을 나가면 해당 변수는 영향을 끼치지 못하기 때문이다.

3. Control Statements- 제어문
제어문이란, 프로그램의 흐름을 제어하는 문장을 의미한다. 코드의 실행 순서를 바꾸거나, 조건에 따라 분기하거나하는 것이다. 조건문이라고도 한다. 제어문은 다음과 같이 나눌 수 있다.

if(조건) { }
만약~라면의 그 if에서 따온 if문이다. 조건의 결과를 만족하면 참true을 반환하고, 그렇지 않다면 false를 반환한다. if에는 if else와 else문도 같이 붙는데, else문의 경우 앞선 if문의 결과가 거짓(false)일 때 수행되는 것은 else라고 한다. if(식) { 내용 } 다음에 else { }를 붙여서 전개한다. 여기엔 조건식을 붙이지 않으며, if문이 없으면 실행되지 못한다. 만약 if문의 결과가 거짓이되 새로운 조건식을 붙이고 싶으면 if(식) { 내용 }과 else { } 사이에 else if를 넣을 수 있다.
다음 코드와 함께 살펴보자. 연습문제다.
var id = prompt("아이디 입력");
var pwd = prompt("비밀번호 입력");
var msg = '';
if(id == 'abcd' && pwd == '1234') { //pwd가 반드시 숫자가 아닐 수도 있어 정정합니다.
msg = '로그인 성공';
}
else {
alert('아이디 또는 비밀번호가 일치하지 않습니다.');
msg = '로그인 실패';
}
document.write(msg);
prompt로 입력받은 변수 id와 pwd값에 대한 if문이다. 여기서 id는 아이디, pwd는 비밀번호를 의미한다. 여기서 조건은 id는 abcd일 것, pwd는 1234일 것이다. 이 두 가지가 모두 충족해야 로그인에 성공하는 것이 된다. 여기서 &&문은 AND 연산자다. 즉, 두 가지 조건을 모두 달성해야 로그인이 성공하는 메시지가 나온다.
본래의 코드에서는 ParseInt라는 형변환을 pwd의 값에 사용했다. ParseInt는 문자열을 정수로 변환하는 것인데, 빠진 이유에 대해서 설명하는 것이 도움이 될 듯하여 적는다.
ParseInt를 할 경우 '숫자'를 반영한다. 즉, 숫자값이 아닐 경우에는 값에서 제외되는 것이다. 그렇다면 pwd에 1234가나다라라고 적어도, 나1234라고 적어도 pwd의 조건에는 맞는 것이 된다. 조건을 따질 때는-if 문의 작성에서는- 까다롭게 따지는 것이 가장 중요하다.

switch
witch문은 여러 조건 중 하나를 선택해서 실행하는 제어문이다. 여러 조건case을 처리할 수 있다는 장점이 있지만, 제약이 많다. 수식과 결과값이 간단하지 않을 경우, if문을 사용하는 것이 낫다. 과제가 없었기에 이전 일지에서 사용한 코드를 가져온다.
const day = '월요일';
switch (day) {
case '월요일':
console.log('월요일입니다');
break;
case '화요일':
console.log('화요일입니다');
break;
case '수요일':
console.log('수요일입니다');
break;
default: //만약 아무것과 일치하지 않으면 default의 결과가 나타난다.
console.log('기타 요일입니다');
break;
}
for()
for문은 반복문이라고 한다. 조건이 true인 이상 for 문 안에 있는 스크립트는 실행된다. 대체로 for문을 사용할 때는 for(let i = 0; 조건식; i++) {} 형태로 사용한다. 메커니즘에 관한 것은 다음처럼 간단하게 표현할 수 있다.

다음은 연습과제로 낸 코드다. 리뷰를 하면서 설명하겠다.
for(i = 1; i<=4; i++) {
for(j = 1; j<=3; j++) {
document.write('<img src="./image/apple.png">');
document.write('<img src="./image/bomb.png">');
}
document.write('<img src="./image/apple.png">');
document.write('<br>');
}
먼저 조건에는 i = 1; i<=4; i++라고 적혀 있다. i = 1은 초기값이다. 1에서 시작을 하겠다는 의미다. i<=4는 조건식을 의미한다. 이 조건이 false가 될 때까지 실행한다는 의미이다. i++는 증감식으로, 실행할 때마다 i의 값을 반복하겠다는 것이다.
기본적으로 i가 Index의 준말이라 자주 사용되지만, 사실 값 자체는 크게 상관이 없다. 안에는 중첩으로 for문을 넣었다.
사실 이 코드는 %2라고 하는 if문의 제어를 사용하면 더 간단해진다.(j가 짝수인지 확인하는 것이다)
for (i = 1; i<=4; i++) {
for (j = 1; j <=8; j++) {
if (j % 2 == 0) {
document.write("<img src='image/apple.png'></img>");
} else {
document.write("<img src='image/bomb.png'></img>");
}
}
document.write("<br>");
}
while(조건){}
while 또한 for문처럼 반복문으로 사용한다. for과의 차이는 while은 좀 더 조건을 중심으로 하는 구성이란 것이다. 그리고 반복 횟수가 불명확할 경우에는 for문대신 사용된다.
다음은 연습과제로 낸 코드다. 리뷰를 하면서 설명하겠다.
let i = 0;
let sum = 0;
document.write('<table><thead><th>i</th><th>sum</th></thead>');
document.write('<tbody>');
while(i<10) {
i++;
sum += i;
document.write('<tr><td>' + i + '</td><td>' + sum + '</td></tr>');
}
document.write('</tbody></table>');
먼저 while에서 (i<10)이 바로 조건문이다. 1가 10이 될 때까지 while 내의 내용을 반복하겠다는 것. 그리고 i++가 있다. 먼저 i를 증가시키고 적용하겠다는 것이다.
이 과제는 피보나치 수열과 같이 진행되는 수의 합산을 다루는 것이다. 즉, i들을 계속해서 더해가서 sum의 값을 내놓는 것. 이것을 for문으로 바꾸면 이런 느낌이 된다.
let sum = 0;
document.write('<table><thead><th>i</th><th>sum</th></thead>');
document.write('<tbody>');
for(let i = 1; i <= 10; i++) {
sum += i;
document.write('<tr><td>' + i + '</td><td>' + sum + '</td></tr>');
}
document.write('</tbody></table>');
이렇게 돌아가는 것에 근본적으로는 별로 크게 차이가 없다. 안정성을 위해서 보통은 for문을 사용한다.
4. Array -배열
배열이란 동일한 이름을 갖는 원소(value)들의 연속적 저장 영역이다. 배열의 원소는 메모리 내에서 순서대로 저장되어, 각 배열의 원소는 인덱스(순서번호 보통 [0]으로 시작한다.)로 구별한다.
다음은 연습과제로 낸 코드다. 리뷰를 하면서 설명하겠다.
let colors = new Array(4); //크기가 4인 배열을 생성.
document.write('<ol type="A">');
for(i = 0; i < colors.length; i++) {
//colors.length를 사용한다. 크기가 4이므로, i가 4가 될 때까지 반복.
colors[i] = prompt('색상 입력');
//colors[i]로 colors의 원소 값을 prompt로 지정한다.
document.write('<li>' + colors[i] + '</li>');
//이후 colors의 원소값을 인덱스별로 출력한다.
}
document.write('</ol>');
여기서 new Array는 배열을 생성하는 것이다. 안에 숫자를 넣어 배열의 원소 개수(length)를 미리 정할 수 있다. 그리고 그 length의 개수만큼을 i의 조건문으로 가져와, 그만큼의 색상을 prompt로 입력하게 만들고, 그 입력값을 그대로 document.write 했다.
5. Function- 함수
함수란 독립적인 모듈이며, 자체 블록을 가진다. 특정 기능을 수행하고 결과를 돌려주는 독립적인 코드 집합이다. 함수의 구성에 대해서는 일지에 적었던 것을 그대로 가져와본다.

이 상황에서 한번 예제 코드를 보자.
let starNum;
function input(){
starNum = prompt("숫자 입력 : ");
show();
}
function show(){
for(let i = 0; i < parseInt(starNum); i++){
document.write("★");
}
}
function input(){} 이라는 함수가 있고, 이것이 전역변수인 starNum을 다시 정의한다. 그리고 show();라는 함수를 불러온다. 그렇다, 함수를 부르려면 함수명(); 을 실행하면 된다. 이것 때문에 함수 참조와 헷갈리는 일이 생겼는데, 이 부분은 setInterval 부분에서 다시 확인한다.
그리고 함수는 값을 return할 수 있다. 값을 return반환한다라는 건, 함수가 계산한 결과를 호출한 곳으로 돌려주는 것을 의미한다. return을 한 뒤에는 함수는 그 즉시 종료된다. 반환된 값은 변수에 저장하거나, 바로 사용할 수 있다.
다음이 바로 return에 대한 예제 코드다. 같이 리뷰하며 확인하자. 세 과목의 점수 평균을 구하는 문제다.
function start(){
var confirm = window.confirm("성적을 입력하시겠습니까?");
if(confirm){alert("평균 : " + input());}
else {alert("종료합니다.");}
}
function input() {
const korScore = Number(prompt("국어 점수 입력 : "));
const engScore = Number(prompt("영어 점수 입력 : "));
const mathScore = Number(prompt("수학 점수 입력 : "));
return (korScore + engScore + mathScore) / 3;
}
보다시피 confirm 후에 alert("평균 : " + input());을 사용하고 있다. 이것이 함수의 비동기성, 호이스팅이라고 할 수 있다. 함수의 존재 의의이기도 한 이것은 당장 실행되지 않기 때문에 나중에 또 함수function를 사용할 수 있도록 해준다. 이것은 매개변수와 함께 쓰이는데, 이 부분은 후술한다.
이에 따라서 input()을 출력하게 되는데, 여기서 input();의 결과 값인 (korScore + engScore + mathScore) / 3;이 반환되어, 평균 값을 출력한다.
본 코드는 위에서 보여준 Array와 함께 사용하면 이렇게 사용하기 편해진다.
function start(){
var confirm = window.confirm("성적을 입력하시겠습니까?");
if(confirm){
alert("평균 : " + input());
} else {
alert("종료합니다.");
}
}
function input() {
const subjects = ['국어', '영어', '수학'];
const scores = [];
for(let i = 0; i < subjects.length; i++) {
const score = Number(prompt(subjects[i] + " 점수 입력 : "));
scores.push(score);
}
let sum = 0;
for(let i = 0; i < scores.length; i++) {
sum += scores[i];
}
return sum / scores.length;
}
이어서 매개 변수에 대해서 후술한다고 했는데, 매개변수란, 함수 호출 시에 전달된 값을 받기 위해 사용되는 변수로 지역 변수이다. 이 매개 변수는 기본적으로 함수 스코프이다. 이 매개변수와 함수의 특성이 합쳐지면, 함수가 재사용하기 좋아진다.

다음은 함수의 매개변수를 사용하기 위한 스크립트다. 리뷰하면서 살펴보자.
function input() {
const rows = prompt('테이블의 행 수 입력 :');
const cols = prompt('테이블의 열 수 입력 :');
makeTable(rows, cols);
}
const makeTable = (rows, cols) => {
const rowNum = parseInt(rows);
const colNum = parseInt(cols);
const rowArray = [];
for (let i = 0; i < rowNum; i++) {
rowArray[i] = i;
}
const colArray = [];
for (let j = 0; j < colNum; j++) {
colArray[j] = j;
}
document.write('<table border="1">');
rowArray.forEach(() => {
document.write('<tr>');
colArray.forEach(() => {
document.write('<td>★</td>');
});
document.write('</tr>');
});
document.write('</table>');
};
왜 이리 복잡하냐면 콜백(그리고 화살표와)과 함께 사용했기 때문이다. 이 스크립트를 조금 더 알아보기 쉽게 바꿔보았다.
function input() {
const rows = prompt('테이블의 행 수 입력 :');
const cols = prompt('테이블의 열 수 입력 :');
makeTable(rows, cols);
}
function makeTable(rows, cols) {
const rowNum = parseInt(rows);
const colNum = parseInt(cols);
const rowArray = [];
for (let i = 0; i < rowNum; i++) {
rowArray[i] = i;
}
const colArray = [];
for (let j = 0; j < colNum; j++) {
colArray[j] = j;
}
document.write('<table border="1">');
for (let i = 0; i < rowArray.length; i++) {
document.write('<tr>');
for (let j = 0; j < colArray.length; j++) {
document.write('<td>★</td>');
}
document.write('</tr>');
}
document.write('</table>');
}
참고로 위 함수는 매우매우 복잡하고 비효율적인 식이다. 굳이 Array에다가 넣고 forEach를 썼다(forEach는 후술한다)… 내 과제 제출이라서 그렇다. 이후에 다듬은 코드로 냈는데, 그 코드를 다시 다듬어서 보여주겠다.
function input() {
const rows = prompt('테이블의 행 수 입력 :');
const cols = prompt('테이블의 열 수 입력 :');
makeTable(rows, cols);
}
function makeTable(rows, cols) {
const rowNum = parseInt(rows);
const colNum = parseInt(cols);
for (let i = 0; i < rowNum; i++) {
document.write('<tr>');
for (let j = 0; j < colNum; j++) {
document.write('<td>★</td>');
}
document.write('</tr>');
}
document.write('</table>');
}
prompt로 받은 rows와 cols값이 makeTable에 매개변수로 저장되어 전달된다. 즉, 이렇게 하면 함수끼리 동기화-통신-이 가능해진다는 장점이 있다. input()이라는 function(함수)에서 보낸 변수를 makeTable에서 매개변수로 만들고, 그에 따라 행과 열을 for문으로 생성하고 있다.
이후로는 콜백을 이야기하고 있는데, 콜백에 대해서는 특별편에서 이미 다룬 적이 있으니 그쪽을 참고해주기 바란다.(링크)

대신 여기에서는 콜백 메서드 중 하나인 setTimeout과 setInterval에 대해서 다뤄본다.
setTimeout은 setTimeout(함수,딜레이); 처럼 사용한다. 이것은 일정 시간의 시간이 지날 때 해당 함수를 실행하는 비동기 작업 함수이다. setInterval()은 setInterval (함수,실행간격); 처럼 사용한다. 이것은 일정 시간의 간격을 갖고 주기적으로 해당 함수를 실행하는 비동기 작업 함수다.
그럼 연습문제부터 볼까… 하기 전에, 잠깐.
setTimeout()과 setInterval()과 같은 콜백 메서드를 사용하기 전에 한 가지 짚고 넘어갈 것이 있다.
그건 바로 함수 참조다.
함수 참조
어느 날 강사님이 onload를 하시면서 setTimout()안에 함수 명을 넣으신 적이 있다. 이때 넣었던 코드는
setTimeout('func()',1000);
이었다. 나는 이걸 따라하면서, 다음과 같이 적었다.
setTimeout(func(),1000);
그러나 작동하지 않았다.
script 안에서는 분명히 잘 되었던 거 같은데?
코딩이라는 게 세미콜론 하나로 돌아가고 안 돌아간다지만 대체 무슨 차이지?
그러나 다음과 같이 입력할 때는 또 잘 되었다.
setTimeout(func,1000);
이것과 저것의 차이는 무엇일까? 분명히 함수명(); 은 함수를 호출하는 것이다. 근데 ()가 없는 경우는 무엇일까? 도저히 알 수가 없었다.

그것은 바로 함수명();은 함수 호출이고 함수명만 사용하는 건 함수 참조인 의미이다. 콜백 메서드에서는 특별편에서 말했듯 함수가 인자로 사용되는데, 그렇기 때문에 함수 호출이 아니라 함수 참조가 된다. 이 메서드들이 나중에 그 함수를 호출하기 위해 함수 참조를 받는 것이다. 만약 함수 호출()을 전달하면, 함수가 즉시 실행되고 그 결과(반환값)만 전달되기 때문에, 콜백 메서드가 나중에 호출할 함수가 없어져버린다.
한 마디로 함수 참조는 주소값을 받는 것이라서, 나중에 찾아가겠다는 것인데 함수 호출을 해버리면 갑자기 상대가 이쪽으로 오겠다는 의미가 된다. 배달로 비유하면, 배달 주문한 손님이 배달을 받겠다 해놓고 가게에 갑자기 들어오는 것과 동일하다. 이렇게 때문에 setInterval()과 setTimeout() 입장에서는 갑자기 찾아온 손님 때문에 패닉 상태가되는 것이다. 아직 기다리셔야해요! 지금 당장 드릴 수는 없어요! 그러므로 손님은 배달이 오기까지 얌전히 기다려야 한다.
이어서 setInterval()과 setTimeout()에 대한 예제 코드와 함께 리뷰를 해보겠다.
과제로 제출한 코드가 놀랍게도 한 차례 틀려 좋은 예제가 되어버렸기 때문에, 그대로 첨부한다.
과제는 이미지를 apple과 bomb로 차례대로 10개까지 출력하는 것이었다. 여기에 조건이 하나 더 걸린다 1초마다.
내가 처음에 10개에 집중해서 내놓은 과제는 다음과 같다.
function start(){
alert('이미지 10개 출력');
for(let i = 0; i < 10; i++) {
setTimeout(function() {
showImg(i);
}, i * 1000);
}
}
function showImg(i){
if(i % 2 === 0) {
document.write('<img src="./image/apple.png">');
} else {
document.write('<img src="./image/bomb.png">');
}
}
start();
위에서 설명했듯이 setTimeout()은 일정 시간이 지나면 함수를 실행한다. 실행하는 함수는 showImg(i)였다. for문으로 반복 실행을 하고, i의 값만큼의 딜레이를 계속 가지고 실행하는 것… 이었는데.
문제는 이 문제가 setInterval()과 관련한 문제였다는 것. setInterval()에 대한 설명을 들었음에도 불구하고 10에 과집중하여 이상한 답변을 내놓게 되었다.
이런 잘못된 과제에 대한 강사님의 피드백이 바로,
for문으로 setTimeout을 실행하는 것이 바로 setInterval이에요!
그렇다. for문으로 setTimeout()을 계속 실행하는 것이 바로 setInterval()의 역할이다. setTimout()이 딜레이를 가지고 실행한다면, setInterval()은 일정 시간마다 실행하는 것이니까. 그것을 듣고 수정한 내 코드는 다음과 같다.
let appleCount = 0;
let timerId;
function start(){
alert('이미지 10개 출력');
timerId = setInterval(showImg, 1000);
}
function showImg(){
appleCount++;
if(appleCount % 2 === 0) {
document.write('<img src="./image/apple.png">');
} else {
document.write('<img src="./image/bomb.png">');
}
if(appleCount >= 10) {
clearInterval(timerId);
}
}
start();
여기서 사용된 clearInterval()의 역할은 실행된 setInterval()을 정지하는 효과가 있다. 이렇게 하면 10개의 이미지라는 조건이 만족되면 setInterval()은 멈춘다.
6. Object- 객체
객체에 대한 설명은 일지에서도 한 적이 있지만, 다시 해본다. 일반적인 프로그래밍에서 객체의 정의는 다음과 같다.(위키백과 인용)
객체 또는 오브젝트(object)는 클래스에서 정의한 것을 토대로 메모리(실제 저장공간)에 할당된 것으로 프로그램에서 사용되는 데이터 또는 식별자에 의해 참조되는 공간을 의미하며, 변수, 자료 구조, 함수 또는 메소드가 될 수 있다.
이것이 JS에서도 비슷하게 적용된다. 클래스는 JS에서 사용하지 않기 때문에-class 의존적인 언어가 아니다- 제외한다면, 정의한 것을 토대로 메모리에 할당되는 것이다. 즉, JS의 대부분을 Object가 구성하고 있다 봐도 무방하다. 다만 변수에 관한 이야기는 오해가 있을까봐 덧붙여두는 것인데, JS에서는 변수가 즉 객체는 아니다. 변수가 가리키는 값이 객체가 될 수 있다는 느낌으로 알아두는 것이 좋다.

JS 내장 객체
JS 내에서 미리 정의된 객체이다. 선언 과정을 통해서 변수를 정의해서 사용한다. 이들의 종류를 이미지로 정리하면 다음과 같다고 볼 수 있다. 상세한 것은 일지에 한 차례 정리해둔 적이 있지만, 일지에 사용한 표를 이미지화 해서 다시 올려본다.

내장 객체 각자의 메서드에 관해서는 이전에 적었던 내용을 그대로 표로 가져와보겠다. 굵은 표시가 자주 사용되는 것이다.
Date
Date의 메소드 종류는 많아서(표가 10개까지만 지원된다) 종류에 따라서 정리한다.
Date 객체의 시간/날짜 정보를 반환하는 메소드
| 메소드 | 설명 |
| getYear() | 1970년 이후의 연도를 반환한다. |
| getMonth() | 월 반환(0:1월, 1:2월…) |
| getDate() | 일 반환 |
| getDay() | 요일 반환(0:일, 1:월…, 6:토) |
| getHours() | 시 반환(0~23) |
| getMinutes() | 분 반환(0~59) |
| getSeconds() | 초 반환(0~59) |
| getTime() | 1970년 1월 1일 이후 시간을 1/1000 단위로 표시 |
Date 객체의 시간/날짜 정보를 설정하는 메소드
| 메소드 | 설명 |
| setYear() | 1970년 이후의 연도를 설정한다 |
| setMonth() | 월 설정(0:1월, 1:2월…) |
| setDate() | 일 설정 |
| setHours() | 시 설정(0~23) |
| setMinutes() | 분 설정(0~59) |
| setSeconds() | 초 설정(0~59) |
| setTime() | 1970년 1월 1일 이후 시간을 1/1000 단위로 설정 |
Date 객체의 시간/날짜의 포맷을 변경하는 데 사용되는 메소드
| 메소드 | 설명 |
| parse(날짜 문자열) | 문자열을 시간으로 변경 |
| toGMTString() | 문자열을 GMT 날짜로 복귀 |
| toLocaleString() | 날짜를 문자열로 변환 |
Array
배열은 중요해서 몇 번이나 다루었으니, 메소드만 정리한다.
| 메소드 | 설명 |
| unshift(데이터) | 배열 맨 앞에 요소 추가 |
| shift() | 첫 번째 요소 삭제 |
| push(데이터) | 배열 마지막에 요소 추가 |
| pop() | 마지막 요소 삭제 |
| reverse() | 배열 순서를 역순으로 변경 |
| sort() | 오름차순으로 변경 |
| slice(start,end) | start~end-1 범위의 요소를 추출하여 새 범위를 생성 |
| splice(위치,개수,데이터) | 특정 위치에 요소 삭제하고 추가 |
Math
| 메소드 | 설명 | 메소드 | 설명 |
| sin(x) | sin | pow(x,y) | 지수 |
| cos(x) | cos | sqrt(x) | 제곱근 |
| tan(x) | tangent | round(x) | 반올림 |
| abs(x) | 절대값 | floor(x) | 버림(내림) |
| exp(x) | 지수함수 | ceil(x) | 올림 |
| log(x) | 로그함수 | max(x,y) | 최대값 |
| random(x) | 난수함수 | min(x,y) | 최소값 |
String
| 메소드 | 설명 |
| charAt() | 인덱스로 지정된 위치의 문자 반환 |
| indexOf() | 문자열에서 특정 문자의 위치 반환 |
| lastIndexOf() | 문자열 끝에서부터 검색하여 위치 반환 |
| substring() | 문자열의 일부분 추출 |
| slice() | 문자열의 일부분 추출(오른쪽 끝(음수) 지정 가능) |
| substr() | 문자열의 일부분 추출(추출할 문자 개수 지정) |
| toUpperCase() | 문자열을 모두 대문자로 변경 |
| toLowerCase() | 문자열을 모두 소문자로 변경 |
| split() | 문자열 분리 |
그 중에서 Math.random을 사용한 연습문제를 예제로 들고 와보겠다.
const picture = ['그림1.jpg', '그림2.jpg', '그림3.jpg'];
const getRandomPicture = () => {
const randomIndex = Math.floor(Math.random() * picture.length);
return picture[randomIndex];
};
let Randompicture = getRandomPicture();
document.write(`<img src="./${Randompicture}">`);
document.write(Randompicture);
참고로 이 과제의 제출문은 화살표 함수로 이루어져 있을 필요가 없기도 해서 다음처럼 한번 수정하였다. 수정한 것으로 보자.
const picture = ['그림1.jpg', '그림2.jpg', '그림3.jpg'];
const Randompicture = getRandomPicture();
function getRandomPicture() {
const randomIndex = Math.floor(Math.random() * picture.length);
return picture[randomIndex];
}
document.write(`<img src="./${Randompicture}">`);
document.write(Randompicture);
Math.random은 0.0x~0.9x까지의 난수를 생성한다. 여기에 picture.length를 곱해서 picutre.length만큼의 것을 생성하고(0.0x~0.2x), Math.floor()를 통하여 버림 형태로 구현한다. 왜 버림으로 했냐면, Array의 Index는 위에서 설명했다시피 0에서 시작하기 때문이다. 따라서 난수는 0,1,2가 생성이 되어, picture[0], picutre[1], picture[2]가 나타난다고 할 수 있다.
만약 이것을 +1하고, Array를 사용하지 않는다면 다음처럼 될 것이다.
function getRandomPicture() {
const randomIndex = Math.floor(Math.random() * 3) + 1;
return `그림${randomIndex}.jpg`;
}
const Randompicture = getRandomPicture();
document.write(`<img src="./${Randompicture}">`);
document.write(Randompicture);
DOM- Document Object Model
DOM이란 객체 지향 모델로써 구조화된 문서를 표현하는 형식이다. HTML 문서에 접근하기 위한 표준 모델이다. 기본적으로 사용하기 위해서는 각 메서드 안에 선택자를 넣어야 한다.
여기서 DOM Tree라는 개념에 대해서 알 필요가 있다.
DOM Tree
DOM Tree란, HTML 문서를 트리 구조로 표현한 것이다. HTML 문서의 계층 구조를 트리 형태로 표현하여, Node들을 부모(Parent)-자식(Child) 관계로 연결한다. 이 DOM Tree는 다음과 같이 그려진다 할 수 있다.

잠깐, 그렇다면 Node는 무엇인가? Node란, DOM 트리를 구성하는 개별 요소이다. 즉 DOM 트리 안에 Node가 있다고 할 수 있다. 여기서 조금 헷갈렸던 것은 Element(요소)와 Node의 관계인데, Element 또한 Node의 한 종류이다. ElementNode가 바로 Element를 가리키고 있는 것이다.
이를 위해서 DOM의 구성을 이미지화 해보았다.

Collections
Node는 다시 말했듯이 DOM 트리를 구성하는 개별 요소이다. 즉 DOM 트리 안에 Node가 있다고 할 수 있다. 그렇다면 Collections는 무엇일까? 여러 요소들을 모아놓은 객체이다. 어, 이거 배열Array과 비슷한 거 아니야? 하고 구조만 보면 착각할 수 있지만, 그렇지 않다. 물론 컬렉션은 배열로 변환이 가능하다. 하지만 컬렉션은 일단 배열 메서드를 사용하기 어렵다. 배열 메서드는, map, filter, reduce forEach 같은 것이 배열 메서드이다. 이 둘의 차이는 다음 표로 나타낼 수 있다.
| 배열 | 컬렉션 | |
| 배열 메서드 사용 | 모두 사용 가능 | NodeList만이 forEach를 사용할 수 있음 |
| 수정 가능 | 가능 (push, pop 등) | 읽기 전용 |
| 생성 | 직접 생성 가능 | DOM 메서드가 반환 |
| 타입 | Array | NodeList, HTMLCollection |
컬렉션은 각 DOM 요소를 for문으로 순회할 수 있고, length를 가지고 있다는 지점에서 사용하기 좋지만, 대체로 배열 변환을 한 뒤에 배열 메서드와 함께 사용한다.
DOM API Methods
DOM을 제어하기 위한 메서드이다. createElement()와 같이 요소를 생성하거나, getElementById(), getElementByName()와 같이 요소를 선택할 수 있다.
다음 연습문제와 함께 API 메서드를 보자.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>자바스크립트 연습</title>
<script>
function changeBorder(){
const span = document.getElementById('mySpan'); //Id myspan을 선택하여 변수로 만든다.
span.style.border = '1px dotted red'; //myspan의 style을 수정한다.
}
function countP(){
const pArr = document.querySelectorAll('p'); //p라는 선택자를 가진 요소 전부를 선택
let pCount = pArr.length; //pArr가 컬렉션이기 때문에 length 속성을 사용할 수 있다.
alert('<p>태그의 개수는 ' + pCount);
}
</script>
</head>
<body>
<h3>자바스크립트란?
<button onclick="changeBorder()">border</button>
<button onclick="countP()">p</button>
</h3>
<hr>
<p>자바스크립트는 웹 프로그래밍 언어로서 웹 페이지를 동적 변경시킬 수 있다.</p>
<p><span id="mySpan">C 언어</span>를 아는 사용자는 빠르게 학습할 수 있다.</p>
<p>이벤트 등 GUI 프로그래밍에 필요한 요소들이 있어 학습에 약간의 어려움이 있다.</p>
</body>
</html>
document.getElementById나 document.querySelectorAll를 사용하여 각 요소를 선택한다. 위는 mySpan이라는 id를 가진 span의 요소를 지정했고, 아래는 p라는 선택자를 가진 요소들 전부를 선택했다. 이럴 경우 컬렉션이 되기 때문에 length가 정의되어, 반환이 가능하다. 정확히는 NodeList라는 컬렉션이다. 만약 이녀석들에게 배열 메서드를 사용하면 그대로 되지 않는다.
Event
event는 사용자의 행동이나 브라우저의 동작에 의해 발생하는 사건을 의미한다. 사용자 이벤트나, 브라우저 이벤트로 나눌 수 있다. 사용자 이벤트의 대표적인 예로는 '클릭'이 있다. 클릭을 하면 어떤 동작이 웹페이지로부터 나오는 것, 그것이 이벤트이다.
이런 이벤트를 처리하는 방법에는 세 가지가 있다. 1. HTML 태그에 직접 이벤트 달기, 2. 속성방식으로 이벤트 처리하기, 3. 이벤트 리스너 등록하기. 다음 예제 코드를 준비해보았다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>이벤트 리스너 예제</title>
<script>
function alertClick(){
alert('클릭하셨군요!');
}
window.onload = function() {
// 방법 2: onclick 속성 방식
const button2 = document.getElementById('button2');
button2.onclick = function() {
alert('클릭하셨군요!');
};
// 방법 3: addEventListener 방식
const button3 = document.getElementById('button3');
button3.addEventListener('click', function() {
alert('클릭하셨군요!');
});
};
</script>
</head>
<body>
<h3>이벤트 리스너 예제</h3>
<button id="button1" onclick="alertClick()">직접 이벤트 다는 방식</button>
<button id="button2">onclick 속성 방식</button>
<button id="button3">addEventListener 방식</button>
</body>
</html>
이 세 방식의 차이는 HTML 등록과 속성 방식과 달리 addEventListener는 여러 개의 이벤트를 등록할 수 있다는 것이다. 간단한 경우에만 앞 두 가지 방법을 사용하고, 한 번의 이벤트 핸들러로 여러 가지 이벤트를 실행하고 싶을 경우에는 addEventListener를 사용한다.
7. 정리하며
이번에는 단순히 복습하기 보단 연습 코드와 함께 보충학습 형태로 한 주를 돌아보았다. 다음에는 특별편인 JS의 언어 방식에 대해서 다룰 예정이다.
'부트캠프 일지 > 멀티캠퍼스 TIL' 카테고리의 다른 글
| [Java 풀스택 개발자] React의 언어체계 (0) | 2026.01.26 |
|---|---|
| [Java 풀스택 개발자] jQuery 실전- localStorage 활용 Todo List (0) | 2026.01.19 |
| [Java 풀스택 개발자] #특별편(보충학습) - Javascript의 언어체계 (0) | 2026.01.18 |
| [Java 풀스택 개발자] #특별편(보충학습) - 콜백 함수에 대해 (0) | 2026.01.12 |
| [Java 풀스택 개발자] HTML과 CSS의 구성에 대해 (0) | 2026.01.06 |