728x90
0. 프로미스
- 자바스크립트는 비동기 처리를 위한 패턴으로 콜백 함수 사용
- 전통적인 콜백 패턴은 콜백 헬로 인해 가독성이 나쁘고 비동기 처리중 발생한 에러의 처리가 곤란해 여러개의 비동기처리를 한번에 처리하는데 한계가 있음
- ES6에서 비동기 처리 위한 패턴으로 프로미스 도입
- 전통적인 콜백 패턴이 가진 단점 보완
- 비동기 처리 시점을 명확하게 표현 가능
1. 비동기 처리 위한 콜백 패턴의 단점
a. 콜백 헬
콜백 헬
- 콜백 헬 : 콜백 함수를 통해 비동기 처리 결과에 대한 후속 처리를 수행하는 비동기 함수가 비동기 처리 결과를 가지고 또다시 비동기 함수를 호출해야한다면 콜백 함수 호출이 중첩되어 복잡도 높아지는 현상
- 콜백헬 은 가독성 나쁘게 하며 실수 유발하는 원인
비동기 함수
- 비동기 함수 : 함수 내부에 비동기로 동작하는 코드를 포함한 함수
- 비동기 함수를 호출하면 함수 내부의 비동기로 동작하는 코드가 완료되지 않았다 해도 기다리지 않고 즉시 종료
- 비동기 함수 내부의 비동기로 동작하는 코드는 비동기 함수가 종료된 이후 완료
- 비동기 함수 내부의 비동기로 동작하는 코드에서 처리 결과를 외부로 반환하거나 상위 스코프의 변수에 할당하면 기대한 대로 동작하지 않음
setTimeout 함수는 비동기 함수
- setTimeout 함수가 비동기 함수인 이유 : 콜백 함수의 호출이 비동기로 동작하기 때문
- setTimeout 함수를 호출하면 콜백 함수를 호출 스케줄링한 다음, 타이머 id 반환 후 즉시 종료
- 비동기 함수인 setTimeout 함수의 콜백 함수는 setTimeout 함수가 종료된 이후 호출
- => setTimeout 함수 내부의 콜백 함수에서 처리 결과를 외부로 반환하거나 상위 스코프의 변수에 할당하면 기대한대로 동작하지 않음
- setTimeout 함수의 콜백 함수에서 상위 스코프의 변수에 값을 할당하면
- setTimeout 함수는 생성된 타이머를 식별할 수 있는 고유한 타이머 id 를 반환하므로 콜백 함수에서 값 반환하는 것은 무의미
get 함수가 서버의 응답 결과를 반환하게 하려면?
- get 함수가 비동기 함수인 이유 : get 함수 내부의 onload 이벤트 핸들러가 비동기로 동작하기 때문
- get 함수 호출하면 XMLHttpRequest 객체를 생성하고 HTTP 요청을 초기화한 후 HTTP GET 요청을 전송하고 onload 이벤트 핸들러를 등록한 다음 Undefined 반환하고 즉시 종료
- 비동기 함수인 get 함수 내부의 onload 이벤트 핸들러는 get 함수가 종료된 이후 실행
- get 함수의 onload 이벤트 핸들러에서 서버의 응답 결과를 반환하거나 상위 스코프의 변수에 할당하면 기대한 대로 동작하지 않음
- 비동기 함수의 반환값은 캐치할 수 없음
- xhr.onload 이벤트 핸들러 프로퍼티에 바인딩한 이벤트 핸들러의 반환문은 get 함수의 반환문이 아님
- get 함수는 반환문이 생략되었으므로 이미 암묵적으로 undefined 반환되었음
- 함수의 반환값은 명시적으로 호출한 다음 캐치 가능하므로 onload 이벤트 핸들러를 get 함수가 호출할 수 있다면 이벤트 핸들러의 반환값을 get 함수가 캐치해 다시 반환할 수도 있겠지만 onload 이벤트 핸들러는 get 함수가 호출하지 않기 때문에 그럴 수 없음
- => onload 이벤트 핸들러의 반환값은 캐치할 수 없음
- xhr.onload 이벤트 핸들러에서 서버의 응답을 상위 스코프의 변수에 할당하면 처리 순서가 보장되지 않음
- 비동기 함수 get이 호출되면 함수 코드를 평가하는 과정에서 get 함수의 실행 컨텍스트가 생성되고 실행 컨텍스트 스택(콜 스택)에 푸시
- 함수 코드 실행 과정에서 xhr.onload 이벤트 핸들러 프로퍼티에 이벤트 핸들러 바인딩
- get 함수 종료시 get 함수의 실행 컨텍스트가 콜 스택에서 팝 되고 곧바로 console.log 호출
- 이때 console.log의 실행 컨텍스트가 생성되어 실행 컨텍스트 스택에 푸시
- 만약 console.log가 호출되기 직전에 load 이벤트가 발생했더라도 xhr.onload 이벤트 핸들러 프로퍼티에 바인딩한 이벤트 핸들러는 xhr.onload 보다 먼저 실행되지 않음
- 서버로부터 응답이 도착하면 xhr 객체에서 load 이벤트 발생
- 이때 xhr.onload 핸들러 프로퍼티에 바인딩한 이벤트 핸들러가 즉시 실행되는 것은 아님
- xhr.onload 이벤트 핸들러는 load 이벤트가 발생하면 일단 태스크 큐에 저장되어 대기하다가 콜 스택이 비면 이벤트 루프에 의해 콜 스택으로 푸시되어 실행
- 이벤트 핸들러도 함수이므로 이벤트 핸들러의 평가-> 실행 컨텍스트 생성 -> 콜 스택에 푸시 -> 이벤트 핸들러 실행 과정을 거침
- => xhr.onload 이벤트 핸들러가 실행되는 시점에는 콜 스택이 빈 상태여야하므로 console.log는 이미 종료된 이후
- 만약 get 함수 이후에 console.log가 100번 호출된다해도 모든 console.log 종료 이후 xhr.onload 실행
- xhr.onload 이벤트 핸들러에서 상위 스코프의 변수에 서버의 응답 결과를 할당하기 이전에 console.log가 먼저 호출되어 undefined 출력
비동기함수의 결론
- 비동기 함수는 비동기 처리 결과를 외부에 반환할 수 없고 상위 스코프의 변수에 할당할 수도 없음
- 비동기 함수의 처리 결과(서버의 응답 등)에 대한 후속 처리는 비동기 함수 내부에서 수행해야함
- 비동기 함수를 범용적으로 사용하기 위해 비동기 함수에 비동기 처리 결과에 대한 후속 처리를 수행하는 콜백 함수를 전달하는 것이 일반적
- 필요에 따라 비동기 처리가 성공하면 호출될 콜백 함수와 비동기 처리가 실해하면 호출될 콜백 함수 전달 가능
b. 에러처리의 한계
- 비동기 처리를 위한 콜백 패턴의 문제점 중에서 가장 심각한 것은 에러 처리가 곤란하다는 것
- try 코드 블록 내에서 호출한 setTimeout 함수는 1초 후에 콜백함수가 실행되도록 타이머 설정하고 이후 콜백함수는 에러 발생
- 하지만 이 에러는 catch 코드 블록에서 캐치 되지 않음
- 비동기 함수인 setTimeout 호출 되면 setTimeout 함수의 실행 컨텍스트가 생성되어 콜 스택에 푸시되어 실행
- setTimeout은 비동기 함수라서 콜백 함수가 호출되는 것을 기다리지 않고 즉시 종료되어 콜 스택에서 제서
- 이후 타이머가 만료되면 setTimeout 함수의 콜백 함수는 태스크 큐로 푸시되고 콜 스택이 비어졌을 때 이벤트 루프에 의해 콜 스택으로 푸시되어 실행
- setTimeout 함수의 콜백 함수가 실행될 때 setTimeout 함수는 이미 콜 스택에서 제거된 상태
- setTimeout 함수의 콜백 함수를 호출한 것이 setTimeout 함수가 아니라는 것을 의미
- setTimeout 함수의 콜백 함수의 호출자가 setTimeout 함수라면 콜 스택의 현재 실행중인 실행 컨텍스트가 콜백 함수의 실행 컨텍스트일 때 현재 실행중인 실행 컨텍스트의 하위 실행 컨텍스트가 setTimeout 함수여야함
- 에러는 호출자 방향으로 전파
- 콜 스택의 아래 방향(실행중인 실행 컨텍스트의 이전 실행 컨텍스트)으로 전파
- setTimeout 함수의 콜백함수를 호출한 것은 setTimeout 함수가 아니라서 catch 블록에서 캐치되지 않음
try...catch...finally문
- try...catch...finally문 : 에러 처리를 구현하는 방법
- try...catch...finally문을 실행하면 먼저 try 코드 블록 실행
- try 코드 블록에 포함된 문 중에서 에러가 발생하면 해당 에러는 catch문의 err 변수에 전달되고 catch 코드 블록 실행
- finally 코드 블록은 에러 발생과 상관없이 반드시 한번 실행
- try...catch...finally문으로 에러 처리하면 프로그램이 강제 종료되지 않음
2. 프로미스의 생성
- ES6에서 도입된 Promise는 호스트 객체가 아닌 ECMAScript 사양에 정의된 표준 빌트인 객체
- Promise 생성자 함수를 new 연산자와 함께 호출하면 프로미스(Promise 객체) 생성
- Promise 생성자 함수는 비동기 처리를 수행할 콜백 함수(ECMAScript 사양에서는 executor 함수)를 인수로 전달받는데 이 콜백함수는 resolve와 reject 함수를 인수로 전달받음
- Promise 생성자 함수가 인수로 전달받은 콜백 함수 내부에서 비동기 처리 수행
- 비동기 처리 성공 시 콜백 함수의 인수로 전달받은 resolve 함수 호출
- 비동기 처리 실패 시 reject 함수 호출
프로미스는 현재 비동기 처리가 어떻게 진행되고 있는지를 나타내는 상태 정보를 가짐
생성된 직후의 프로미스는 기본적으로 pending 상태
- 이후 비동기 처리가 수행되면 비동기 처리 결과에 따라 프로미스 상태 변화
- 비동기 처리 성공 : resolve 함수를 호출해 프로미스를 fulfilled 상태로 변경
- 비동기 처리 실패 : reject 함수를 호출해 프로미스를 rejected 상태로 변경
- 프로미스 상태는 resolve 또는 reject 함수를 호출하는것으로 결정됨
fulfilled 또는 rejected 상태를 settled 상태라고 함
- settled 상태 : fulfilled/rejected상태와 상관없이 pending 이 아닌 상태로 비동기 처리가 수행된 상태
- 프로미스는 pending 상태에서 fulfilled 또는 rejected 상태, 즉 settled 상태로 변화 가능
- 하지만 일단 settled 상태가 되면 더는 다른 상태로 변화 불가능
- 프로미스는 비동기 처리 상태와 더불어 비동기 처리결과도 상태로 가짐
- 비동기 처리가 성공하면 프로미스는 pending 상태에서 fulfilled 상태로 변화하고 비동기 처리 결과인 값을 가짐
- 비동기 처리가 실패하면 프로미스는 pending 상태에서 rejected 상태로 변화
- 비동기 처리결과인 Error 객체를 값으로 가짐
- 프로미스는 비동기 처리상태와 처리 결과를 관리하는 객체
3. 프로미스의 후속 처리 메서드
- 프로미스의 비동기 처리 상태가 변화하면 이에 따른 후속처리를 해야함
- 프로미스가 fulfilled 상태가 되면 프로미스의 처리 결과를 가지고 무언가를 해야하고
- 프로미스가 rejected 상태가 되면 프로미스의 처리결과(에러)를 가지고 에러 처리를 해야함
- 이를 위해 프로미스는 후속 메서드 then, catch, finally 제공
- 프로미스의 비동기 처리 상태가 변화하면 후속 처리 메서드에 인수로 전달한 콜백 함수가 선택적으로 호출됨
- 이때 후속 처리 메서드의 콜백 함수에 프로미스의 처리 결과가 인수로 전달됨
- 모든 후속 처리 메서드는 프로미스를 반환하며 비동기로 동작
a. Promise.prototype.then
- then 메서드는 두개의 콜백 함수를 인수로 전달 받음
- 첫번째 콜백 함수는 프로미스가 fulfilled 상태(resolve 함수가 호출된 상태)가 되면 호출됨
- 비동기 처리가 성공했을 때 호출되는 성공 처리 콜백 함수
- 이때 콜백 함수는 프로미스의 비동기 처리 결과를 인수로 전달 받음
- 두번째 콜백 함수는 프로미스가 rejected 상태(rejected 함수가 호출된 상태)가 되면 호출됨
- 비동기 처리가 실패했을 때 호출되는 실패 처리 콜백 함수
- 콜백 함수는 프로미스의 에러를 인수로 전달 받음
- 첫번째 콜백 함수는 프로미스가 fulfilled 상태(resolve 함수가 호출된 상태)가 되면 호출됨
- then 메서드는 언제나 프로미스를 반환
- 만약 then 메서드의 콜백함수가 프로미스를 반환하면 그 프로미스를 그대로 반환하고 콜백 함수가 프로미스가 아닌 값을 반환하면 그 값을 암묵적으로 resolve 또는 reject 하여 프로미스를 생성해 반환
b. Promise.prototype.catch
- catch 메서드는 한개의 콜백함수를 인수로 전달받음
- catch 메서드의 콜백 함수는 프로미스가 rejected 상태인 경우만 호출
- catch 메서드는 then(undefined, onRejected)과 동일하게 동작 => 언제나 프로미스 반환
c. Promise.prototype.finally
- finally 메서드는 한개의 콜백 함수를 인수로 전달 받음
- finally 메서드의 콜백 함수는 프로미스의 성공(fulfilled) 또는 실패(rejected)와 상관없이 무조건 한번 호출됨
- finally 메서드는 프로미스의 상태와 상관없이 공통적으로 수행해야할 처리 내용이 있을 때 유용
- 언제나 프로미스 반환
4. 프로미스의 에러 처리
- 비동기 처리를 위한 콜백 패턴은 에러 처리가 곤란한데 프로미스는 에러를 문제없이 처리 가능
- 비동기 처리 결과에 대한 후속 처리 : 프로미스가 제공하는 수속 처리 메서드 then, catch, finally 사용해 수행
- 비동기 처리에서 발생한 에러
- then 메서드의 두번째 콜백 함수로 처리 가능
- 프로미스의 후속 처리 메서드 catch 사용해 처리 가능
catch 메서드
- catch 메서드 호출 시 내부적으로 then(undefined, onRejected) 호출
- 단, then 메서드의 두번째 콜백 함수는 첫번째 콜백 함수에서 발생한 에러를 캐치하지 못하고 코드가 복잡해져 가독성이 별로임
- catch 메서드를 모든 then 메서드를 호출한 이후에 호출하면 비동기 처리에서 발생한 에러(rejected)뿐만 아니라 then 메서드 내부에서 발생한 에러까지 모두 캐치 가능
5. 프로미스 체이닝
- 비동기 처리를 위한 콜백 패턴은 콜백 헬이 발생하는 문제가 있음
- 프로미스는 then, catch, finally 후속 처리 메서드를 통해 콜백 헬 해결
- then-> then-> catch 순서로 후속 처리 메서드 호출
- 프로미스 체이닝 : then, catch, finally 후속 처리 메서드는 언제나 프로미스를 반환하므로 연속 호출 가능
- 후속 처리 메서드의 콜백 함수는 프로미스의 비동기 처리 상태가 변경되면 선택적으로 호출됨
- 후속처리 메서드의 콜백 함수는 인수를 전달받으면서 호출됨
- 후속 처리 메서드의 콜백 함수가 프로미스가 아닌 값을 반환하더라도 그 값을 암묵적으로 resolve 또는 reject 하여 프로미스 생성해 반환
- 프로미스는 프로미스 체이닝을 통해 비동기 처리 결과를 전달받아 후속 처리를 하므로 비동기 처리를 위한 콜백 패턴에서 발생하던 콜백 헬이 발생하지 않음
- 프로미스도 콜백 패턴을 사용하므로 콜백 함수를 사용하지 않는 것은 아님
async/await
- async/await를 사용하면 프로미스의 후속 처리 메서드 없이 마치 동기 처리처럼 프로미스가 처리 결과를 반환하도록 구현
- async/await 도 프로미스를 기반으로 동작하므로 프로미스는 잘 이해하고 있어야함
6. 프로미스의 정적 메서드
- Promise 주로 생성자 함수로 사용되지만 함수도 객체이므로 메서드를 가질 수 있음
- Promise는 5가지 정적 메서드 제공
a. Promise.resolve / Promise.reject
- Promise.resolve와 Promise.reject 메서드는 이미 존재하는 값을 래핑하여 프로미스를 생성하기 위해 사용
Promise.resolve 메서드
- Promise.resolve 메서드는 인수로 전달받은 값을 resolve 하는 프로미스 생성
Promise.reject 메서드
- Promise.reject 메서드는 인수로 전달받은 값을 reject 하는 프로미스 생성
b. Promise.all
- Promise는 세개의 비동기 처리를 순차적으로 처리
- 앞선 비동기 처리가 완료하면 다음 비동기 처리 수행
- 세개의 비동기 처리는 서로 의존하지 않고 개별 수행
- => 앞선 비동기 처리 결과를 다음 비동기 처리가 사용하지 않음
- => 세 개의 비동기 처리를 순차적으로 처리할 필요 없음
- 예시에서는 각각의 처리가 이루어져 6초 이상 소요
- Promise.all 메서드 : 여러개의 비동기 처리를 모두 병렬 처리할 때 사용
- Promise.all 메서드는 프로미스를 요소로 갖는 배열 등의 이터러블을 인수로 전달
- 전달받은 모든 프로미스가 모두 fulfilled 상태가 되면 모든 처리 결과를 배열에 저장해 새로운 프로미스 반환
- 첫번째 프로미스는 3초 후에 1을 resolve
- 두번째 프로미스는 2초 후에 2을 resolve
- 세번째 프로미스는 1초 후에 3을 resolve
- Promise.all 메서드는 인수로 전달받은 배열의 모든 프로미스가 모두 fulfilled 상태가 되면 종료
- Promise.all 메서드가 종료하는데 걸리는 시간은 가장 늦게 fulfilled 상태가 되는 프로미스 처리 시간보다 조금 더 김
- 모든 처리에 걸리는 시간은 가장 fulfilled 상태가 되는 첫번째 프로미스의 처리시간인 3초보다 조금 더 소요됨
- 모든 프로미스가 fulfilled 상태가 되면 resolve된 처리 결과를 모두 배열에 저장해 새로운 프로미스를 반환
- 첫번째 프로미스가 가장 나중에 fulfilled 상태가 되어도 Promise.all 메서드는 첫번째 프로미스가 resolve한 처리결과부터 차례대로 배열에 저장해 그 배열을 resolve 하는 새로운 프로미스 반환 => 처리 순서 보장
- Promise.all 메서드는 인수로 전달받은 배열의 프로미스가 하나라도 rejected 상태가 되면 나머지 프로미스가 fulfilled 상태가 되는 것을 기다리지 않고 즉시 종료
- 세번째 프로미스가 가장 먼저 rejected 상태가 되므로 세번째 프로미스가 reject한 에러가 catch 메서드로 전달
- Promise.all 메서드는 인수로 전달받은 이터러블의 요소가 프로미스가 아닌 경우 Promise.resolve 메서드를 통해 프로미스로 래핑
- Promise.all 메서드는 promiseGet 함수가 반환한 3개의 프로미스로 이루어진 배열을 인수로 전달받고 이 프로미스들이 모두 fulfilled 상태가 되면 처리 결과를 배열에 저장해 새로운 프로미스 반환
- Promise.all 메서드가 반환한 프로미스는 세개의 사용자 객체로 이뤄진 배열 담고 있고 이 배열은 첫번째 then 메서드에 인수로 전달
c. Promise.race
- Promise.race 메서드는 프로미스를 요소로 갖는 배열 등의 이터러블을 인수로 전달 받음
- Promise.race 메서드는 모든 프로미스가 fulfilled 상태가 되는 것을 기다리는 것이 아니라 가장 먼저 fulfilled 상태가 된 프로미스의 처리 결과를 resolve 하는 새로운 프로미스 반환
- 프로미스가 rejected 상태가 되면 Promise.race 메서드에 전달된 프로미스가 하나라도 rejected 상태가 되면 에러를 reject 하는 새로운 프로미스를 즉시 반환
d. Promise.allSettled
- ES11에 도입된 Promise.allSettled 메서드는 프로미스를 요소로 갖는 배열 등의 이터러블을 인수로 전달받음
- 전달받은 프로미스가 모두 setteld 상태(비동기 처리가 수행된 상태, fulfilled, rejected 상태)가 되면 처리결과를 배열로 반환
- Promise.allSettled 메서드가 반환한 배열에는 fulfilled, rejected 상태와는 상관없이 Promise.allSettled 메서드가 인수로 전달받은 모든 프로미스들의 처리 결과가 모두 담겨 있음
- 프로미스 처리 결과를 나타내는 객체
- 프로미스가 fulfilled 상태인 경우 : 비동기 처리 상태를 나타내는 status 프로퍼티와 처리 결과를 나타내는 value 프로퍼티 가짐
- 프로미스가 rejected 상태인 경우 : 비동기 처리 상태를 나타내는 status 프로퍼티와 에러를 나타내는 reason 프로퍼티 가짐
7. 마이크로태스크 큐
- 프로미스의 후속 처리 메서드도 비동기로 동작하므로 1->2->3->순으로 출력될 것 처럼 보이지만 2->3->1 순으로 출력됨
- 프로미스의 후속 처리 메서드의 콜백 함수는 태스크큐가 아니라 마이크로태스크 큐에 저장되기 때문
- 마이크로태스크 큐는 태스크 큐와는 별도의 큐
- 마이크로 태스크 큐에는 프로미스의 후속 처리 메서드의 콜백 함수가 일시 저장됨
- 그 외의 비동기 함수의 콜백함수나 이벤트 핸드러는 태스크 큐에 일시 저장됨
- 콜백 함수나 이벤트 핸들러를 일시 저장한다는 점에서 태스크큐와 동일하지만 마이크로 태스크 큐는 태스크 큐보다 우선순위가 높음
- 이벤트 루프는 콜 스택이 비면 먼저 마이크로 태스크 큐에서 대기하고 있는 함수 가져와 실행
- 이후 마이크로태스크 큐가 비면 태스크 큐에서 대기하고 있는 함수 가져와 실행
8.fetch
- fetch 함수 : XMLHttpRequest 객체와 마찬가지로 HTTP 요청 전송 기능을 제공하는 클라이언트 사이드 Web API
- fetch 함수는 XMLHttpRequest 객체보다 사용법이 간단하고 프로미스 지원하기 때문에 비동기 처리를 위한 콜백 패턴 단점에서 자유로움
- fetch 함수에는 HTTP 요청 전송할 URL과 HTTP 요청 메서드, HTTP 요청 헤더, 페이로드 등을 설정한 객체 전달
fetch 함수는 HTTP 응답을 나타내는 Response 객체를 래핑한 Promise 객체 반환
- fetch 함수는 후속 처리 메서드 then을 통해 프로미스가 resolve한 Response 객체 전달 받을 수 잇음
- Response 객체는 HTTP 응답을 나타내는 다양한 프로퍼티 제공
- Response.prototype에는 Response 객체에 포함되어 있는 HTTP 응답 몸체를 위한 다양한 메서드 제공
- 예를 들어 fetch 함수가 반환한 프로미스가 래핑하고 있는 MIME 타입이 application/json인 HTTP 응답 몸체를 취득하려면 Response.prototype.json 메서드 사용
- Response.prototype.json 메서드는 Response객체에서 HTTP 응답 몸체를 취득해 역직렬화
fetch 함수 사용 시 에러 처리에 주의
- 부적절한 URL 지정 시 404 Not Found 에러 발생하고 catch 후속 처리 메서드에 의해 error 출력될 것 처럼 보이지만 ok 출력
- fetch 함수를 반환하는 프로미스는 기본적으로 404 Not Found, 500 Internal Server Error 와 같은 HTTP 에러가 발생해도 에러를 reject 하지 않고 불리언 타입의 ok 상태를 false로 설정한 Response 객체 resolve
- 오프라인 등의 네트워크 장애나 CORS 에러에 의해 요청이 완료되지 못한 경우에만 프로미스 reject
- fetch 함수 사용 시 fetch 함수가 반환한 프로미스가 resolve한 불리언 타입의 ok 상태 확인해 명시적으로 에러 처리할 필요 있음
axios
- axios는 모든 HTTP 에러를 reject하는 프로미스 반환
- 모든 에러를 catch에서 처리할 수 있어 편리
- 인터셉터, 요청 설정 등 fetch보다 다양한 기능 지원
a. GET 요청
b. POST 요청
c. PATCH 요청
d. DELETE 요청
모던 자바스크립트 딥다이브 책을 정리한 내용입니다!!
728x90
'개념 정리 > 모던 자바스크립트 딥다이브' 카테고리의 다른 글
모던 자바스크립트 : 에러처리 (0) | 2023.12.16 |
---|---|
모던 자바스크립트 : 이벤트 (0) | 2023.12.14 |
모던 자바스크립트 : REST API (1) | 2023.12.11 |
모던 자바스크립트 : Ajax (0) | 2023.12.08 |
모던 자바스크립트 : 타이머 (0) | 2023.12.07 |