[자바스크립트] fetch (7)

단일 스레드인 자바스크립트의 비동기 실행 (async - await fetch)
Aug 31, 2024
[자바스크립트] fetch (7)
 

자바스크립트의 동기 실행

아래 코드는 HTML 문서와 함께 JavaScript와 jQuery를 사용하여 동적으로 DOM을 조작하고 서버로부터 데이터를 요청하여 화면에 표시하는 예제이다.
(요즘은 아래의 방법을 쓰지 않고, fetch 를 사용한다. ^^)
notion image
"http://192.168.0.99:8080/test" → 에 5초가 sleep() 걸려있는 상태이다.
자바스크립트의 동기적 특성은 무조건 종료가 되어야 그림을 그리기 시작한다. `<div>그림</div>`
코드 실행 순서는 위에서 밑으로 내려가기 때문에, 일단 밑에까지 읽어져야 한다.
그 전까지는 DOM 을 정리하는 것이다.
let xhr = download(); 가 5초가 걸리니까 밑의 코드도 안읽어지는 것.
그래서 ‘그림’ 이라는 텍스트가 5초동안 그려지지 않는 것이다.
$("#root").append(makeDom()); $("#root").append(makeDom());
notion image
이것이 동기적 요청. (단점: 고장난 것 처럼 보인다. UX 사용자 경험이 안좋음)
 
자바스크립트는 단일 스레드이다. 스레드 하나가 쟤네를 다 실행시키고 끝나는 것.
 
만약 스레드가 두 개라면 오래걸리는 let xhr = download(); 를 다른 스레드로 넘기고,
기존 스레드는 실행, 실행해서 그림 그리면 된다. `<div>그림</div>`
$("#root").append(makeDom()); // 실행 $("#root").append(makeDom()); // 실행
다른 스레드는 기다리고 있겠지. (5초 sleep 장소에서 대기)
→ 자바의 경우, 멀티스레드 기반이라 이렇게 작동
 
하지만 자바스크립트는 단일 스레드라서 그렇게 안된다. TT
비동기로 실행되어야 한다.
 

자바스크립트의 비동기 실행 / fetch

 
위의 코드를 비동기로 실행 하게되면,
notion image
아래 실행하고 `<div>그림</div>`
$("#root").append(makeDom()); // 실행 $("#root").append(makeDom()); // 실행
let xhr = download(); 때리고 자기 볼일 보러 감, 메인으로 하는 자기 할 일 다 끝나고 돌아가면 됨.
실행은 하는데 안기다리고 내려가는 것. 일의 순서가 없다.
그림 다 그렸으면 다시 돌아가서 처리 하는 것.
→ 이 때, fetch 를 쓰면 된다.
 

fetch

fetch 는 JavaScript에서 URL에 HTTP 요청을 보내는 메서드이다.
fetch 메서드는 비동기적으로 서버와의 통신을 처리할 수 있게 해주며, URL을 인자로 받아 해당 URL에 HTTP 요청을 보낸다. fetch 는기본적으로 fetch 는 GET 요청을 보내지만, 옵션을 지정하면 POST, PUT, DELETE 등 다른 메서드로 요청을 보낼 수도 있다.
 
서버는 강사님이 깃헙에 올려주신 서버로 실행하자.
notion image
notion image
 

async - await fetch 사용

 
fetch는 무겁다. IO 가 일어난다. (입출력은 오래 걸린다. cpu 가 하는게 아니면 오래 걸림)
오래 걸리는 작업들은 fetch 를 사용하면(5초든.. 몇 초든.. 시간이 걸리는 작업들),
promise 라는 객체를 준다.(어음을 줌) (F12 누르면 확인 할 수 있다. console.log(response);)
어음은 실제 값이 아니기 때문에, response 를 실제 값으로 받을 수 있게 await 를 걸어주어야 한다.
 
await 붙으면 동기가 되기 때문에 5초 있다가 값이 들어온다.
notion image
response 는 리얼 값임.
 
원래는 fetch 를 붙이면 promise 를 준다.
우리는 await 를 걸어, promise 를 안주고 리얼 값을 준다. 근데 리얼 값은 5초를 기다렸다 줄거야.
5초 뒤에 json 으로 파싱한다.
let data = await response.json(); // json 으로 파싱 이것은 문법 -> 자바스크립트로 바뀜
그림 그리는 시간까지 6초.
async 를 걸면 비동기 함수가 된다. (async 와 await 는 한 세트)
notion image
 
notion image
그림 그리고
그림 그리고
download(); 호출했을 때, → 얘는 비동기 함수구나 하고 fetch 때리면 pending 상태가 됨
원래 함수는 종료되어야 도망 나갈 수 있음. 끝까지 다 실행되어야 한다.
근데 비동기 함수는 아님, await fetch 를 체크포인트로 잡고 함수를 그냥 빠져나가버린다. → 비동기함수
cpu 는 도망나와서 실행한다.
`<div>그림</div>` 실행
`<div>그림</div>` 실행
`<div>그림</div>` 실행
cpu 할 일 없으니 await 로 다시 돌아간다.
통신이 끝나면 파싱하고 슥
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> </head> <body> <div id="root"> </div> <script> function makeDom() { return `<div>그림</div>`; } async function download() { // 비동기로 실행되어야 함 let response = await fetch("http://192.168.0.99:8080/test"); // fetch 는 기본적으로 비동기 함수라 먼저 때림 ㄱ let body = await response.json(); // 기다렸다가 줄거야, await 붙으면 동기적이거든 $("#root").append(`<div>${body}</div>`); } $("#root").append(makeDom()); $("#root").append(makeDom()); download(); $("#root").append(makeDom()); </script> </body> </html>
시간이 지난 후에 응답데이터 [object Object] 가 뜬다.
notion image
 
전체 코드는 비동기적으로 진행되고,
함수 내부 코드 블락만 동기적으로 실행된다.
notion image
(다시 설명)
await 걸린 await fetch 줄을 21번 메모장에 적어 놓는다.
원래 stack 이 종료되면 지역변수가 다 날라가지만,
이 경우에는 stack 이 메모리에 살아있다. 지역변수가 죽지 않는다.
stack 이 살아있는 상황에서 cpu 가 도망 나온다.
21번 라인으로 돌아가서 체크해야지~ 하고 cpu 가 이벤트루프로 가서 다시 봐야징~ 하고 간다.
OS 의 cpu 가 다됐나~ 하고 다른 일 들어오면 그 일 하러 가고~
cpu 가 풀파워로 체킹하고 있는게 아니라서 다른 일 하고~
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> </head> <body> <div id="root"> </div> <script> function makeDom() { return `<div>그림</div>`; } async function download() { // 비동기로 실행되어야 함 // 함수 내부 코드 블락은 동기적이다. let response = await fetch("http://192.168.0.99:8080/test"); // fetch 는 기본적으로 비동기 함수라 먼저 때림 ㄱ let data = await response.json(); // 기다렸다가 줄거야, await 붙으면 동기적이거든 // json 으로 파싱 이것은 문법 -> 자바스크립트로 바뀜 $("#root").append(`<div>${data.body}</div>`); } $("#root").append(makeDom()); // 전체코드는 비동기적으로 진행됨 $("#root").append(makeDom()); // 함수 내부 코드블락만 동기적 download(); $("#root").append(makeDom()); </script> </body> </html>
notion image
 
Share article

eunmouse