티스토리 뷰

프리온보딩 프론트앤드 코스 2기 TIL

3주 차 여섯 번째 수업 TIL

YG - 96년생 , 강아지 있음, 개발자 희망 2022. 2. 23. 11:56

원티드 프리온 보딩 프론트 앤드 3주 차 여섯 번째 수업  TIL (22.01.24~22.03.03)

프리온 보딩 프론트 앤드의 강사님은 위 코드의 공동 창업자&이사의 직책을 가지고 계신 김예리 님이 강의를 해주셨습니다.

 

동기와 비동기

 

동기(Synchronouse)

정의

  • 현재 실행 중인 코드가 끝나야 다음 코드를 실행 = 현재 실행 중인 task가 종료할 때까지, 다음 task가 대기하는 방식

고민할 점

  • 장점: 동기 처리는 코드를 순서대로 하나씩 실행하기 때문에, 실행 순서가 보장된다.
  • 단점: 현재 실행중인 task가 종료될 때까지 다음 task가 실행이 안 된다는 게 문제 = task가 블로킹(blocking) 된다고 말한다.

참고) 전형적인 동기의 blocking 예제

const arr = [];

for (let i = 0; i < 1000; i++) {
  arr.push(i);
	// 1000번 반복하면서 실행할 더더더더더 복잡한 코드
}

**alert("안녕하세요");**  // 확인 누를 때까지 console 코드로 넘어가지 않음
****console.log(arr);

 

비동기(Asynchronouse)

정의

  • 현재 실행 중인 코드가 완료되지 않아도, 다음 코드로 넘어감 = 비동기 task(코드)는 실행하라고 브라우저에 맡겨놓고, 다음 task(코드)로 넘어감

고민할 점

  • 장점: 현재 실행중인 task가 완료되지 않아도, 다음 task를 실행하기 때문에 블로킹이 발생하지 않는다.
  • 단점: task의 실행 순서가 보장되지 않는다.

 

🙋🏻‍♀️ [비동기 처리가 필요한 이유]

자바스크립트 엔진은 한 번에 하나의 task만 실행할 수 있는 Single Thread. Single Thread는 한 번에 하나의 task만 실행할 수 있기 때문에 처리에 시간이 걸리는 task를 실행하는 경우 Blocking(작업 중단)이 발생한다.

Blocking 되면 사용자가 다음 task가 실행될 때까지 기다려야 되겠죠? 🤢

 

 🙆🏻‍♂️ [여기에서 바로 콜백함수가 등장]

비동기를 처리하기 위해 전통적으로 콜백 패턴을 사용합니다.

 

 

AJAX(Asynchronous JavaScript and XML)

  • AJAX는 js를 사용하여 브라우저가 서버에게 비동기 방식으로 데이터를 요청하고, 응답한 데이터를 수신하여 웹페이지를 일부 동적으로 갱신.

 

콜백 함수 (Callback Function; cb)

정의

  • 함수의 매개변수가 함수일 때, 매개변수로 받은 함수를 콜백함수르고 부른다. 끝 -!
  • 고차 함수(Higher Order Function): 매개변수를 함수로 받은 함수. 즉, 외부에서 콜백 함수를 전달받은 함수
    • 아래에서 showMessage, Array.map 등
    • 고차 컴포넌트 Higher Order Component(HOC) 들어보셨나요? 컴포넌트를 매개변수로받아서, 컴포넌트를 반환하는 컴포넌트~~
  • 잠깐 일급함수에 대해 알고 넘어갈게요.
    • 일급 함수의 특징
      • 함수를 변수에 할당 가능
      • 함수를 또 다른 함수 인자로 전달 가능
      • 함수의 반환값으로 함수 전달 가능
    • 함수형 프로그래밍 특징 중의 하나가 바로 일급 함수입니다.
      • 자바스크립트 언어 또한 함수형 프로그래밍 기법을 구사할 수 있습니다.
  • 함수를 다른 변수와 동일하게 다루는 언어는 일급 함수를 가졌다고 표현합니다. 예를 들어, 일급 함수를 가진 언어에서는 함수를 다른 함수에 인수로 제공하거나, 함수가 함수를 반환할 수 있으며, 변수에도 할당할 수 있습니다.

