
data(값) 를 저장할수 있는 이름 지어진 기억 공간을 변수(variable)라고 한다.
변수를 만들때는 let 이라는 예약어를 이용해서 만든다.
작성방법
let 식별자(변수명) = 대입할값 ;
// num1 이라는 이름 지어진 기억 공간을 만들어서 숫자 data 10 을 대입하기(저장하기)
let num1 = 10;
// myName 이라는 이름 지어진 기억 공간을 만들어서 문자열 AcornAcademy 대입하기
let myName = "AcornAcademy";
값을 만들어서 Read Only (읽기 전용) 으로 사용하고 싶을 때는 상수로 만들 수도 있다.
작성방법
const 식별자(상수명) = 대입할값;
// 3.14159 라는 숫자값을 가지고 있는 PI 라는 이름의 상수 만들기
const PI = 3.14159;
// https://acornacademy.co.kr 이라는 문자값을 가지고 있는 ACORN 이라는 이름의 상수 만들기
const ACORN = "https://acornacademy.co.kr";
대입 연산자 = 는 우측에 있는 값을 좌측에 대입할 때 사용하는 연산자 이다.
변수 a 에 숫자 10을 대입하는 방법
let a = 10 ;
세미콜론은 실행할 명령문의 끝에 작성한다
// myColor 라는 변수에 "red" 라는 문자열 대입하기
let myColor = "red";
// myColor 에 다른 문자열(blue) 대입하기
myColor = "blue";
위의 2줄을 실행하면 최종적으로 myColor 라는 변수에는 "blue" 라는 문자열이 저장되어 있게 된다.
만드는 방법
- 필요한 숫자를 단순히 작성하면 만들어진다
- 산술연산(+, -, *, /, % 등등) 의 결과로 만들어진다
// 정수 10 을 만들어서 변수 num1 에 대입하기
let num1 = 10;
// 실수 10.1 을 만들어서 변수 num2 에 대입하기
let num2 = 10.1;
// 10 + 1 의 결과 값을 변수 result1 에 대입하기
let result1 = 10 + 1;
// 변수 num1 에 저장된 값에 10 을 더한 값을 변수 result2 에 대입하기
let result2 = num1 + 10 ;
만드는 방법
- 싱글 따옴표(single quotation) 으로 감싼다.
- 더블 따옴표(double quotation) 으로 감싼다.
- 백틱 (backtick) 으로 감싼다.
//single quotation 으로 string type 데이터 만들어서 변수에 대압하기
let myName = 'acorn';
//double quotation 으로 string type 데이터 만들어서 변수에 대압하기
let yourName = "academy";
//backtic 으로 string type 데이터 만들어서 변수에 대압하기
let ourName = `acorn academy`;
//backtic 을 이용하면 여러 줄의 문자열을 작성 하기가 편리하다
let info = `
번호 : 1
이름 : acorn academy
주소 : 강남역
전화번호 : 010
`;
만드는 방법
- true 또는 false 를 직접 작성하면 만들어진다.
- 비교연산, 논리연산의 결과로 만들어진다
let isRun = true;
let isWait = false;
let canEat = true;
//왼쪽이 오른쪽 보다 큰지 비교
let result = 10>1;
//왼쪽이 오른쪽 보다 작거나 같은지 비교
let result2 = 10<=1;
만드는 방법
const obj = { } ;
const obj2 = new Object( ) ;
Plain Object 에 여러가지 정보를 담고 참조해 보기
// 번호는 1 이고 이름은 김구라 이고 성별은 남자인 회원의 정보를 Plain Object 에 담기
let mem1 = {num:1, name:"김구라", isMan:true};
//a는 object type
let a=mem1; // mem1에 있는 plain object 값을 a에 복사
//b는 number type
let b=mem1.num;
//c는 string type
let c=mem1.name;
//d는 boolean type
let d=mem1.isMan;
//빈 object 를 만들고 나중에 필요에 따라서 데이터를 추가 할수 있다.
let mem2={};
mem2.num=2;
mem2.name="해골";
mem2.isMan=false;
//object 를 만들때 여러줄로 만들수도 있다.
let mem5={
num:3,
name:"원숭이",
isMan:true
};
만드는 방법
const arr = [ ] ;
const arr2 = new Array( ) ;
/*
내가 가장 좋아하는 음식을 아래의 순서대로 저장하기
소고기, 치즈, 햄버거, 곰탕, 스프
*/
//array type
let foods = ["소고기", "치즈", "햄버거", "곰탕", "스프"];
//배열의 특정 인덱스에 저장된 item 을 변수에 담기
let a=foods[0]; // 대괄호 안에 인덱스를 표기해서 참조 할수 있다.
let b=foods[1];
let c=foods[2];
//배열의 특정 인덱스에 저장된 item 을 수정하기
foods[2]="자장면"; // 대입 연산자를 이용해서 수정이 가능하다
foods[3]="짬뽕";

JavaScript에서 함수(Function)는 특정 작업을 수행하기 위해 독립적으로 작성된 코드 블록입니다. 함수는 코드를 재사용 가능하게 하고, 입력값(매개변수)에 따라 다른 결과를 반환할 수 있도록 합니다. JavaScript의 함수는 다른 변수와 마찬가지로 객체로 취급되며, 다양한 방식으로 정의하고 호출할 수 있습니다.
만드는 방법
// 익명의 함수를 만들어서 f1 이라는 상수에 대입하기
const f1 = function( ){ };
// 화살표 함수를 만들어서 f2 라는 상수에 대입하기
const f2 = ( )=>{ }
// f3 라는 이름의 함수 만들기
function f3( ){ }
일괄 실행할 javascript 를 작성하는 위치
function(){
중괄호 안에 여러줄의 javascript 를 작성 하면 된다.
}
function(){
실행할 javascript1 ;
실행할 javascript2 ;
실행할 javascript3 ;
.
.
.
}
함수 안에 작성된 javascript 를 일괄 실행하는 방법
// 함수를 만들어서 f1 변수 안에 담아 놓고
let f1 = function(){
console.log("하나");
console.log("두울");
console.log("세엣");
};
// 일괄 실행하고 싶은 시점에 f1() 을 실행하면 된다.
f1();
//변수를 선언만하고 값을 대입하지 않으면?
let a; // undefined 가 들어 있다
let b=undefined; //명시적으로 undefined 를 넣을수도 있다.

