ES6+ 문법
let과 const
ES6에서는 var 대신 블록 스코프를 가지는 let과 불변 변수인 const가 추가됨.
let x = 10;
x = 20; // 가능
const y = 30;
y = 40; // 에러 (const는 재할당 불가능)
let → 재할당 가능
const → 재할당 불가능
화살표 함수 (()=>{})
ES6에서 함수 선언을 간결하게 표현하는 방법.
// 일반 함수 표현식
function add(a, b) {
return a + b;
}
// 화살표 함수
const add = (a, b) => a + b;
console.log(add(2, 3)); // 5
특징
- return을 생략 가능 (한 줄 코드일 때)
- this가 기존 함수와 다르게 동작 (lexical this)
const obj = {
value: 10,
normalFunc: function () {
console.log(this.value); // this → obj
},
arrowFunc: () => {
console.log(this.value); // this → 상위 스코프 (window or undefined)
}
};
obj.normalFunc(); // 10
obj.arrowFunc(); // undefined (또는 window 객체 값)
템플릿 리터럴 (`${}`)
문자열을 더 쉽게 조작할 수 있도록 도와주는 문법.
const name = "희성";
const age = 25;
// 기존 문자열 결합 방식
console.log("이름: " + name + ", 나이: " + age);
// 템플릿 리터럴 사용
console.log(`이름: ${name}, 나이: ${age}`);
백틱(```)을 사용하여 여러 줄 문자열도 가능
const multiLine = `첫 번째 줄
두 번째 줄
세 번째 줄`;
console.log(multiLine);
객체 구조 분해 할당 (Destructuring)
객체에서 필요한 속성만 쉽게 꺼내서 사용할 수 있음.
const person = {
name: "희성",
age: 25,
job: "개발자"
};
// 기존 방식
console.log(person.name);
console.log(person.age);
// 구조 분해 할당
const { name, age } = person;
console.log(name); // "희성"
console.log(age); // 25
주의점
- 객체의 속성 이름과 같은 변수 이름을 사용해야 함.
- const { job: occupation } = person; 처럼 **별칭(Alias)**을 사용할 수도 있음.
const { job: occupation } = person;
console.log(occupation); // "개발자"
배열 구조 분해 할당
배열에서도 특정 요소를 쉽게 꺼낼 수 있음.
const numbers = [1, 2, 3];
// 기존 방식
console.log(numbers[0], numbers[1]);
// 구조 분해 할당
const [first, second] = numbers;
console.log(first); // 1
console.log(second); // 2
필요 없는 값은 빈칸으로 건너뛰기
const [, , third] = numbers;
console.log(third); // 3
나머지 값들을 배열로 저장할 수도 있음.
const [first, ...rest] = numbers;
console.log(rest); // [2, 3]
스프레드 연산자 (...)
스프레드 연산자는 배열, 객체를 펼치거나 복사하는 데 사용됨.
배열에서 사용
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];
console.log(arr2); // [1, 2, 3, 4, 5]
배열 복사
const copy = [...arr1]; // 깊은 복사
console.log(copy); // [1, 2, 3]
배열 결합
const arr3 = [4, 5, 6];
const combined = [...arr1, ...arr3];
console.log(combined); // [1, 2, 3, 4, 5, 6]
객체에서 사용
const user = { name: "희성", age: 25 };
const updatedUser = { ...user, job: "개발자" };
console.log(updatedUser);
// { name: "희성", age: 25, job: "개발자" }
객체 복사
const copyUser = { ...user };
console.log(copyUser); // { name: "희성", age: 25 }
객체 병합
const extraInfo = { job: "개발자", location: "서울" };
const fullUser = { ...user, ...extraInfo };
console.log(fullUser);
// { name: "희성", age: 25, job: "개발자", location: "서울" }
속성 덮어쓰기
const updatedUser2 = { ...user, age: 30 };
console.log(updatedUser2);
// { name: "희성", age: 30 } (원래 age=25였지만 덮어씌워짐)
디폴트 파라미터 (Default Parameters)
함수의 매개변수에 기본값을 설정할 수 있음.
function sum(a = 0, b = 0) {
return a + b;
}
console.log(sum(5, 10)); // 15
console.log(sum(5)); // 5 (b가 없으므로 기본값 0 사용)
console.log(sum()); // 0 (a와 b 모두 기본값 사용)
객체를 매개변수로 전달할 때도 기본값을 설정 가능
function greet(user = { name: "Guest" }) {
console.log(`Hello, ${user.name}!`);
}
greet({ name: "희성" }); // Hello, 희성!
greet(); // Hello, Guest!
주의: undefined일 때만 기본값 적용, null은 적용되지 않음.
console.log(sum(undefined, 5)); // 5 (기본값 적용)
console.log(sum(null, 5)); // null + 5 = 5 (null은 기본값 적용 X)
Promise (프로미스)
비동기 작업을 처리하는 객체. resolve(성공), reject(실패) 상태를 가짐.
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("데이터 로드 완료!");
}, 2000);
});
};
fetchData()
.then((result) => console.log(result)) // "데이터 로드 완료!" (2초 후)
.catch((error) => console.error(error));
resolve() → 성공, reject() → 실패
const fetchDataWithError = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject("데이터 로드 실패!");
}, 2000);
});
};
fetchDataWithError()
.then((result) => console.log(result))
.catch((error) => console.error(error)); // "데이터 로드 실패!" (2초 후)
여러 개의 Promise 실행 (Promise.all, Promise.race)
const p1 = new Promise((res) => setTimeout(() => res("첫 번째 완료"), 1000));
const p2 = new Promise((res) => setTimeout(() => res("두 번째 완료"), 2000));
Promise.all([p1, p2]).then(console.log);
// ["첫 번째 완료", "두 번째 완료"] (2초 후)
Promise.race([p1, p2]).then(console.log);
// "첫 번째 완료" (1초 후, 가장 먼저 실행된 프로미스 반환)
async/await
Promise를 더 쉽게 다룰 수 있도록 하는 ES8 문법.
const fetchData = async () => {
return "데이터 로드 완료!";
};
fetchData().then(console.log); // "데이터 로드 완료!"
await를 사용하여 Promise 결과를 기다릴 수 있음
const fetchWithDelay = () => {
return new Promise((resolve) => {
setTimeout(() => resolve("데이터 로드 완료!"), 2000);
});
};
const getData = async () => {
console.log("로딩 중...");
const result = await fetchWithDelay(); // 2초 대기
console.log(result);
};
getData();
// "로딩 중..." (즉시 실행)
// "데이터 로드 완료!" (2초 후 실행)
예외 처리 (try-catch)
const fetchWithError = () => {
return new Promise((_, reject) => {
setTimeout(() => reject("데이터 로드 실패!"), 2000);
});
};
const getDataWithErrorHandling = async () => {
try {
console.log("로딩 중...");
const result = await fetchWithError(); // 2초 대기
console.log(result);
} catch (error) {
console.error("에러 발생:", error);
}
};
getDataWithErrorHandling();
// "로딩 중..." (즉시 실행)
// "에러 발생: 데이터 로드 실패!" (2초 후 실행)
함수형 프로그래밍(Functional Programming, FP)은 순수 함수(Pure Function)와 불변성(Immutability)을 중시하는 프로그래밍 패러다임입니다.
ES6+에서는 map(), filter(), reduce() 같은 배열 메서드를 활용하여 함수형 스타일의 코드를 작성할 수 있습니다.
배열의 주요 메서드
map()
배열의 각 요소를 변형하여 새로운 배열을 반환합니다.
const numbers = [1, 2, 3, 4];
// 모든 요소를 제곱
const squared = numbers.map(num => num ** 2);
console.log(squared); // [1, 4, 9, 16]
기존 배열(numbers)을 변경하지 않고 새로운 배열을 생성함 → 불변성 유지!
filter()
조건을 만족하는 요소만 추려 새로운 배열을 반환합니다.
const numbers = [1, 2, 3, 4, 5];
// 짝수만 필터링
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers); // [2, 4]
reduce()
배열의 요소들을 하나의 값으로 축약할 때 사용합니다.
const numbers = [1, 2, 3, 4, 5];
// 모든 숫자의 합 구하기
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum); // 15
초깃값(0)을 설정해야 하며, acc(누적값)가 반복되면서 최종 값이 됨.
forEach()
배열의 각 요소를 순회하며 반복 작업을 수행합니다. 하지만 새로운 배열을 반환하지 않습니다!
const numbers = [1, 2, 3];
numbers.forEach(num => console.log(num * 2));
// 2, 4, 6 (출력만 할 뿐 새로운 배열을 생성하지 않음)
map()과 다르게 새로운 배열을 반환하지 않으므로, 값을 변환하려면 map()을 사용하는 것이 좋습니다.
find()
조건을 만족하는 첫 번째 요소를 반환합니다.
const users = [
{ id: 1, name: "희성" },
{ id: 2, name: "지민" },
{ id: 3, name: "태형" }
];
const user = users.find(user => user.id === 2);
console.log(user); // { id: 2, name: "지민" }
여러 개가 조건을 만족하더라도 첫 번째 요소만 반환합니다.
some()
배열에 하나라도 조건을 만족하는 요소가 있으면 true 반환.
const numbers = [1, 3, 5, 7];
// 짝수가 하나라도 있는가?
const hasEven = numbers.some(num => num % 2 === 0);
console.log(hasEven); // false (짝수가 없음)
every()
배열의 모든 요소가 조건을 만족해야 true 반환.
const numbers = [2, 4, 6, 8];
// 모든 요소가 짝수인가?
const allEven = numbers.every(num => num % 2 === 0);
console.log(allEven); // true (모든 요소가 짝수)
불변성 (Immutability)
함수형 프로그래밍에서는 원본 데이터를 변경하지 않고 새로운 데이터를 생성하는 방식을 권장합니다.
Object.assign()을 활용한 불변 객체 생성
const user = { name: "희성", age: 25 };
// 새로운 속성 추가 (원본 변경 X)
const updatedUser = Object.assign({}, user, { job: "개발자" });
console.log(updatedUser); // { name: "희성", age: 25, job: "개발자" }
console.log(user); // { name: "희성", age: 25 } (원본 변경 X)
스프레드 연산자 (...)를 활용한 불변 객체 생성
const user = { name: "희성", age: 25 };
// 새로운 속성 추가 (불변성 유지)
const updatedUser = { ...user, job: "개발자" };
console.log(updatedUser); // { name: "희성", age: 25, job: "개발자" }
console.log(user); // { name: "희성", age: 25 } (원본 변경 X)
객체 속성을 변경할 때도 새로운 객체를 만들어야 함.
const updatedUser2 = { ...user, age: 30 };
console.log(updatedUser2); // { name: "희성", age: 30 }
console.log(user); // { name: "희성", age: 25 } (원본 변경 X)
스프레드 연산자로 불변 배열 생성
const numbers = [1, 2, 3];
// 새로운 요소 추가 (불변성 유지)
const newNumbers = [...numbers, 4];
console.log(newNumbers); // [1, 2, 3, 4]
console.log(numbers); // [1, 2, 3] (원본 변경 X)
특정 요소를 수정할 때도 새로운 배열을 만들어야 함.
const updatedNumbers = numbers.map(num => (num === 2 ? 20 : num));
console.log(updatedNumbers); // [1, 20, 3]
console.log(numbers); // [1, 2, 3] (원본 변경 X)
비동기 프로그래밍
비동기 프로그래밍은 시간이 걸리는 작업(예: API 호출, 파일 읽기, 타이머 등)을 블로킹 없이 실행하는 방식.
1️⃣ setTimeout()
일정 시간이 지난 후 한 번만 실행되는 함수
console.log("시작");
setTimeout(() => {
console.log("3초 후 실행됨");
}, 3000);
console.log("끝");
실행 순서:
시작
끝
(3초 후) 3초 후 실행됨
2️⃣ setInterval()
일정 시간 간격으로 반복 실행되는 함수
let count = 0;
const interval = setInterval(() => {
count++;
console.log(`실행 횟수: ${count}`);
if (count === 5) {
clearInterval(interval); // 5번 실행 후 종료
}
}, 1000);
실행 결과:
실행 횟수: 1
실행 횟수: 2
실행 횟수: 3
실행 횟수: 4
실행 횟수: 5
(이후 중지)
3️⃣ Promise
비동기 작업을 처리하는 객체로, 성공(resolve()) 또는 실패(reject()) 상태를 가짐.
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("데이터 로드 완료!");
}, 2000);
});
};
fetchData()
.then(result => console.log(result)) // 2초 후 "데이터 로드 완료!"
.catch(error => console.error(error));
resolve() → 성공하면 .then() 실행
reject() → 실패하면 .catch() 실행
const fetchDataWithError = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject("데이터 로드 실패!");
}, 2000);
});
};
fetchDataWithError()
.then(result => console.log(result))
.catch(error => console.error("에러 발생:", error)); // "에러 발생: 데이터 로드 실패!" (2초 후)
4️⃣ async/await
Promise를 더 쉽게 다룰 수 있도록 하는 문법
const fetchData = () => {
return new Promise(resolve => {
setTimeout(() => resolve("데이터 로드 완료!"), 2000);
});
};
const getData = async () => {
console.log("로딩 중...");
const result = await fetchData(); // 2초 기다림
console.log(result);
};
getData();
// "로딩 중..." 즉시 출력
// (2초 후) "데이터 로드 완료!"
await을 사용하면 비동기 함수가 실행될 때까지 기다림
try-catch를 활용한 에러 처리 가능
const fetchDataWithError = () => {
return new Promise((_, reject) => {
setTimeout(() => reject("데이터 로드 실패!"), 2000);
});
};
const getDataWithErrorHandling = async () => {
try {
console.log("로딩 중...");
const result = await fetchDataWithError(); // 2초 대기
console.log(result);
} catch (error) {
console.error("에러 발생:", error);
}
};
getDataWithErrorHandling();
// "로딩 중..." 즉시 출력
// (2초 후) "에러 발생: 데이터 로드 실패!"
5️⃣ fetch() API
비동기적으로 서버에서 데이터를 가져오는 함수 (내장 HTTP 요청)
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then(response => response.json()) // JSON 변환
.then(data => console.log(data))
.catch(error => console.error("에러 발생:", error));
response.json() → 서버 응답을 JSON으로 변환
.catch() → 네트워크 오류 처리 가능
async/await으로 fetch() 사용하기
const fetchPost = async () => {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/posts/1");
const data = await response.json();
console.log(data);
} catch (error) {
console.error("에러 발생:", error);
}
};
fetchPost();
await fetch(url) → 서버 응답을 기다림
await response.json() → JSON 변환도 기다려야 함
'JavaScript > React' 카테고리의 다른 글
| React Router DOM (0) | 2025.03.21 |
|---|---|
| React 기본 개념 (0) | 2025.03.21 |
| 서버 트래픽 비용을 줄이고 싶을 때, Squoosh (0) | 2025.03.06 |
| [React] function - export가 없는 경우, export가 있는 경우: export, export default의 차이 (0) | 2025.01.12 |
| [React] React Hook[State, Effect, Ref, Context, Memo, Callback, Reducer, customHook] (1) | 2025.01.11 |