사용

// closeFn가 바로 콜백함수!
// closeFn가 비동기로 쓰인건 아닙니다. (sync callback - 동기 콜백)
function showMessage(msg, closeFn) {
	// 로직로직~~
	
	closeFn(true);
}
// map 함수의 인자인 el => el*2 함수가 콜백함수!
// 얘도 비동기 아닙니다. (sync callback)
[1,2,3].map(el => el*2);
// addEventListener의 두 번째 인자도 콜백함수!
// 얘가 바로~ 비동기로 동작! (async callback)
window.addEventListener('keydown', e => {
	// 로직
});
// setTimeout 함수에 넘긴 익명함수가 콜백함수!
// Hello 또한 3초뒤에 나오죠. 비동기 동작! (async callback)
setTimeout(function(){ 
	alert("Hello"); 
}, 3000);
  • 콜백 함수라고 해서 꼭 비동기 동작에 쓰이는 것이 아닙니다.

 

 

Promise

  • Promise는 비동기 동작을 처리하기 위해 ES6에 도입되었다.
  • Promise는 클래스다.
  • Promise 클래스를 인스턴스화 해서 promise 객체를 만든다.
  • 반환된 promise로 원하는 비동기 동작을 처리한다.
  • Promise는 일단 state와 resolve, reject 함수를 이해하면 된다.

 

Promise - resolve, reject

Promise 구현하기

let promise = new Promise(function(resolve, reject) {
	// 여기 비동기 로직을 작성!
	// 시켜놓고 언제 완료될지 모르는 로직!
});
  • resolve는 비동기 로직이 성공했을 때 실행할 함수
  • reject는 비동기 로직이 실패했을 때 실행할 함수

resolve 이해하기

let promise = new Promise(function(resolve, reject) {
	// 여기 비동기 로직을 작성!
	// 시켜놓고 언제 완료될지 모르는 로직!

	// 완료 하면 -> resolve 호출
  // 비동기 동작 실패 하면 -> reject 호출
});

promise.then(function() {
	// 이 함수가 바로 위의 resolve 입니다.
	// 위의 비동기 로직이 성공하면 호출 됩니다!
});

예제

let promise = new Promise(function(**resolve**, reject) {
    setTimeout(function() {
				// resolve 함수에 인자 넘기면
        **resolve('hello world');**
    }, 2000);
});

// resolve 호출시 전달되는 인자 → then 콜백함수의 매개변수로 받는다.
promise.then(**function(msg) {
    console.log(msg);  // 2초 뒤에 hello world!
}**);

 

reject 이해하기

let promise = new Promise(function(resolve, **reject**) {

});

// then 인자 둘 다 cb 함수
// 첫 번째는 성공했을 때 실행할 resolve 함수 정의
// 두 번째는 실패했을 때 실행할 reject 함수 정의
promise.then(function() {}, **function() {}**);
let promise = new Promise(function(resolve, reject) {
	setTimeout(function() {
				// 실패한 건 아니지만, 실패했다고 가정하고 reject 호출
				// 보통은 api를 호출하고 응답 에러가 났을 때 reject를 호출하죠.
        **reject('으악!');**
  }, 2000);
});

promise.then(function() {
	console.log('resolve');        // 여기는 실행이 안 되고
}, **function(msg) {
	console.log('reject', msg);    // 여기만 실행됨! "reject 으악!"
}**);

주의

resolve나 reject는 둘 중 무엇이든 한 번만 실행이 됩니다. 그 뒤에 코드는 작동하지 않습니다.

 