number type 데이터를 연산할때 사용한다
+ 더하기, - 빼기, * 곱하기, / 나누기, % 나머지
let result1 = 10+1;
let result2 = 10-1;
let result3 = 10*10; // * 는 곱하기 연산자
let result4 = 10/2; // / 는 앞에 있는 수를 뒤에 있는 수로 나누는 나누기 연산자
let result5 = 10%3; // 10 을 3으로 나눈 나머지값 1
let num1=10;
let num2=1;
//산술연산을 할때 숫자가 들어있는 변수명으로 할수도 있다.
let result6 = num1+1;
let result7 = num1%3;
let result8 = num1-num2;
//object 혹은 array 에 들어 있는 데이터를 이용해서 연산을 할수도 있다.
let obj={first:10, second:20};
let arr=[10, 20, 30];
let result9 = 1+obj.first;
let result10 = 10*arr[1];
값을 변수에 저장하거나 계산 결과를 변수에 다시 저장할 때 사용합니다.
==> 우측에 있는 값을 좌측에 대입
+==> 우측에 있는 값을 좌측에 있는 원래 값에 더해서 대입
-==> 우측에 있는 값을 좌측에 있는 원래 값에 빼서 대입
*==> 우측에 있는 값을 좌측에 있는 원래 값에 곱해서 대입
/==> 우측에 있는 값을 좌측에 있는 원래 값에 나누어서 대입
%==> 우측에 있는 값을 좌측에 있는 원래 값을 나눈 나머지 값을 대입
let num = 10; // 값 할당
num += 5; // 10 + 5 -> num = 15
num -= 3; // 15 - 3 -> num = 12
num *= 2; // 12 * 2 -> num = 24
num /= 4; // 24 / 4 -> num = 6
num %= 3; // 6 % 3 -> num = 0
두 값을 비교하고 참(
true) 또는 거짓(false)을 반환합니다.
===> 같은지 비교
!==> 다른지 비교
>=> 큰지 비교
>==> 크거나 같은지 비교
<=> 작은지 비교
<==> 작거나 같은지 비교
//1. 문자열의 내용 비교
let myName = "김구라"
let isEqual = myName == "김구라"; //true
let isDifferent = myName != "해골"; //true
//2. 숫자의 크기 비교
let myNum = 100;
let isBigger = myNum > 50; //true
let isSmaller = myNum < 200; //true
//3. 숫자가 같은지 다른지 비교
let yourNum=100;
let isNumEqual= yourNum == 101; //false
let isNumDiff= yourNum != 101; //true
논리 연산자는 조건문에서 논리값(
true또는false)을 조합하여 결과를 반환하는 데 사용됩니다. 다양한 조건을 결합하거나 반전할 때 유용합니다.
&& (AND 연산자)true)을 반환합니다.조건1 && 조건2false)이라면 조건2는 평가하지 않습니다. (단락 평가) let a = true;
let b = false;
console.log(a && b); // false (하나가 false)
console.log(a && !b); // true (a는 true, b는 false의 반전)
console.log(a && (5 > 3)); // true (5 > 3은 true)
|| (OR 연산자)true)을 반환합니다.조건1 || 조건2true)이라면 조건2는 평가하지 않습니다. (단락 평가) let a = true;
let b = false;
console.log(a || b); // true (하나가 true)
console.log(b || (3 > 5)); // false (모두 false)
console.log(b || (10 === 10)); // true (10 === 10은 true)
! (NOT 연산자)true) → 거짓(false) false) → 참(true)!조건 let a = true;
let b = false;
console.log(!a); // false (a의 반전)
console.log(!b); // true (b의 반전)
console.log(!(5 > 3)); // false (5 > 3은 true, 반전하면 false)
조건에 따라 다른 값을 반환합니다.
조건 ? 값1 : 값2
조건이 참이면 값1을, 거짓이면 값2를 반환합니다.
let age = 20;
let isAdult = (age >= 18) ? '성인' : '미성년자';
console.log(isAdult); // '성인'
증감 연산자는 변수의 값을 1 증가하거나 1 감소시킬 때 사용됩니다.
숫자 값에만 사용할 수 있으며, 변수 앞(prefix)이나 뒤(postfix)에 사용할 수 있습니다.
++)++변수): 값을 먼저 증가시키고, 증가된 값을 반환합니다.변수++): 값을 반환한 후, 값을 증가시킵니다. let a = 5;
console.log(++a); // 6 (먼저 1 증가하고 반환)
console.log(a); // 6
a = 5; // 초기화
console.log(a++); // 5 (값 반환 후 1 증가)
console.log(a); // 6
--)
- 변수의 값을 1 감소시킵니다.
- Prefix (
--변수): 값을 먼저 감소시키고, 감소된 값을 반환합니다.- Postfix (
변수--): 값을 반환한 후, 값을 감소시킵니다.
let b = 10;
console.log(--b); // 9 (먼저 1 감소하고 반환)
console.log(b); // 9
b = 10; // 초기화
console.log(b--); // 10 (값 반환 후 1 감소)
console.log(b); // 9
++변수, --변수)변수++, 변수--) let x = 3;
console.log(++x); // 4 (값을 먼저 증가하고 반환)
console.log(x); // 4
let y = 3;
console.log(y++); // 3 (값을 반환한 뒤 증가)
console.log(y); // 4
| 연산자 | 설명 | 결과 예시 |
|---|---|---|
++변수 | 값 증가 후 반환 | let x = 1; ++x; // 2 |
변수++ | 값 반환 후 증가 | let x = 1; x++; // 1 |
--변수 | 값 감소 후 반환 | let x = 1; --x; // 0 |
변수-- | 값 반환 후 감소 | let x = 1; x--; // 1 |
데이터의 타입을 확인하거나 변환할 때 사용합니다.
typeof: 데이터 타입 반환,instanceof: 객체의 인스턴스 여부 확인.
console.log(typeof 10); // 'number'
console.log(typeof 'hello'); // 'string'
console.log(typeof true); // 'boolean'
console.log(typeof []); // 'object'
console.log([] instanceof Array); // true (배열은 Array의 인스턴스)

