일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 코드잇
- Cookie
- 엘리스sw트랙
- 항해99
- TiL
- 방송대컴퓨터과학과
- MySQL
- 프로그래머스
- 99클럽
- JavaScript
- 파이썬프로그래밍기초
- 중간이들
- 코딩테스트
- 파이썬
- 꿀단집
- Python
- 방송대
- node.js
- 유노코딩
- Git
- HTML
- presignedurl
- redis
- 코딩테스트준비
- aws
- nestjs
- 데이터베이스시스템
- 개발자취업
- SQL
- CSS
- Today
- Total
배꼽파지 않도록 잘 개발해요
[엘리스sw] 4주차 1일 - 비동기통신 Promise 본문
◆ 자바스크립트 제어 흐름
◆ 이벤트 루프
◆ Promise
자바스크립트 제어 흐름
자바스크립트 비동기 이해하기
· 자바스크립트는 다른 멀티스레드 프로그래밍 언어(JAVA, C++)와 다른 방식으로 비동기 동작을 처리한다.
· 처음 자바스크립트를 접하는 경우, 동작에 대한 정확한 이해가 없으면 코드의 흐름을 따라잡기 어렵다.
· 자바스크립트 내부의 비동기 동작을 이해하기 위해서는 이벤트 루프 등의 개념을 알아야만 한다.
자바스크립트 엔진
· 자바스크립트 엔진은 하나의 메인 스레드로 구성된다.
· 메인 스레드는 코드를 읽어 한 줄씩 실행한다.
· 브라우저 환경에서는 유저 이벤트를 처리하고 화면을 그린다.
자바스크립트(비동기)와 자바(멀티스레드)
자바스크립트
- 비동기 API가 호출되면(ex. setTimeout) 콜백함수가 즉시 실행되지 않는다. 대신 일정 시간이 지난 후 실행되도록 예약이 되어 있다. 브라우저나 Node.js 런타임은 이벤트 루프를 관리하며, 지정된 시간이 경과하면 콜백이 작업 대기열에 배치된다.
- 자바스크립트의 기본 스레드는 작업 대기열(Task Queue)에서 작업을 실행하는 역할을 한다. 호출 스택이 비어있을 때마다 대기열을 확인한다.
setTimeout(() => console.log('Hi'), 10000);
자바
- 지연을 도입하거나 특정 기간 동안 기다리려면 'Thread.slee' 메서드를 사용할 수 있다.
- 현재 스레드가 일시 중지되고 전체 프로그램이 지정된 기간 동안 지연된다. 이 시간 동안 스레드는 다른 작업을 수행하는 데 사용할 수 없다.
public class Main {
public static void main(String[] args) {
Runnable runnable = () -> {
try {
Thread.sleep(10000);
System.out.println("Hi");
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
동기적 제어 흐름
· 동기적 제어 흐름은 현재 실행 중인 코드가 종료되기 전까지 다음 줄의 코드를 실행하지 않는 것을 의미한다.
· 분기문, 반복문, 함수 호출 등이 동기적으로 실행된다.
· 코드의 흐름과 실제 제어 흐름이 동일하다.
· 싱글 스레드 환경에서 메인 스레드를 긴 시간 점유하면, 프로그램을 멈추게 한다.
let a = 10; // 선언문
console.log("a: ", a) // 동기적 실행
// 반복문
function foo(num) {
for (let i = 0; i < 10; ++i) {
console.log(num)
}
}
// 함수 호출
foo(num)
비동기적 제어 흐름
· 비동기적 제어흐름은 현재 실행 중인 코드가 종료되기 전에 다음 라인의 코드를 실행하는 것을 의미한다.
· 프로미스, 콜백 함수를 호출하는 함수 등은 비동기적으로 실행된다.
· 코드 흐름과 실제 제어 흐름이 다르다.
· 비동기 작업을 기다리는 동안 메인 스레드는 다른 작업을 처리한다.
· 비동기 등을 처리하는 모듈은 여러 스레드로 구성될 수 있다.
let a = 10; // 1
setTimeout(function callback() {
console.log('a : ', a)}
, 3000) // 3 (3초 후 실행됨)
console.log('Finished'); // 2
이벤트 루프
자바스크립트 비동기
· 자바스크립트 엔진은 비동기처리를 제공하지 않고, 이벤트 루프는 자바스크립트 엔진 외부에 존재함.
· 대신 비동기 코드는 정해진 함수(API)를 제공하여 활용할 수 있다.
ex. SetTimeout, XMLHttpRequest, fetch 등 Web API가 있음.
· node.js의 경우 파일 처리 API, 암호화 API 등을 제공한다.
// 타이머 비동기 처리
setTimeout(() => console.log('타이머 끝'), 1000)
setInterval(() => console.log('인터벌 타이머'), 1000)
- setTimeout: 지정된 지연(밀리초 단위) 후에 함수를 한 번 실행
- setInterval: 지정된 간격(밀리초 단위)으로 함수를 반복적으로 실행
// 네트워크 처리
fetch('https://google.com')
.then(() => console.log('네트워크 요청 성공.'))
.catch(() => console.log('네트워크 요청 실패.'))
- fetch : 네트워크 요청을 시작하고 해당 요청에 대한 응답으로 확인되는 Promise를 반환한다.
- .then() : Promise가 해결되면(네트워크 요청이 성공한 경우) 콜백 함수를 실행한다.
- .catch() : Promise가 거부된 경우(네트워크 오류가 있거나 응답 상태 코드가 오류를 나타내는 경우) 콜백 함수를 실행한다.
비동기 처리 모델
· 비동기 코드를 처리하는 모듈은 자바스크립트 엔진 외부에 있다.
· 이벤트루프(event loop), 태스크 큐(task queue), 잡 큐(job queue) 등으로 구성된다.
· API 모듈은 비동기 요청을 처리한 후 태스크 큐에 콜백 함수를 넣는다.
· 자바스크립트 엔진은 콜 스택이 비워지면, 태스크 큐의 콜백함수를 들어온 순서대로 실행한다.
// 사용자 데이터 로드 시에 콜백 함수가 실행
request("user-data", (userData) => {
// 사용자 데이터가 로드되었음을 나타내는 메시지 출력
console.log("userData 로드");
// 로드된 사용자 데이터를 처리하기 위해 `saveUsers` 함수 호출
saveUsers(userData);
});
console.log("DOM 변경");
console.log("유저 입력");
Promise
Promise API
· Promise API는 비동기 API 중 하나이다.
· 태스크 큐가 아닌 잡 큐(Job queue 혹은 microtask queue)를 사용한다.
· 잡 큐는 태스크 큐보다 우선순위가 높다.
setTimeout(() => {
console.log("타임아웃1");
}, 0);
Promise.resolve().then(() => console.log("프로미스1"));
setTImeout(() => {
console.log("타임아웃2");
}, 0);
Promise.resolve().then(() => console.log("프로미스2"));
/*
프로미스1
프로미스2
타임아웃1
타임아웃2
*/
- setTimeout : 지정한 시간(ms)만큼 기다렸다가 콜백 함수를 실행하는데, 이때 시간이 0ms라도 콜백함수는 현재 이벤트 루프가 끝난 후에 실행된다. 즉, 이전에 등록한 비동기 작업들이 먼저 실행된다는 의미이다.
- Promise.resolve().then(...) : Promise 객체를 즉시 해결하고, 해당 Promise에 등록된 콜백 함수는 마이크로태스크 큐에 들어가게 된다. 마이크로태스크 큐는 이벤트 루프의 현재 iteration에서 처리되기 때문에, 이 콜백 함수들은 현재 iteration이 끝날 때 즉시 실행된다.
- Promise의 콜백 함수가 마이크로태스크 큐에 들어가는 것과 setTimeout의 콜백 함수가 이벤트 큐에 들어가는 것의 차이로 인해 "프로미스1"과 "프로미스2"가 "타임아웃1"과 "타임아웃2"보다 먼저 실행된다.
Promise
· 비동기 작업을 표현하는 자바스크립트 객체
· 비동기 작업의 진행, 성공, 실패 상태를 표현함.
· 비동기 처리의 순서를 표현할수 있음.
Promise 생성자
new Promise(callback)
callback 함수는 (resolve, reject) 두 인자를 받는다.
- Promise가 성공했을 때 : resolve를 호출
- Promise 가 실패했을 때 : reject를 호출
// Promise 생성자를 사용하여 새로운 Promise 객체 생성
let promise = new Promise((resolve, reject) => {
// Math.random()은 0(포함)과 1(미포함) 사이의 난수를 생성
if (Math.random() < 0.5) {
// 랜덤 조건이 참이면, Promise를 "실패" 이유로 거부
return reject("실패");
}
// 랜덤 조건이 거짓이면, Promise를 값 10으로 이행
resolve(10);
});
- then() 메서드에 성공했을 때 실행할 콜백함수를 인자로 넘긴다.
- catch() 메서드에 실패했을 때 실행할 콜백함수를 인자로 넘긴다.
- finally() 메서드는 성공/실패 여부와 상관없이 모두 실행할 콜백 함수를 인자로 넘긴다.
- then(callback1, callback2)로 callback1의 자리에 성공, callback2의 자리에 실패 메서드를 인자로 넘길 수 있다.
promise
.then(data => {
console.log("성공:", data)
})
.catch(e => {
console.log("실패:", e)
})
.finally(() => {
console.log("promise 종료")
})
Promise 메서드 체인
· then/catch 메서드가 또 다른 Promise를 리턴하여, 비동기 코드에 순서를 부여한다.
· 이렇게 동일한 객체에 메서드를 연결할 수 있는 것을 체이닝(chaining)이라 한다.
· 함수를 호출한 주체가 함수를 끝낸 뒤 자기 자신을 리턴하도록 하여 구현한다.
promise
.then(data => {
return fetchUser(data)
})
.then(user => {
console.log('User : ', user_
})
.catch(e => {
console.log("실패: ", e)
})
promise.resolve, promise.reject
· Promise.resolve 함수는 성공한 Promise를 바로 반환한다.
· Promise.reject 함수는 실패한 Promise를 바로 반환한다.
· 인위적으로 Promise 메서드 체인을 만들 수 있다.
· 비동기 코드로 진행해야 하는 상황 등에 유용하게 사용할 수 있다.
Promise
.resolve(10)
.then(console.log)
Promise
.reject("Error")
.catch(console.log)
Promise.all
· Promise.all은 Promise의 배열을 받아 모두 성공 시 각 Promise의 resolved 값을 배열로 반환한다.
· 하나의 Promise라도 실패할 시, 가장 먼저 실패한 Promise의 실패 이유를 반환한다.
Promise.all([
promise1,
promise2,
promise3
])
.then(values => {
console.log("모두 성공:", values);
})
.catch(e => {
console.log("하나라도 실패:", e);
});
디바운싱과 쓰로틀링
디바운싱(Debouncing)
- 특정 이벤트(키보드 입력, 스크롤 이벤트)가 여러 번 발생할 때, 마지막 이벤트가 발생한 후에만 특정 동작을 수행하는 기술
- 예시 : 텍스트를 입력할 때 자동으로 검색 결과를 가져오는데, 사용자가 연속적으로 텍스트를 입력하는 경우에 매번 검색을 수행하지 않고, 마지막 텍스트 입력 이후 일정 시간 동안 대기한 뒤에 검색을 수행하는 것
// Debouncing function
function debounce(func, delay) {
let timer;
// 실제로 호출될 함수를 반환
return function () {
// 함수가 호출될 때의 컨텍스트와 인자를 저장
const context = this;
const args = arguments;
// 이전에 설정된 타이머를 취소
// 모았다가 한번에 해야됨.
clearTimeout(timer);
// delay 시간 후에 실제 함수를 호출하는 타이머를 설정
timer = setTimeout(() => {
func.apply(context, args);
}, delay);
};
}
쓰로틀링(Throttling)
- 특정 이벤트의 발생을 제한하여 일정 시간 동안 해당 이벤트가 여러 번 발생해도 특정 동작이 너무 자주 실행되지 않도록 하는 기술
- 예시 : 무한 스크롤 혹은 페이지 스크롤 이벤트에서, 사용자가 스크롤할 때마다 많은 이벤트가 발생할 수 있음. 이때 이벤트 발생 횟수를 제한함.
// Throttling function
function throttle(func, delay) {
let throttled = false;
// 실제로 호출될 함수를 반환
return function () {
// 함수가 호출될 때의 컨텍스트와 인자를 저장
const context = this;
const args = arguments;
// 쓰로틀링이 적용되지 않은 경우
if (!throttled) {
// 실제 함수를 호출
func.apply(context, args);
// 쓰로틀링 플래그를 설정
throttled = true;
// delay 시간 후에 쓰로틀링 플래그를 초기화하는 타이머를 설정
setTimeout(() => {
throttled = false;
}, delay);
}
};
}
'교육 > 엘리스 SW 학습 내용' 카테고리의 다른 글
[엘리스sw] 5주차 1일 - Node.js와 MongoDB I (0) | 2024.01.20 |
---|---|
[엘리스sw] 4주차 3일 - async/await, API (0) | 2024.01.15 |
[엘리스sw] 3주차 5일 - 자바스크립트 실행 (변수와 객체) (0) | 2024.01.11 |
[엘리스sw] 3주차 3일 - 자바스크립트 동작원리 (0) | 2024.01.08 |
[엘리스sw] 2주차 3일 - DOM과 이벤트 (0) | 2024.01.01 |