fetch api와 Promise 비동기 이해하기

하영·2024년 7월 30일
0

JavaScript

목록 보기
19/29
post-thumbnail

개인과제 재제출하면서 최종목표였던 비동기작업..!
맨날 기본 비동기 기본 구문만 가지고 연습하다가 실제로 적용해보려니까 어디서부터 손을 봐야할지 전혀 모르겠어서 울고싶었다 😭

팀 도움을 받아서 끙차 해결하긴했는데 fetch라든가 Promise도 흐름을 파악하지 못하고 외우다시피 쓰는 느낌이라서 조금 더 꼼꼼하게 공부해보았다.


fetch api

api를 받아오고 받아온 데이터를 활용해서 무언가를 만드는 일이 정말 많고 일상이 될 것 같았다. 단순히 외워서 써도 되는데 fetch가 함수인지 뭔지도 모르고 따라 쓰려니까 머리에 들어오지를 않더라..ㅎ
그래서 mdn도 보고 관련 강의도 찾아서 정리했다.


1. fetch api 파악하기

구문

fetch(resource)
fetch(resource, options)

fetch를 사용하기위해 작성하는 구문은 이렇게 쓰면 된다.
resource에는 주로 우리가 데이터를 받아올 api 주소가 들어간다.


실제 활용 예시

fetch("https://jsonplaceholder.typicode.com/posts")
    .then((response) => {
        return response.json(); // 위 주소로 받아온 데이터 타입이 json 이라는 걸 알기 위해 return 값 json으로 처리
    })
    .then((myJson) => { // 우리가 가져온 데이터는 여기에서 알 수 있다.
        console.log(myJson);
    })

(➕ api 주소는 연습할 때 사용하면 좋은 가짜api(?)사이트에서 가져왔다. : https://jsonplaceholder.typicode.com/)


fetch는 함수인데, 이 뒤에 주소를 주고 실행을 하면 파라미터(여기서는 myJson)를 통해 웹서버가 return해준다. 이 데이터들은 json형태인데 자바스크립트 타입에 맞게 컨버팅 해주는 결과를 가져올 수 있게 된다.

따라서 위 내용은 1) fetch 뒤에 있는 url 주소에서 데이터를 가져오면, 2)json타입으로 바꿔주고, 3) 그러고 나서 myJson이라는 파라미터에 전달해줘!가 된다.

놀라운(?) 사실은 ⭐️ 위에서 사용한 .then 메소드는 Promise 형태이다.
.thenPromise를 내뱉기 때문에 배열 메소드를 체이닝해서 썼던 것처럼, 똑같이 Promise 메소드를 체이닝해서 쓸 수 있다.(Promise chaining)


2. fetch method(함수) 뜯어보기

구문

fetch(resource)
fetch(resource, options)

const fetchResponsePromise = fetch(resource[, init])

위에서 본 내용에 조금 더 추가해보았다.
fetch 함수를 실행하면 resource 를 주고 위에서 본 것처럼 여기에 url을 주면 된다.

mdn공식문서에서 보면 위 문구를 확인할 수 있는데 "Response 객체로 이행하는 Promise입니다." 라는 말이다. 즉, fetch 함수는 Promise 데이터 타입을 return 하고, Promise 데이터 타입은 Response Object 타입(객체)을 올려준다.


예시

fetch("https://jsonplaceholder.typicode.com/posts")
    .then((response) => {
        // console.log('response', response.json());
        return response.json();
    })
    .catch((reject) => {
        console.log(reject);
    })
    .then((data) => {
        console.log('data', data); // Promise chaining
    })

코드를 먼저 보도록하자

  1. fetch의 주소는 Promisereturn해서 비동기적으로 처리할 가능성이 높다.
  2. 두 개의 메소드를 사용할 수 있는데 그게 바로 .then, .catch >> 둘다 콜백함수를 받는다.
  3. 둘 다 파라미터를 하나씩 가지고 있다. (resolve, reject)

이 코드를 실행시켜 확인해보면

fetch Promisepending 상태라고 뜨는 걸 보면서 우리는 Promise 데이터를 return 한다는 말을 이해할 수 있다.

이렇게 json타입으로 컨버팅 된 데이터들이 Response 객체 안에 데이터가 담긴걸 확인 할 수 있다.