제어문은 프로그램의 흐름을 결정하는 핵심 도구로, 코드가 실행되는 순서를 제어하고 조건에 따라 다른 동작을 수행할 수 있도록 돕습니다. 자바스크립트에서 제어문은 코드의 흐름을 논리적으로 결정하고, 복잡한 문제를 효율적으로 해결하기 위해 매우 중요한 역할을 합니다.
특정 code 블럭을 조건부로 실행하고자 할때 사용한다.
조건이 참(true) 이면 { } 블럭을 실행하고 거짓(false) 이면 { } 블럭을 실행하지 않는다.if ( 조건 ){
조건부로 실행할 code1;
조건부로 실행할 code2;
조건부로 실행할 code3;
.
.
}
// 변수 선언
let age = 20;
// 단일 if 문
if (age >= 18) {
console.log("성인입니다.");
}
// 출력 결과: 성인입니다.
// 변수 선언
let age = 10;
// 단일 if 문
if (age >= 18) {
console.log("성인입니다.");
}
// 아무것도 출력되지 않음
조건이 참일 때와 거짓일 때 각각 다른 코드 블럭을 실행하고자 할 때 사용합니다.
조건이 참일 경우 if 블럭이 실행되고, 거짓일 경우 else 블럭이 실행됩니다.
// 변수 선언
let age = 16;
// if...else 문
if (age >= 18) {
console.log("성인입니다.");
} else {
console.log("미성년자입니다.");
}
// 출력 결과: 미성년자입니다.
여러 조건을 순차적으로 검사하고, 해당 조건이 참인 코드 블럭을 실행합니다.
각 조건이 참인지 순차적으로 검사하며, 참인 조건의 블럭이 실행된 후에는 조건 검사를 종료합니다.
// 변수 선언
let score = 85;
// if...else if...else 문
if (score >= 90) {
console.log("A 학점입니다.");
} else if (score >= 80) {
console.log("B 학점입니다.");
} else if (score >= 70) {
console.log("C 학점입니다.");
} else {
console.log("F 학점입니다.");
}
// 출력 결과: B 학점입니다.
if 문 안에 또 다른 if 문을 포함하여 여러 조건을 중첩해서 검사할 수 있습니다.
바깥 조건이 참일 경우에만 내부 조건을 검사합니다.
// 변수 선언
let age = 22;
let hasID = true;
// 중첩 if 문
if (age >= 18) {
if (hasID) {
console.log("입장이 가능합니다.");
} else {
console.log("신분증이 필요합니다.");
}
} else {
console.log("미성년자는 입장할 수 없습니다.");
}
// 출력 결과: 입장이 가능합니다.
하나의 변수나 표현식에 대한 여러 조건을 검사하고, 조건에 맞는 블럭을 실행합니다.
case키워드를 사용하여 조건을 지정하며, 일치하는 조건을 찾으면 해당 블럭이 실행됩니다.
break를 사용하여 각 case에서 조건 검사를 종료합니다.default는 일치하는 조건이 없을 때 실행됩니다.
// 변수 선언
let day = 3;
// switch 문
switch (day) {
case 1:
console.log("월요일");
break;
case 2:
console.log("화요일");
break;
case 3:
console.log("수요일");
break;
case 4:
console.log("목요일");
break;
case 5:
console.log("금요일");
break;
default:
console.log("주말");
}
// 출력 결과: 수요일
JavaScript에서 반복문은 특정 코드 블럭을 여러 번 실행할 때 사용됩니다. 반복문에는 다양한 종류가 있으며, 반복 조건에 따라 선택적으로 사용할 수 있습니다.
지정된 횟수만큼 반복하고자 할 때 사용합니다.
초기화, 조건식, 증감식을 이용하여 반복을 제어합니다.
// 1부터 5까지 출력
for (let i = 1; i <= 5; i++) {
console.log(i);
}
// 출력 결과: 1 2 3 4 5
조건이 참(
true)인 동안 반복을 계속 실행합니다.
조건이 거짓(false)이 되면 반복이 종료됩니다.
// 1부터 5까지 출력
let i = 1;
while (i <= 5) {
console.log(i);
i++;
}
// 출력 결과: 1 2 3 4 5
최소 한 번은 반복을 실행한 후, 조건을 검사하여 반복을 계속할지 결정합니다.
조건이 거짓이어도 최초 1회는 반드시 실행됩니다.
// 1부터 5까지 출력
let i = 1;
do {
console.log(i);
i++;
} while (i <= 5);
// 출력 결과: 1 2 3 4 5
배열과 같은 반복 가능한 객체에서 각 요소를 반복할 때 사용합니다.
배열이나 문자열의 각 요소를 순차적으로 접근합니다.
// 배열의 각 요소 출력
const numbers = [10, 20, 30];
for (let num of numbers) {
console.log(num);
}
// 출력 결과: 10 20 30
객체의 속성(key)을 반복할 때 사용합니다.
객체의 각 속성 이름에 순차적으로 접근합니다.
// 객체의 각 속성 출력
const person = { name: "Alice", age: 25, city: "Seoul" };
for (let key in person) {
console.log(key + ": " + person[key]);
}
// 출력 결과: name: Alice, age: 25, city: Seoul
반복문을 즉시 종료합니다.
특정 조건을 만족할 때 반복을 중단하고자 할 때 유용합니다.
// 1부터 5까지 출력, 3에서 중단
for (let i = 1; i <= 5; i++) {
if (i === 3) {
break;
}
console.log(i);
}
// 출력 결과: 1 2
현재 반복을 건너뛰고 다음 반복으로 넘어갑니다.
특정 조건에서 반복을 건너뛰고자 할 때 유용합니다.
// 1부터 5까지 출력, 3은 건너뜀
for (let i = 1; i <= 5; i++) {
if (i === 3) {
continue;
}
console.log(i);
}
// 출력 결과: 1 2 4 5
JavaScript에서 예외 처리는 코드 실행 중 발생하는 오류를 잡아내고, 프로그램이 중단되지 않도록 적절히 처리할 수 있게 해줍니다. 예외 처리는 주로 try, catch, finally, throw 키워드를 사용합니다.
try블럭 안의 코드에서 예외가 발생하면,catch블럭이 실행됩니다.
예외가 발생하지 않으면catch블럭은 실행되지 않습니다.
try {
// 예외가 발생할 수 있는 코드
let result = 10 / 0;
console.log("결과:", result);
} catch (error) {
console.log("오류가 발생했습니다:", error.message);
}
// 출력 결과: 오류가 발생했습니다: Division by zero (가정)
finally블럭은 예외 발생 여부와 관계없이 항상 실행됩니다.
리소스를 해제하거나, 마무리 작업을 할 때 유용합니다.
try {
let data = JSON.parse('{"name": "Alice"}');
console.log("이름:", data.name);
} catch (error) {
console.log("JSON 파싱 오류:", error.message);
} finally {
console.log("예외 처리 완료.");
}
// 출력 결과:
// 이름: Alice
// 예외 처리 완료.
사용자 정의 예외를 발생시킬 수 있습니다.
throw키워드를 사용하여 특정 조건에서 강제로 예외를 발생시킵니다.
function checkAge(age) {
if (age < 18) {
throw new Error("나이는 18세 이상이어야 합니다.");
}
return "입장 가능합니다.";
}
try {
console.log(checkAge(16));
} catch (error) {
console.log("오류 발생:", error.message);
}
// 출력 결과: 오류 발생: 나이는 18세 이상이어야 합니다.
특정한 상황에서 오류 메시지를 커스터마이징하여 예외를 던질 수 있습니다.
throw와Error객체를 사용하여 오류 메시지를 지정합니다.
function divide(a, b) {
if (b === 0) {
throw new Error("0으로 나눌 수 없습니다.");
}
return a / b;
}
try {
console.log(divide(10, 0));
} catch (error) {
console.log("예외 처리:", error.message);
}
// 출력 결과: 예외 처리: 0으로 나눌 수 없습니다.
finally블럭은 예외 발생 여부와 상관없이 항상 실행됩니다.
리소스 해제나 마무리 작업을 위해 사용됩니다.
try {
let file = "data.txt";
// 파일을 열거나 데이터를 처리하는 코드
console.log("파일 처리 중...");
throw new Error("파일 처리 중 오류 발생");
} catch (error) {
console.log("오류:", error.message);
} finally {
console.log("파일을 닫습니다.");
}
// 출력 결과:
// 파일 처리 중...
// 오류: 파일 처리 중 오류 발생
// 파일을 닫습니다.
catch 블럭으로 전달되는 예외 객체에는 다양한 정보를 담고 있습니다.
message: 오류 메시지 텍스트를 반환합니다.name: 예외의 이름을 반환합니다 (예: TypeError, ReferenceError 등).stack: 예외 발생 시점의 스택 정보를 반환합니다.try {
let num = undefinedVariable; // 정의되지 않은 변수
} catch (error) {
console.log("에러 이름:", error.name);
console.log("에러 메시지:", error.message);
console.log("스택 추적:", error.stack);
}
try...catch 문을 사용하여 예외를 안전하게 처리하면, 코드의 오류 발생 시 프로그램이 중단되지 않도록 할 수 있습니다.throw를 사용해 사용자 정의 예외를 발생시켜, 특정 조건에서 오류 처리를 유연하게 제어할 수 있습니다.finally 블럭은 에러 발생 여부와 관계없이 항상 실행되므로, 리소스 해제와 같은 마무리 작업에 유용합니다.JavaScript의
document객체는 브라우저가 로드한 웹 페이지에 대한 정보와 조작을 제공합니다.document객체를 사용하여 HTML 요소에 접근하고, 내용을 변경하거나 속성을 조작할 수 있습니다.
document객체는 웹 페이지의 루트 노드이며, DOM 트리의 최상위에 있습니다.
웹 페이지의 모든 요소와 속성은document객체를 통해 접근할 수 있습니다.
console.log(document); // 현재 웹 페이지의 document 객체
document 객체를 사용하여 특정 HTML 요소를 선택할 수 있는 다양한 메서드가 있습니다.
getElementByIdid 속성을 기준으로 요소를 선택합니다.
id는 페이지 내에서 고유해야 하므로, 한 개의 요소만 선택됩니다.
<div id="content">Hello, World!</div>
const content = document.getElementById("content");
console.log(content.textContent); // 출력 결과: Hello, World!
getElementsByClassName클래스 이름을 기준으로 요소 목록을 선택합니다.
HTMLCollection으로 반환되며, 여러 요소가 선택될 수 있습니다.
<p class="text">첫 번째 문단</p>
<p class="text">두 번째 문단</p>
const texts = document.getElementsByClassName("text");
console.log(texts[0].textContent); // 출력 결과: 첫 번째 문단
getElementsByTagName태그 이름을 기준으로 요소 목록을 선택합니다.
HTMLCollection으로 반환되며, 여러 요소가 선택될 수 있습니다.
<div>Div 1</div>
<div>Div 2</div>
const divs = document.getElementsByTagName("div");
console.log(divs[1].textContent); // 출력 결과: Div 2
querySelectorCSS 선택자를 사용하여 첫 번째 요소를 선택합니다.
클래스, id, 태그 등을 조합하여 요소를 선택할 수 있습니다.
<p class="intro">안녕하세요</p>
const intro = document.querySelector(".intro");
console.log(intro.textContent); // 출력 결과: 안녕하세요
querySelectorAllCSS 선택자를 사용하여 모든 일치하는 요소를 선택합니다.
NodeList로 반환되며, 여러 요소가 선택될 수 있습니다.
<p class="item">아이템 1</p>
<p class="item">아이템 2</p>
const items = document.querySelectorAll(".item");
items.forEach(item => console.log(item.textContent));
// 출력 결과: 아이템 1, 아이템 2
innerHTML요소의 HTML 내용을 설정하거나 가져옵니다.
HTML 태그도 포함할 수 있습니다.
<div id="container"></div>
const container = document.getElementById("container");
container.innerHTML = "<p>새로운 문단 추가</p>";
console.log(container.innerHTML); // 출력 결과: <p>새로운 문단 추가</p>
innerText요소의 텍스트 내용을 설정하거나 가져옵니다.
<p id="text">안녕하세요</p>
const text = document.getElementById("text");
text.innerText = "안녕, 세계!";
console.log(text.innerText); // 출력 결과: 안녕, 세계!
getAttribute와 setAttribute요소의 속성을 가져오거나 설정할 때 사용합니다.
<img id="logo" src="logo.png" alt="사이트 로고">
const logo = document.getElementById("logo");
console.log(logo.getAttribute("src")); // 출력 결과: logo.png
logo.setAttribute("alt", "새로운 로고");
console.log(logo.getAttribute("alt")); // 출력 결과: 새로운 로고
removeAttribute요소의 특정 속성을 제거합니다.
logo.removeAttribute("alt");
console.log(logo.hasAttribute("alt")); // 출력 결과: false
classList.add요소에 클래스를 추가합니다.
<div id="box" class="red"></div>
const box = document.getElementById("box");
box.classList.add("blue");
console.log(box.className); // 출력 결과: red blue
classList.remove요소에서 특정 클래스를 제거합니다.
box.classList.remove("red");
console.log(box.className); // 출력 결과: blue
classList.toggle클래스가 존재하면 제거하고, 없으면 추가합니다.
box.classList.toggle("highlight");
console.log(box.className); // 출력 결과: blue highlight
classList.contains요소에 특정 클래스가 있는지 확인합니다.
console.log(box.classList.contains("blue")); // 출력 결과: true
addEventListener특정 이벤트가 발생했을 때 실행할 함수를 지정합니다.
<button id="myButton">클릭하세요</button>
const button = document.querySelector("#myButton");
button.addEventListener("click", () => {
alert("버튼이 클릭되었습니다!");
});
removeEventListener이벤트 리스너를 제거합니다.
function handleClick() {
alert("버튼이 클릭되었습니다!");
}
button.addEventListener("click", handleClick);
button.removeEventListener("click", handleClick);
참고
document객체를 통해 HTML 요소에 접근하고 내용을 조작할 수 있습니다.
getElementById,querySelector등을 사용하여 HTML 요소를 선택할 수 있습니다.
innerText,innerHTML등을 사용해 요소의 내용을 변경하고,setAttribute등으로 속성을 조작할 수 있습니다.
JavaScript에서 함수를 정의하는 방법은 여러 가지가 있습니다.
함수 선언식(Function Declaration)
함수 선언식은 function 키워드를 사용해 함수를 정의하는 방식입니다.
function add(a, b) {
return a + b;
}
이 방식으로 정의된 함수는 호이스팅(hoisting)에 의해 스크립트의 최상단으로 끌어올려져, 선언 전에 호출할 수 있습니다.
함수 표현식(Function Expression)
함수 표현식은 함수가 변수에 할당되어 정의되는 방식입니다.
const multiply = function(a, b) {
return a * b;
};
함수 표현식으로 정의된 함수는 호이스팅이 적용되지 않으므로, 함수 선언 이후에만 호출할 수 있습니다.
화살표 함수(Arrow Function)
화살표 함수는 간결하게 함수를 정의할 수 있는 ES6(ES2015) 문법입니다. function 키워드를 생략하고, =>를 사용하여 함수를 작성합니다.
const divide = (a, b) => a / b;
화살표 함수는 this 키워드의 동작 방식이 일반 함수와 다르며, 간단한 함수 표현에 주로 사용됩니다.
JavaScript 함수는 함수 선언 시 괄호 안에 변수를 나열하여 매개변수를 정의합니다. 매개변수는 함수가 호출될 때 함수 외부로부터 값을 전달받는 통로 역할을 합니다.
기본 매개변수: 매개변수에 기본값을 설정할 수 있습니다. 기본값이 설정된 매개변수는 함수가 호출될 때 값이 전달되지 않으면 기본값이 적용됩니다.
function greet(name = "Guest") {
console.log("Hello, " + name);
}
greet(); // "Hello, Guest" 출력
greet("Alice"); // "Hello, Alice" 출력
Rest 파라미터: Rest 파라미터는 함수가 전달받는 가변적인 수의 인수를 배열로 받아올 수 있게 해줍니다.
function sum(...numbers) {
return numbers.reduce((acc, curr) => acc + curr, 0);
}
console.log(sum(1, 2, 3, 4)); // 10 출력
JavaScript 함수는 return 키워드를 사용하여 특정 값을 반환할 수 있습니다. 반환된 값은 함수 호출 결과로 반환되며, 반환되는 값의 데이터 타입에 제한이 없습니다. 함수 내부에서 return 키워드가 실행되면, 함수의 실행은 즉시 종료되고, 이후의 코드는 실행되지 않습니다.
반환 값이 있는 함수:
function add(a, b) {
return a + b;
}
const result = add(5, 10); // 15가 result에 할당됨
console.log(result); // 15 출력
반환 값이 없는 함수: return이 없으면 undefined가 반환됩니다.
function logMessage(message) {
console.log(message);
}
const output = logMessage("Hello World"); // "Hello World" 출력
console.log(output); // undefined 출력
JavaScript에서 함수는 특별한 객체 유형으로, 다른 객체와 같이 변수에 할당하거나 다른 함수의 인수로 전달할 수 있습니다. 함수의 반환 타입(return type)은 함수가 반환하는 값의 타입이며, 특정 타입을 강제하지 않습니다.
예를 들어, 함수는 숫자, 문자열, 객체, 배열, 함수 그 자체 등 어떠한 데이터 타입이라도 반환할 수 있습니다.
숫자 반환:
function getNumber() {
return 42;
}
객체 반환:
function getPerson() {
return { name: "Alice", age: 30 };
}
함수 반환:
function createGreeting(name) {
return function() {
return "Hello, " + name;
};
}
const greeting = createGreeting("Bob");
console.log(greeting()); // "Hello, Bob" 출력
결론
JavaScript 함수는 특정 작업을 수행하거나 값을 반환하기 위해 작성됩니다. 매개변수와 반환 타입이 자유로워 함수 작성에 유연성을 제공합니다.
return문을 사용하여 함수가 값을 반환할 수 있으며, 반환되는 값의 타입에 제한이 없습니다. 또한 함수는 JavaScript의 객체 유형으로, 변수나 다른 함수의 인수로도 활용될 수 있습니다.
JavaScript에서 Plain Object(또는 "순수 객체")는 객체 리터럴(Object Literal)로 정의된 가장 기본적인 형태의 객체입니다. 다른 클래스나 프로토타입에서 상속되지 않은, 순수한 키-값 쌍으로 이루어진 객체를 의미합니다. 대부분의 객체는 이 형태로 생성되며,
{}또는new Object()를 사용해 만들 수 있습니다.
key: value 쌍으로 구성되며, 키는 문자열 또는 Symbol만 가능합니다.Object.prototype을 상속받고 추가적인 프로토타입 체인이 없습니다.JavaScript에서 Plain Object는 보통 두 가지 방법으로 생성합니다.
객체 리터럴을 사용한 생성
객체 리터럴 방식은 {} 중괄호를 사용하여 객체를 만드는 방식으로, 가장 간단하고 직관적입니다.
const person = {
name: "Alice",
age: 25,
greet: function() {
console.log("Hello, " + this.name);
}
};
new Object() 생성자 사용
JavaScript의 내장 생성자인 Object를 사용하여 Plain Object를 만들 수도 있습니다.
const person = new Object();
person.name = "Alice";
person.age = 25;
person.greet = function() {
console.log("Hello, " + this.name);
};
하지만 대부분 객체 리터럴 방식을 더 많이 사용하며, new Object()는 거의 사용되지 않습니다.
Plain Object의 속성은 점 표기법과 대괄호 표기법으로 접근할 수 있으며, 새로운 속성을 추가하거나 기존 속성을 수정할 수도 있습니다.
object.property 형태로 접근합니다.object["property"] 형태로 접근합니다. 대괄호 표기법은 속성 이름에 공백이 있거나 동적으로 접근해야 할 때 사용합니다.const car = { brand: "Toyota", model: "Camry" };
// 속성 접근
console.log(car.brand); // "Toyota"
console.log(car["model"]); // "Camry"
// 속성 추가 및 수정
car.year = 2020;
car["color"] = "blue";
console.log(car); // { brand: "Toyota", model: "Camry", year: 2020, color: "blue" }
객체의 속성은 delete 키워드를 사용하여 삭제할 수 있습니다.
delete car.year;
console.log(car); // { brand: "Toyota", model: "Camry", color: "blue" }
for...in 루프를 사용하여 객체의 모든 속성을 반복(iterate)할 수 있습니다. ES6 이후에는 Object.keys(), Object.values(), Object.entries()를 사용해 키, 값, 또는 키-값 쌍을 배열 형태로 가져와 반복할 수 있습니다.
for...in: 객체의 모든 열거 가능한 속성을 반복합니다.
for (let key in car) {
console.log(key + ": " + car[key]);
}
Object.keys(): 객체의 모든 키를 배열로 반환합니다.
const keys = Object.keys(car); // ["brand", "model", "color"]
Object.values(): 객체의 모든 값을 배열로 반환합니다.
const values = Object.values(car); // ["Toyota", "Camry", "blue"]
결론
Plain Object는 JavaScript에서 가장 기본적인 객체 형태로, 키-값 쌍을 저장하기 위한 용도>로 자주 사용됩니다.
Object.keys()와 같은 내장 메서드를 활용하여 속성 접근과 반복을 쉽게 수행할 수 있으며 Plain Object는 복잡한 데이터 구조의 기초로써 다양한 용도로 사용됩니다.
JavaScript에서 배열(Array)은 여러 값을 한 번에 저장할 수 있는 특수한 객체입니다. 배열은 순서(index)를 가지며, 다양한 데이터 타입의 값을 저장할 수 있습니다. 배열은 주로 데이터를 모아 관리하고, 반복 작업을 수행할 때 사용됩니다.
JavaScript에서 배열을 생성하는 방법은 두 가지가 있습니다.
배열 리터럴(Literal) 사용
배열 리터럴 방식은 대괄호 []를 사용하여 배열을 생성하는 가장 간단한 방법입니다.
const fruits = ["apple", "banana", "cherry"];
new Array() 생성자 사용
Array 생성자를 사용하여 배열을 만들 수도 있습니다. 초기값을 지정하거나 배열의 길이만 설정할 수 있습니다.
const fruits = new Array("apple", "banana", "cherry");
const numbers = new Array(5); // 길이가 5인 빈 배열
배열의 각 요소는 0부터 시작하는 인덱스(index)로 접근할 수 있습니다.
const fruits = ["apple", "banana", "cherry"];
console.log(fruits[0]); // "apple"
fruits[1] = "blueberry"; // "banana"를 "blueberry"로 수정
console.log(fruits); // ["apple", "blueberry", "cherry"]
JavaScript는 배열을 다루기 위한 다양한 내장 메서드를 제공합니다. 몇 가지 유용한 메서드를 살펴보겠습니다.
push(): 배열의 끝에 새로운 요소를 추가하고, 배열의 새로운 길이를 반환합니다.
const fruits = ["apple", "banana"];
fruits.push("cherry"); // ["apple", "banana", "cherry"]
pop(): 배열의 마지막 요소를 제거하고, 제거된 요소를 반환합니다.
const fruits = ["apple", "banana", "cherry"];
const lastFruit = fruits.pop(); // "cherry"
console.log(fruits); // ["apple", "banana"]
shift(): 배열의 첫 번째 요소를 제거하고, 제거된 요소를 반환합니다.
const fruits = ["apple", "banana", "cherry"];
const firstFruit = fruits.shift(); // "apple"
console.log(fruits); // ["banana", "cherry"]
unshift(): 배열의 앞에 새로운 요소를 추가하고, 배열의 새로운 길이를 반환합니다.
const fruits = ["banana", "cherry"];
fruits.unshift("apple"); // ["apple", "banana", "cherry"]
splice(): 배열에서 특정 위치에 요소를 추가, 제거하거나, 기존 요소를 수정할 수 있습니다.
const fruits = ["apple", "banana", "cherry"];
fruits.splice(1, 1, "blueberry"); // ["apple", "blueberry", "cherry"]
slice(): 배열의 일부를 선택하여 새로운 배열로 반환합니다. 원본 배열은 변경되지 않습니다.
const fruits = ["apple", "banana", "cherry"];
const newFruits = fruits.slice(0, 2); // ["apple", "banana"]
concat(): 두 개 이상의 배열을 연결하여 새로운 배열을 반환합니다.
const fruits = ["apple", "banana"];
const vegetables = ["carrot", "pepper"];
const food = fruits.concat(vegetables); // ["apple", "banana", "carrot", "pepper"]
forEach(): 배열의 각 요소에 대해 주어진 함수를 실행합니다.
const fruits = ["apple", "banana", "cherry"];
fruits.forEach(fruit => console.log(fruit));
// "apple", "banana", "cherry" 출력
map(): 배열의 각 요소에 함수를 적용한 결과를 모아 새로운 배열을 반환합니다.
const numbers = [1, 2, 3];
const squares = numbers.map(num => num * num); // [1, 4, 9]
filter(): 조건을 만족하는 요소들만 모아 새로운 배열로 반환합니다.
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(num => num % 2 === 0); // [2, 4]
배열은 다양한 반복 방법을 제공합니다.
for 루프: 가장 기본적인 반복문으로, 인덱스를 사용해 배열의 각 요소에 접근합니다.
const fruits = ["apple", "banana", "cherry"];
for (let i = 0; i < fruits.length; i++) {
console.log(fruits[i]);
}
for...of 루프: 배열의 각 요소를 반복하는 간단한 방법입니다.
for (let fruit of fruits) {
console.log(fruit);
}
forEach() 메서드: 배열의 각 요소에 대해 함수를 실행하는 메서드로, 배열의 길이에 맞춰 자동으로 반복합니다.
fruits.forEach(fruit => console.log(fruit));
동적 크기: JavaScript 배열은 크기를 동적으로 변경할 수 있습니다. 요소를 추가하거나 삭제할 때 자동으로 크기가 조정됩니다.
다양한 데이터 타입: JavaScript 배열은 여러 데이터 타입을 섞어서 저장할 수 있습니다.
const mixedArray = [1, "apple", true, { key: "value" }];
인덱스 기반: 배열 요소는 인덱스로 접근하며, 인덱스는 0부터 시작합니다.
length 속성: 배열의 길이를 반환합니다.
const fruits = ["apple", "banana"];
console.log(fruits.length); // 2
includes() 메서드: 배열에 특정 요소가 포함되어 있는지 확인합니다.
const fruits = ["apple", "banana"];
console.log(fruits.includes("banana")); // true
결론
JavaScript의 배열은 매우 유용한 데이터 구조로, 데이터를 순서대로 저장하고, 다양한 내장 메서드를 통해 데이터 작업을 쉽게 수행할 수 있습니다. 배열은 크기가 동적으로 조정되고, 인덱스가 자동으로 할당되며,
map(),filter()등 고급 메서드를 통해 더욱 강력하게 사용할 수 있습니다.
XMLHttpRequest는 웹 애플리케이션이 서버와 비동기적으로 데이터를 주고받을 수 있도록 하는 JavaScript 객체입니다. 이를 통해 페이지 전체를 새로고침하지 않고도 웹 페이지 일부의 데이터를 업데이트할 수 있습니다. 특히, AJAX(Asynchronous JavaScript and XML)의 핵심 역할을 하며, JSON 데이터를 포함한 다양한 형식의 데이터를 처리할 수 있습니다.
XMLHttpRequest 객체생성 및 초기화
new XMLHttpRequest(): 객체를 생성합니다.open(method, url, async): 서버 요청을 설정합니다.method: GET, POST 등 HTTP 메서드를 지정합니다.url: 요청할 서버의 URL을 설정합니다.async: 요청이 비동기적으로 이루어질지 여부를 지정합니다. true일 경우 비동기, false일 경우 동기로 처리됩니다.요청 보내기
send(body): 설정된 요청을 서버로 전송합니다. body는 POST 요청에서 전송할 데이터를 의미하며, GET 요청에서는 생략할 수 있습니다.setRequestHeader(header, value): 요청 헤더를 설정합니다. 예를 들어, setRequestHeader("Content-Type", "application/json")와 같이 요청 헤더를 설정하여 서버가 데이터를 어떤 형식으로 받을지 알려줄 수 있습니다.응답 처리
responseText: 텍스트 형태로 응답을 반환합니다.responseXML: XML 형태의 응답을 반환합니다(서버에서 XML을 반환하는 경우 사용).status: HTTP 응답 상태 코드를 반환합니다(예: 200은 성공, 404는 페이지를 찾을 수 없음).statusText: 상태 코드를 설명하는 텍스트를 반환합니다.이벤트
onreadystatechange: 요청의 상태가 변경될 때 호출됩니다. readyState와 status를 통해 응답이 완료되었는지 확인합니다.readyState: 요청의 상태를 나타내며, 5단계로 나뉩니다.0: UNSENT - 객체가 생성되었지만, open()이 호출되지 않은 상태.1: OPENED - open()이 호출된 상태.2: HEADERS_RECEIVED - 서버가 요청을 수신하고 헤더가 준비된 상태.3: LOADING - 응답 본문을 수신 중인 상태.4: DONE - 요청이 완료되어 응답을 사용할 수 있는 상태.아래는 XMLHttpRequest 객체를 이용하여 비동기적으로 데이터를 요청하고, 성공적으로 응답을 받으면 이를 콘솔에 출력하는 간단한 예제입니다.
// XMLHttpRequest 객체 생성
const xhr = new XMLHttpRequest();
// 요청 초기화
xhr.open("GET", "https://api.example.com/data", true);
// 요청 전송
xhr.send();
// 응답 처리
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) { // 요청 완료 상태 확인
if (xhr.status === 200) { // HTTP 상태 코드 확인 (성공)
console.log("응답 데이터:", xhr.responseText); // 서버에서 받은 응답 출력
} else {
console.error("요청 실패:", xhr.status, xhr.statusText);
}
}
};
동기 vs 비동기 요청
비동기 요청(async = true):
readyState와onreadystatechange콜백을 통해 응답을 처리하며, 요청이 완료될 때까지 브라우저가 다른 작업을 계속 수행할 수 있습니다.
동기 요청(async = false): 요청이 완료될 때까지 코드가 멈춰 있어야 하므로, 브라우저가 응답을 받을 때까지 기다리게 됩니다. 동기 요청은 사용자 경험을 저하시킬 수 있어, 대부분 비동기 요청이 권장됩니다.
XMLHttpRequest와 fetch API최근에는 fetch API가 도입되면서 XMLHttpRequest보다 더 간단하게 비동기 요청을 처리할 수 있습니다. fetch는 Promise 기반으로 동작하여 비동기 처리가 간편하고, 코드가 간결해지며 JSON 데이터를 쉽게 파싱할 수 있는 장점이 있습니다.
fetchAPI는 최신 웹 브라우저에서 비동기 HTTP 요청을 쉽게 수행할 수 있게 도와주는 네이티브 JavaScript API입니다.Promise기반으로 작동하며, 코드가 간결하고 이해하기 쉬워 기존의XMLHttpRequest보다 많은 개발자들이 선호하는 방식입니다.fetch를 사용하면 JSON 데이터를 포함한 다양한 형식의 데이터를 서버로부터 가져오거나 서버로 전송할 수 있습니다.
fetch 함수는 두 개의 매개변수를 받습니다.
fetch(url, options);
url: 데이터를 요청할 URL을 지정합니다.options (선택): 요청의 방법, 헤더, 바디 데이터 등을 설정하는 객체입니다.기본적으로 fetch는 GET 요청을 수행하며, Promise를 반환합니다.
Promise 기반: fetch는 Promise를 반환하기 때문에 then()과 catch() 메서드를 사용해 응답을 처리할 수 있습니다. 이로 인해 비동기 작업을 더 간결하게 작성할 수 있습니다.fetch는 .json() 메서드를 사용하여 응답 데이터를 JSON으로 쉽게 변환할 수 있습니다.fetch는 요청이 성공적으로 이루어졌다고 판단하므로 then 메서드가 호출됩니다. HTTP 상태 코드에 따른 에러 처리를 직접 해주어야 합니다.GET 요청아래는 fetch를 사용하여 간단히 데이터를 요청하는 예제입니다.
fetch("https://api.example.com/data")
.then(response => {
if (!response.ok) {
throw new Error("네트워크 응답에 문제가 있습니다.");
}
return response.json(); // 응답을 JSON 형식으로 변환
})
.then(data => console.log("응답 데이터:", data))
.catch(error => console.error("에러 발생:", error));
response.ok는 HTTP 상태 코드가 200~299 범위 내에 있으면 true를 반환합니다..json() 메서드를 사용하여 JSON 데이터를 쉽게 파싱할 수 있습니다.POST 요청 예제서버에 데이터를 전송할 때는 POST 메서드를 사용하며, options 객체에 method, headers, body 등을 지정합니다.
fetch("https://api.example.com/data", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ name: "John", age: 30 }) // 데이터를 JSON 형식으로 전송
})
.then(response => {
if (!response.ok) {
throw new Error("네트워크 응답에 문제가 있습니다.");
}
return response.json();
})
.then(data => console.log("서버 응답 데이터:", data))
.catch(error => console.error("에러 발생:", error));
headers: 요청의 헤더 정보를 설정합니다. 예를 들어, Content-Type을 application/json으로 지정하여 서버가 JSON 데이터를 받도록 설정할 수 있습니다.body: 요청 본문에 보낼 데이터를 설정합니다. JSON.stringify()로 데이터를 JSON 문자열로 변환하여 전송합니다.fetch는 네트워크 오류(예: 인터넷 연결 문제)가 발생할 경우에만 catch 블록이 호출됩니다. HTTP 오류(예: 404, 500 등)는 요청이 성공했다고 간주되므로, 상태 코드에 따른 처리를 직접 해야 합니다.
fetch("https://api.example.com/data")
.then(response => {
if (!response.ok) {
// HTTP 오류 상태에 따른 에러 처리
throw new Error(`HTTP 오류 상태: ${response.status}`);
}
return response.json();
})
.then(data => console.log("응답 데이터:", data))
.catch(error => console.error("에러 발생:", error));
XMLHttpRequest와의 차이점fetch는 Promise를 사용하여 비동기 작업을 더 간결하게 표현할 수 있습니다.XMLHttpRequest보다 코드가 간결하고 이해하기 쉽습니다..json() 메서드를 통해 JSON 데이터를 쉽게 파싱할 수 있습니다.결론
fetch는 비동기 요청을 수행하는 간단하고 강력한 방법을 제공합니다.Promise기반으로 작성되어 비동기 작업이 깔끔하게 처리되며, 최신 JavaScript 환경에서 널리 사용되고 있습니다. 다만, 상태 코드에 따른 에러 처리를 명시적으로 해줘야 하는 점을 고려해야 합니다.
Promise는 JavaScript에서 비동기 작업을 처리하기 위한 객체입니다. 비동기 작업의 성공 또는 실패 결과를 나타내며, 콜백 지옥 문제를 해결하는 데 큰 역할을 합니다.Promise는 주로 서버 요청이나 파일 읽기와 같은 시간이 오래 걸리는 작업에서 사용되며, 해당 작업이 완료된 후 실행할 코드를 명확하게 작성할 수 있게 해줍니다.
Promise의 상태Promise는 아래와 같은 세 가지 상태를 가집니다.
Promise 객체는 성공과 실패 시 처리할 코드를 지정할 수 있으며, 상태가 fulfilled나 rejected로 변경되면 해당하는 코드가 실행됩니다.
Promise 사용법기본 문법은 다음과 같습니다.
let promise = new Promise((resolve, reject) => {
// 비동기 작업을 수행합니다.
if (/* 성공 조건 */) {
resolve("성공 결과"); // 작업이 성공했을 때 호출
} else {
reject("실패 이유"); // 작업이 실패했을 때 호출
}
});
resolve(value): 작업이 성공하면 호출하며, value는 결과 값을 전달합니다.reject(error): 작업이 실패하면 호출하며, error는 오류 정보를 전달합니다.Promise 메서드.then(): Promise가 이행될 때 호출됩니다. resolve에서 전달된 값을 받아서 처리할 수 있습니다..catch(): Promise가 거부될 때 호출됩니다. reject에서 전달된 오류를 받아서 처리할 수 있습니다..finally(): 성공 또는 실패에 상관없이 작업이 완료된 후 항상 실행됩니다.아래는 Promise를 사용하여 비동기 작업을 처리하는 예제입니다.
let myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
let success = true; // 작업 성공 여부를 결정하는 예시
if (success) {
resolve("작업 성공!");
} else {
reject("작업 실패!");
}
}, 2000); // 2초 후에 작업이 완료되는 예시
});
myPromise
.then(result => {
console.log("성공:", result); // "성공: 작업 성공!" 출력
})
.catch(error => {
console.log("실패:", error); // "실패: 작업 실패!" 출력
})
.finally(() => {
console.log("작업 완료"); // 성공, 실패와 관계없이 항상 실행
});
setTimeout을 사용하여 2초 후에 작업이 성공하도록 설정했습니다.success가 true일 경우 resolve가 호출되어 .then()으로 넘어가고, false일 경우 reject가 호출되어 .catch()로 넘어갑니다..finally()는 작업 완료 후 항상 실행됩니다.Promise 체이닝Promise는 .then()을 연속으로 사용할 수 있어 작업 결과를 다음 작업에 전달하는 체이닝을 할 수 있습니다.
new Promise((resolve, reject) => {
setTimeout(() => resolve(10), 1000); // 1초 후 10을 반환
})
.then(result => {
console.log("1차 결과:", result); // 10
return result * 2;
})
.then(result => {
console.log("2차 결과:", result); // 20
return result * 2;
})
.then(result => {
console.log("3차 결과:", result); // 40
})
.catch(error => console.error("에러 발생:", error));
.then()에서 10이 반환되어 다음 .then()으로 넘어갑니다.Promise의 장점then()과 catch()를 사용해 콜백 지옥을 방지하고, 비동기 코드를 읽기 쉽게 만듭니다.catch()를 사용해 체인 전체에서 발생한 에러를 한 곳에서 처리할 수 있습니다.Promise.all(), Promise.race()와 같은 메서드를 사용해 여러 비동기 작업을 조합하여 처리할 수 있습니다.Promise.all()과 Promise.race()Promise.all(): 여러 개의 Promise를 동시에 실행하고, 모두 완료될 때까지 기다린 후 결과를 배열로 반환합니다. 하나라도 실패하면 reject됩니다.
Promise.all([promise1, promise2, promise3])
.then(results => console.log("모든 작업 성공:", results))
.catch(error => console.error("작업 실패:", error));
Promise.race(): 여러 개의 Promise 중 가장 먼저 완료된 Promise의 결과를 반환합니다. 하나라도 먼저 완료되면 다른 Promise의 상태는 고려하지 않습니다.
Promise.race([promise1, promise2, promise3])
.then(result => console.log("가장 빠른 작업 완료:", result))
.catch(error => console.error("가장 빠른 작업 실패:", error));
콜백 지옥(Callback Hell)은 비동기 작업을 처리하는 과정에서 콜백 함수들이 중첩되면서 코드의 들여쓰기 단계가 점점 깊어지는 현상을 말합니다. 주로 비동기 작업이 순차적으로 실행되어야 할 때 발생하며, 코드가 복잡해지고 가독성이 떨어지는 문제를 일으킵니다. 이를 흔히 "피라미드" 또는 "스파게티 코드" 형태라고도 합니다.
아래는 콜백 지옥이 발생하는 예제입니다. 비동기 작업이 연속적으로 진행될 때, 각 작업이 완료된 후 다음 작업을 수행하는 구조입니다.
doTask1(function(result1) {
doTask2(result1, function(result2) {
doTask3(result2, function(result3) {
doTask4(result3, function(result4) {
console.log("모든 작업 완료:", result4);
});
});
});
});
위 코드에서는 doTask1, doTask2, doTask3, doTask4와 같은 비동기 작업이 중첩되면서 코드가 우측으로 점점 밀려나게 됩니다. 이렇게 코드가 깊게 중첩되면 가독성이 떨어질 뿐만 아니라, 에러 발생 시 디버깅과 유지 보수도 어려워집니다.
콜백 지옥을 해결하기 위한 방법에는 여러 가지가 있습니다.
Promise 사용: Promise를 사용하여 콜백의 중첩을 줄이고, .then() 체이닝을 통해 가독성을 향상시킬 수 있습니다.
doTask1()
.then(result1 => doTask2(result1))
.then(result2 => doTask3(result2))
.then(result3 => doTask4(result3))
.then(result4 => console.log("모든 작업 완료:", result4))
.catch(error => console.error("에러 발생:", error));
async와 await 사용: async와 await는 Promise를 더 간결하게 사용할 수 있는 방법으로, 비동기 작업을 동기적으로 작성할 수 있게 도와줍니다. 이 방식은 코드가 직관적이고 가독성이 높아지는 장점이 있습니다.
async function executeTasks() {
try {
const result1 = await doTask1();
const result2 = await doTask2(result1);
const result3 = await doTask3(result2);
const result4 = await doTask4(result3);
console.log("모든 작업 완료:", result4);
} catch (error) {
console.error("에러 발생:", error);
}
}
executeTasks();
모듈화: 각 비동기 작업을 함수로 분리하고, 작업을 체계적으로 관리하여 가독성을 높일 수 있습니다.
결론
Promise는 비동기 작업의 가독성과 효율성을 높이는 중요한 도구입니다. 콜백 지옥을 피할 수 있고,then(),catch()를 통한 체이닝이 가능하여 직관적으로 코드를 작성할 수 있습니다. 최근에는async와await키워드로Promise를 더욱 간단하게 사용할 수 있지만, 기본적인Promise개념을 이해하는 것은 매우 중요합니다.
콜백 지옥은 비동기 작업을 처리하는 JavaScript 코드에서 발생하는 일반적인 문제로,Promise나async/await를 사용하여 코드의 가독성과 유지 보수성을 높일 수 있습니다. 콜백 지옥을 해결하면 코드가 직관적이고 깔끔해지며, 디버깅이 쉬워지고 유지 보수도 수월해집니다.
async와await는 JavaScript에서Promise기반 비동기 작업을 간편하게 처리하기 위해 도입된 키워드입니다. 이를 사용하면Promise의 체이닝(.then(),.catch())을 사용하지 않고, 마치 동기 작업을 작성하듯이 비동기 작업을 작성할 수 있어 코드의 가독성을 크게 향상시킵니다.
async 함수async 키워드는 함수 앞에 붙여서 해당 함수를 비동기 함수로 만듭니다.async 함수는 항상 Promise를 반환하며, 함수 내부에서 명시적으로 return된 값은 자동으로 Promise.resolve()로 래핑되어 반환됩니다.async function myFunction() {
return "완료";
}
myFunction().then(result => console.log(result)); // "완료" 출력
await 키워드await 키워드는 async 함수 내에서만 사용할 수 있으며, Promise가 해결될 때까지 함수의 실행을 일시 중지시킵니다.await는 Promise가 해결되면 그 결과를 반환하며, 마치 동기 코드처럼 값을 기다린 후 다음 줄의 코드를 실행할 수 있습니다.await는 Promise가 완료될 때까지 기다리지만, 비동기적으로 작동하여 메인 스레드를 차단하지 않습니다.async와 await의 기본 예제아래는 async와 await를 사용하여 비동기 작업을 처리하는 예제입니다.
function fetchData() {
return new Promise(resolve => {
setTimeout(() => resolve("데이터 로드 완료"), 2000); // 2초 후에 데이터 반환
});
}
async function getData() {
console.log("데이터 로드 중...");
const result = await fetchData(); // fetchData가 완료될 때까지 기다림
console.log(result); // "데이터 로드 완료" 출력
}
getData();
async 함수 내부에서 발생한 에러는 try...catch 문을 사용하여 처리할 수 있습니다. 이로 인해 에러 처리가 간결해지고, 코드가 Promise의 .catch() 메서드를 사용하는 것보다 더 직관적이게 됩니다.
async function getData() {
try {
const response = await fetch("https://api.example.com/data");
const data = await response.json();
console.log("응답 데이터:", data);
} catch (error) {
console.error("에러 발생:", error);
}
}
getData();
await를 사용하면 여러 비동기 작업을 순차적으로 실행할 수 있습니다. 아래 예제는 순차적으로 데이터를 처리하는 과정을 보여줍니다.
async function processTasks() {
const result1 = await task1();
const result2 = await task2(result1);
const result3 = await task3(result2);
console.log("최종 결과:", result3);
}
processTasks();
위 코드에서 각 task 함수는 await로 처리되어 순서대로 실행됩니다. 이는 비동기 작업 간 의존성이 있을 때 유용하게 사용됩니다.
비동기 작업 간에 의존성이 없는 경우, Promise.all()을 사용하여 병렬로 실행할 수 있습니다. 이렇게 하면 작업이 동시에 실행되므로 성능이 향상됩니다.
async function fetchDataFromMultipleSources() {
const [data1, data2, data3] = await Promise.all([
fetchData1(),
fetchData2(),
fetchData3()
]);
console.log("모든 데이터 로드 완료:", data1, data2, data3);
}
fetchDataFromMultipleSources();
이 예제에서는 fetchData1(), fetchData2(), fetchData3()가 병렬로 실행되어, 각각의 데이터가 모두 로드될 때까지 기다린 후 결과를 반환합니다.
async와 await의 장점try...catch 구문을 사용하여 에러를 쉽게 처리할 수 있습니다.결론
async와await는 JavaScript 비동기 작업을 더욱 직관적이고 깔끔하게 작성할 수 있게 해주는 강력한 도구입니다. 비동기 처리를 간결하게 하고 가독성을 향상시키기 때문에 최신 JavaScript 코드에서는 널리 사용됩니다. 다만, 비동기 작업을 병렬로 실행해야 하는 경우Promise.all()과 같이 적절한 방법을 병행하여 사용하는 것이 좋습니다.