Promise Chaining

  • 여러 개의 비동기 작업을 순차적으로 해야 하는 경우가 많다.
  • 순차적으로 각각의 작업이 이전 단계 비동기 작업이 성공하고 나서 그 결괏값을 이용하여 다음 비동기 작업을 실행해야 하는 경우

Promise - state

promise 3가지 상태

  • Promise를 인스턴스화 해서 promise 객체를 얻는다고 했습니다. (let promise = new Promise())
  • promise 객체는 "상태"를 갖고 있습니다.
    • Pending(대기): 비동기 처리 로직이 아직 완료되지 않은 상태
    • Fulfilled(이행): 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
    • Rejected(실패): 비동기 처리가 실패하거나 오류가 발생한 상태

Promise - 에러 처리

에러 처리 - reject

let promise = new Promise(function(resolve, reject) {
	setTimeout(function() {
      reject('으악!');
  }, 2000);
});

promise.then(function() {}, **function(msg) {**
	console.log(msg);
**}**);
  • 두 번째 인자로 에러 처리 로직을 작성하시거나, 아래와 같이 catch함수를 사용할 수 있습니다.

 

에러 처리 - catch

let promise = new Promise(function(resolve, reject) {
	setTimeout(function() {
        reject('으악!');
  }, 2000);
});

promise
	.then(function() {})
	.catch(**function(err) {
		console.log(err);
	}**);
  • catch로 받는 것이 가독성이 더 좋습니다.
  • reject handler와 catch 방식은 똑같습니다.

 

Promise - 마무리

promise.finally()

finally() 메소드는 Promise 객체를 반환합니다. Promise가 처리되면 충족되거나 거부되는지 여부에 관계없이 지정된 콜백 함수가 실행됩니다. 이것은 Promise가 성공적으로 수행되었는지 거절되었는지에 관계없이 Promise가 처리된 후에 코드가 무조건 한 번은 실행되는 것을 제공합니다.

이것은 Promise의 then()과 catch() (en-US) 핸들러에서의 코드 중복을 피하게 합니다.

p.finally(onFinally);

p.finally(function() {
   // settled (fulfilled or rejected)
});

Promise.all()

  • 여러 프로미스를 모두 성공시킨 후, 완료 로직을 실행하고 싶은 경우
    • 9초 뒤에 value의 값이 [1, 2, 3]으로 들어옵니다.
