[ JS ] - 비동기 2

200원짜리개발자·2024년 6월 18일
0

FrontEnd

목록 보기
27/29
post-thumbnail

네트워크 통신을 위한 fetch 함수

우리가 앞에서 사용했던 fetch함수에 대해서 자세히 알아보고 네트워크 통신을 하기 위해서 알아야 하는 것들을 공부해보자.

fetch("https://api.heropy.dev/v0/users")
	.then((res) => res.json())
	.then((data) => console.log(data))

우리가 fetch로 서버의 주소를 입력하게 되면 서버에 데이터를 가지러 가게 된다.
그 시작지점이 client이고 도착 부분이 서버이다. 그리고 방향에 따라서 요청(Request)/응답(Response)이라고 부른다.

그래서 우리가 웹 브라우저에서 서버로 요청을 하는 것이기에 웹사이트가 클라이언트 인 것이다.

그럼 이제 요청과 응답에 필요한 것들을 알아보자.

요청(Request)

  • url: 요청 서버 주
  • method: 요청 종류(GET, POST, PUT, DELETE 등)
  • headers: 요청 메타 정보 (클라이어트의 환경 정보)
  • body: 요청 데이터(POST, PUT)
    우리는 fetch를 할 때 url만 넣었는데 나머지 정보들을 어떻게 넣을까?
    바로 두 번째 인수인 객체에 넣어주면 된다.
fetch("https://api.heropy.dev/v0/users", {
  method: "GET",
  headers: {},
  body: undefined,
})
  .then((res) => res.json())
  .then((data) => console.log(data));

우리가 원래 주소만 넣어주었던 이유는 나머지 정보를 생략해도 자동으로 값을 넣어주기 때문에 주소만 적어준 것이다.

응답(Response)

  • status: 응답 상태 코드(200, 400, 500 등)
  • headers: 응답 메타 정보
  • body: 응답 데이
  • ok: 정상적인 처리 여부
    이런식의 정보가 들어있다.

CRUD

CRUD는 create, read, update, delete를 합친 단어이다.

  • Create: POST - 데이터 생성
  • Read: GET - 데이터 조회
  • Update: PUT(PATCH) - 데이터 수정
  • Delete: DELETE - 데이터 삭제
    우리가 요청을 할 때, method로 넘길 수 있는 것들이다.

URL 구조

https://www.heropy.dev/p/QOWqjv?key=value&a=12&b=34#h1-title

  • https: 통신 규약(Protocol)
  • www.heropy.dev: 도메인
  • p/QOWqjv: 경로(Path)
  • key=value&a=12&b=34: 쿼리(Query)
  • #h1-title: 해시(hash)

HTTP 상태 코드

  • 1xx: 처리

  • 2xx: 성공

  • 3xx: 리다이랙트

  • 4xx: 클라이언트 오류

  • 5xx: 서버 오류

  • 200: 정상적으로 처리됨

  • 400: 잘못된 요청

  • 401: 인증 정보가 부족

  • 403: 권한이 없음

  • 404: 찾을 수 없음

  • 500: 서버 오류

fetch 함수

  • fetch(url, options)
  • options.method: 요청 종류(GET, POST, PUT, DELETE 등)
  • options.headers: 요청 메타 정보
  • options.body: 요청 데이터
// fetch(url, options)
// options.method: 요청 종류(GET, POST, PUT, DELETE 등)
// options.headers: 요청 메타 정보
// options.body: 요청 데이터
fetch("https://api.heropy.dev/v0/users", {
  method: "POST",
  headers: {
    "Context-Type": "application/json",
  },
  body: JSON.stringify({
    name: "황현민",
    age: 19,
  }),
})
  .then((res) => res.json())
  .then((data) => console.log(data))

이런식으로 사용할 수 있다.

반복문에서 비동기 처리

우리가 반복문에서 비동기 처리할 떄 주의 해야되는 점을 알아보자.

async function getMovies(movieName) {
  const res = await fetch(
    `https://omdbapi.com/?apikey=7035c60c&s=${movieName}`,
  );
  return await res.json();
}
  
const titles = ["frozen", "avengers", "avatar"];
  
// 배열 메소드 반복
titles.forEach(async (title, index) => {
  const movies = await getMovies(title);
  console.log(`${index + 1} ${title}`, movies);
})

이런식의 코드가 존재한다고 하였을 때, 우리는 영화가 순서대로 출력된다고 생각할 수 있다. 하지만 forEach를 돌리면서 영화의 순서가 뒤죽박죽으로 출력이된다.

우리가 배열데이터의 사용하는 콜백을 활용하는 메소드들 map, filter, reduce 등..의 메소드들의 콜백 함수는 배열 아이템의 순서대로 독립적으로 호출되는 개념이기에 하나의 콜백함수가 완료되는 것을 기다리지 않고, 바로 다음 콜백을 실행한다.

즉, 호출은 순서대로 되지만 await로 기다리는 행위는 독립적으로 진행되어 먼저 응답을 받는 쪽이 출력이 되는 것이다. (이전 콜백의 기다림을 다음 콜백이 기다리지 않는다.)
우리가 순서대로 데이터를 받아와야 하는 상황이라면 배열의 콜백을 활용하는 메소드는 사용하면 안된다.

순서를 보장받고 싶다면 간단하게 for반복문을 사용하면 된다.

async function getMovies(movieName) {
  const res = await fetch(
    `https://omdbapi.com/?apikey=7035c60c&s=${movieName}`,
  );
  return await res.json();
}
  
const titles = ["frozen", "avengers", "avatar"];
  
// 배열 메소드 반복
// titles.forEach(async (title, index) => {
//  const movies = await getMovies(title);
//  console.log(`${index + 1} ${title}`, movies);
// });
  
// for 반복문
(async () => {
  let index = 1;
  for (const title of titles) {
    const movies = await getMovies(title);
    console.log(`${index + 1} ${title}`, movies);
    index += 1;
  }
})()

이런식으로 for문을 사용하게 된다면 await키워드를 사용해서 기다리는 것이 가능하다.

profile
고3, 프론트엔드

0개의 댓글