[JavaScript]
기초
- [JS] Js기초
- [JS] Js기초 변수
- [JS] Js기초 자료형
- [JS] Js기초 형변환
- [JS] Js기초 연산자
- [JS] Js기초 반복문
- [JS] Js기초 switch
- [JS] Js기초 function
- [JS] Js기초 객체
- [JS] Js기초 배열
중급
- [JS] Js중급 호이스팅(Hoisting)과 TDZ(Temporal Dead Zone)
- [JS] Js중급 생성자함수
- [JS] 객체 메소드(Object methods), 계산된 프로퍼티(Computed property)
- [JS] 심볼(Symbol)
- [JS] WeakMap WeakSet
- [JS] 숫자, 수학 method (Number, Math)
- [JS] 문자열 메소드(String methods)
- [JS] 배열 메소드(Array methods)
- [JS] 구조 분해 할당 (Destructuring assignment)
- [JS] 매개변수 리스트와 전개 문법(Rest parameters and spread syntax)
- [JS] 클로저(Closure)
- [JS] setTimeout / setInterval
- [JS] call / apply / bind
- [JS] 상속, 프로토타입(Prototype)
- [JS] 클래스(Class)
- [JS] 클로미스(Promise)
- [JS] 비동기 처리(Async/Await)
- [JS] Generator
- [JS] 메모리 릭(Memory Leak)
async/await는 Promise를 더 쉽게 사용할 수 있게 해주는 문법이야! 😊
1. 기본 문법
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // Promise 방식
function fetchUser() {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ id: 1, name: "김코딩" });
}, 1000);
});
}
// async/await 방식
async function getUser() {
const user = await fetchUser();
console.log(user); // {id: 1, name: "김코딩"}
}
getUser();
|
2. 에러 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| async function fetchData() {
try {
const response = await fetch("https://api.example.com/data");
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error("데이터 가져오기 실패:", error);
throw error; // 에러 다시 던지기
}
}
// 사용
async function main() {
try {
const result = await fetchData();
console.log(result);
} catch (error) {
console.error("메인 에러:", error);
}
}
|
3. 병렬 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| // 순차 처리 (더 느림)
async function sequential() {
const user = await fetchUser(1); // 1초
const posts = await fetchPosts(1); // 1초
const comments = await fetchComments(1); // 1초
// 총 3초 소요
return { user, posts, comments };
}
// 병렬 처리 (더 빠름)
async function parallel() {
const userPromise = fetchUser(1);
const postsPromise = fetchPosts(1);
const commentsPromise = fetchComments(1);
// 동시에 실행
const [user, posts, comments] = await Promise.all([
userPromise,
postsPromise,
commentsPromise,
]);
// 총 1초 소요
return { user, posts, comments };
}
|
4. 실전 예제: API 클래스
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| class API {
constructor(baseURL) {
this.baseURL = baseURL;
}
async get(endpoint) {
const response = await fetch(this.baseURL + endpoint);
if (!response.ok) throw new Error("API 호출 실패");
return response.json();
}
async post(endpoint, data) {
const response = await fetch(this.baseURL + endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
if (!response.ok) throw new Error("API 호출 실패");
return response.json();
}
}
// 사용 예시
const api = new API("https://api.example.com");
async function getUserData(userId) {
try {
// 병렬로 데이터 가져오기
const [user, posts] = await Promise.all([
api.get(`/users/${userId}`),
api.get(`/users/${userId}/posts`),
]);
return { user, posts };
} catch (error) {
console.error("데이터 로딩 실패:", error);
throw error;
}
}
|
5. 반복문에서의 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| // forEach와 async/await (작동하지 않음)
async function wrong() {
const ids = [1, 2, 3];
ids.forEach(async (id) => {
// 주의: 이렇게 하면 안됨!
const data = await fetchData(id);
console.log(data);
});
console.log("완료"); // 데이터 로딩 전에 출력됨
}
// 올바른 방법 1: for...of
async function correct1() {
const ids = [1, 2, 3];
for (const id of ids) {
const data = await fetchData(id);
console.log(data);
}
console.log("완료"); // 모든 데이터 로딩 후 출력
}
// 올바른 방법 2: Promise.all
async function correct2() {
const ids = [1, 2, 3];
const promises = ids.map((id) => fetchData(id));
const results = await Promise.all(promises);
results.forEach((data) => console.log(data));
console.log("완료");
}
|
6. 유용한 패턴들
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| // 타임아웃 추가
async function fetchWithTimeout(timeout) {
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error("시간 초과!")), timeout);
});
try {
const result = await Promise.race([fetchData(), timeoutPromise]);
return result;
} catch (error) {
console.error("에러:", error);
throw error;
}
}
// 재시도 로직
async function fetchWithRetry(maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fetchData();
} catch (error) {
if (i === maxRetries - 1) throw error;
console.log(`재시도 ${i + 1}/${maxRetries}`);
await new Promise((resolve) => setTimeout(resolve, 1000));
}
}
}
|
꿀팁! 🍯
- async 함수는 항상 Promise를 반환
1
2
3
4
5
6
7
8
| async function example() {
return 123;
}
// 위 함수는 아래와 동일
function example() {
return Promise.resolve(123);
}
|
- 화살표 함수에서 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| const fetchData = async () => {
const response = await fetch("https://api.example.com/data");
return response.json();
};
// 즉시 실행 함수
(async () => {
try {
const data = await fetchData();
console.log(data);
} catch (error) {
console.error(error);
}
})();
|
이제 async/await는 마스터! 😎
비동기 코드를 동기 코드처럼 깔끔하게 작성할 수 있을 거야!