Promise.all([
  new Promise(resolve => setTimeout(() => resolve(1), 9000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
]).then(function(value) {
	console.log(value);
});

 

 

async & await

  • async function은 ES8에 도입되었으며, 비동기 함수를 선언합니다.
  • async function은 promise를 반환하기 때문에 Promise를 잘 알아야 합니다.
  • await를 쓰려면 async 함수 안에 꼭 있어야 합니다!

즉시 실행 함수(Immediately invoked function expression, IIFE)

**(**function () {
	// 내용
}**)()**;

(() => {
	// 내용
})();

 

이벤트 루프

 

이벤트 루프

  • 힙: 힙은 단순히 메모리 영역을 지칭하는 용어. 메모리 할당이 이루어지는 곳으로 변수 등의 정보 저장.
    • (콜 스택의 최상단에 있는 실행 컨텍스트가 실행되면서 참조되는 객체들이 저장되어 있는 메모리 공간)
  • 콜스택: 실행하는 코드를 순서대로 실행하는 곳
    • (실행 컨텍스트가 추가되거나 제거되며 코드의 실행순서를 관리)
  • 콜백큐: 처리할 메시지의 대기열
    • (비동기 함수의 콜백함수 또는 이벤트 핸들러가 일시적으로 대기)

 

콜스택

관련 질문

  • callback 패턴과 문제점은?
  • 답 : 함수에서 받은 매개변수를 이용해서 또 다른 함수로 결과값을 리턴하는 패턴을 가지고 있습니다. 문제점으로는 콜백 함수를 여러번 이용하여서 코드를 작성할 시 결과값이 바뀐 것을 토대로 또다시 다른 콜백함수를 처리해야하기에 콜백함수가 완료된 후 리턴값으로 또다른 콜백함수를 불러와서 매개변수로 이용해야 하므로 가독성이 좋지 않고 유지보수에 어려운 점이 문제점입니다.
  • promise와 callback의 차이점은 무엇이고 각각 장단점은?
  • 답 : promise를 사용하면 비동기 메서드에서 동기 메서드처럼 값을 반환할 수 있습니다. callback과의 차이점은 미래 어떤 시점에 결과를 제공하겠는다는 약속을 반환한다는 점이 차이점이고 callback의 장점은 단순하게 사용할 때에는 간단해서 사용하기 좋고 단점으로는 비동기 함수 간의 의존성 코드가 길어질수록 유지보수, 추가가 어렵다는 단점이 있습니다. promise의 장점으로는 비동기 작업의 수정/추가가 유연하고 코드 유지보수성의 증가가 있습니다. 단점으로는 만약 어딘가에서 에러가 발생되었다고 가정했을 때 어디서 발생된 에러인지를 명확히 확인할 수 없다는 단점이 있습니다.
  • promise란 무엇인가
  • 답 : promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와  그 결과 값을 나타냅니다.
  • Promise.all 은 언제 쓰이는지?
  • 답 : 여러 프로미스의 결과를 집계할 때 유용하게 사용할 수 있습니다. 일반적으로 다음 코드를 계속 실행하기 전에 서로 연관된 비동기 작업 여러 개가 모두 이행되어야 하는 경우에 사용됩니다.
  • async/await와 promise의 차이는?
  • 답 : async/await 에서는 더 이상의. then()을 사용하지 않아도 되고 비동기 처리라고 부르기 어색하게 익숙한 일반적인 코드 구조로 되어 있어 가독성이 좋고 try... catch 문을 사용해 예외처리도 할 수 있습니다. 그리고 promise에서 예외가 발생하면 어디서 발생되었는지 확인할 수 없던 잔 점을 async/await에서는 확인할 수 있게 되었습니다.
  • 이벤트 루프를 설명해보세요.
  • 답 : 초기에 있는 모든 동기 코드들이 이벤트를 처리하는 콜 스택에 쌓여있고 순서대로 Web api에서 제공하는 fetch, setTimeout , document 등 을 거쳐 콜백 큐로 들어가 코드를 실행합니다. 또한 비동기 코드는 동기 코드가 전부 실행 될 동안은 스택에 쌓여있다가 실행되고 난 이후에 콜백큐로 들어가 코드를 실행합니다. 이러한 이벤트를 이벤트 루프라고 합니다.

 

참고자료

https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif

 

✨♻️ JavaScript Visualized: Event Loop

Oh boi the event loop. It’s one of those things that every JavaScript developer has to deal with in o...

dev.to

https://developer.mozilla.org/ko/docs/Learn/JavaScript/Asynchronous/Async_await

 

async와 await를 사용하여 비동기 프로그래밍을 쉽게 만들기 - Web 개발 학습하기 | MDN

Javascript에 대한 최신 추가 사항은 ECMAScript 2017 JavaScript 에디션의 일부인 async functions 그리고 await 키워드는 ECMAScript2017에 추가되었습니다. 이 기능들은 기본적으로 비동기 코드를 쓰고 Promise를

developer.mozilla.org

https://tecoble.techcourse.co.kr/post/2021-08-28-event-loop/

 

이벤트 루프, 넌 누구냐

최근 requestAnimationFrame(이하 rAF)과 setTimeout을 공부하면서 브라우저의 싱글 스레드 동작이 정확히 어떻게 이루어지는지 잘 모른다는 생각이 들었다. 이번 기회에 이벤트 루프의 동작을 공부하고

tecoble.techcourse.co.kr

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise

 

Promise - JavaScript | MDN

Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.

developer.mozilla.org

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
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
글 보관함