객체타입으로 데이터가 불러와졌기 때문에 우리는 이를 활용해서 필요한 데이터를 뽑아서 사용할 수 있다.


2. Promise 복습하기

fetch에서 계속 등장한 Promise! 자주 등장했지만 이해도가 부족한 것 같아 정리하면서 다시 공부해보자,,,


예시

function timer(time) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(time);
        }, time);
    });
}

Promise 예시로 너무나 많이 등장하는 setTimeout..🫠
이번에도 역시나 이 함수를 이용해서 timer 라는 함수를 만들었다.
이 함수는 Promise값을 반환하는데 time 이라는 인자에 값을 받아서 그만큼 뒤에 결과를 보여준다.

이제 이 함수를 조금더 간략하게 콜백지옥을 막는 코드로 바꿔보자.


Promise 메소드 사용하기

fetch 정리할 때 말했었는데 Promise를 반환하는 메소드가 2개 있었다. 바로 .then.catch !
이 두 메소드로 Promise chaining 해서 작성하면 아래와 같다.

console.log("START")
timer(1000).then((time) => {
    console.log('time: ' + time);
    // 기존 시간에 1초 더한 만큼 timer 굴리기
    return timer(time + 1000); // promise로 return 하니까 then 이을 수 있음.
}).then((time) => {
    console.log('time: ' + time);
    return timer(time + 1000);
}).then((time) => {
    console.log('time: ' + time);
});
console.log("END")

아까 만든 `timer`의 인자로 1000ms를 부여하고 `.then` 메소드로 콜백함수를 부여했다. 기존 시간에 1초씩 추가한 값을 `return` 하는 단순한 코드이다.

여기에 timer가 실행되기 전에는 start가 콘솔에 찍히고, 끝나면 end 문구가 찍히도록 코드를 추가했다.

✅ 콘솔 확인

띠용용👀
이것은 내가 원한 결과가 아닌디용...
timerPromise니까 비동기적으로 실행된다.
반면에 console.log으로 작성한 start와 end는 비동기로 실행되는 코드가 아니다.

따라서 console.log("START") 가 1번으로 실행되고 -> timer는 비동기 함수니까 일단 실행되는 동안 -> console.log("END") 실행이 된다. -> 그 다음 실행이 완료된 timer가 찍히는 순서이기 때문에 저런 결과가 나온 것이다.

이렇게 수정해주면? 원하는 결과를 얻을 수 있게 된다.


3. async/await 으로 고쳐보기

자 이제 똑같은 코드를 async/await 으로 고쳐보자.
꼭 알아두어야하는 사항 2가지!
1. await은 비동기로 실행되는 것 앞에 붙여주기.
2. awaitasync 안에서만 사용이 가능하므로 function 앞에 async를 써서 만들어주기!

이를 토대로 만든 코드는?!

async function run() {
    console.log("START")
    let time = await timer(1000);
    /* then 안에 있는 첫번째 파라미터를 받아오는 방법, await를 써서 비동기라고 표시*/
    console.log('time: ' + time);
    time = await timer(time + 1000);
    console.log('time: ' + time);
    time = await timer(time + 1000);
    console.log('time: ' + time);
    console.log("END")
}

run(); 
//함수니까 꼭 실행시켜줘야만 결과를 얻을 수 있다!

async/await 로 바꾸기 전에 promise, then을 사용했던 코드에 있던 첫번째 파라미터 time을 받아오는 방법은 let time 으로 지정해서 사용한다.
이렇게 적어주면 2번에서 then 메소드를 썼던 코드와 동일한 결과를 받을 수 있다.



늘 느끼지만 예시코드들은 너무나 이해가 잘 되고 쉽게 느껴진다ㅋㅋㅋ 문제는 실제로 적용해보려고 하거나 조금만 변형된 예시들을 만나면 에러가 뜬다는고지..ㅜ
달리기반 실습에서 비동기 관련 문제들을 풀었는데 그것도 복습하면서 오늘 정리한 내용이랑 같이 TIL로 남겨놓아야겠다!
리액트 들어가기 전까지 비동기 쪼랩 탈출하자🐣



출처
profile
왕쪼랩 탈출 목표자의 코딩 공부기록

0개의 댓글

관련 채용 정보