await

jingjinge·2025년 1월 12일

ASAC_07

목록 보기
11/13
post-thumbnail

API 테스트를 하던 중 의문이 생겼다.

전체 코드


import { useState } from 'react'

export default function GetTest2() {
    const [users, setUsers] = useState([])

    async function onClickHandler() {
        try {
            const result = await fetch('http://localhost:3001/api/users')
            if (!result.ok) throw new Error(result.statusText)
          /*----------의문점----------*/
            setUsers(await result.json())
          /*----------의문점----------*/
        } catch {
            console.log('에러에용~')
        }
    }
    return (
        <div>
            <div style={{ fontSize: 25 }}>GetTest</div>
            <hr />
            <button onClick={onClickHandler}>눌러주세용</button>
            <ul>
                {users.map((user) => (
                    <li key={user.id}>{`${user.name}, ${user.email}`}</li>
                ))}
            </ul>
        </div>
    )
}

지식이 짧아, await은 Promise 객체를 풀어준다 정도로 알고 있었다.
근데 응답값을 쓰려면 body값을 그냥 쓰면 되지 왜 await을 다시 써주는걸까?

하나씩 console.log를 통해 분석해보겠다


console.log(fetch('http://localhost:3001/api/users')) /*Promise*/ 
console.log(await fetch('http://localhost:3001/api/users')) /*Response*/ 
console.log(result.json()) /*Promise*/ 
console.log(await result.json()) /*Response.body*/ 

fetch

console.log(fetch('http://localhost:3001/api/users')) 

  • Promise Object
    • Prototype Object : Method
    • PromiseState : resolve, reject에 따른 값
    • PromiseResult

반환된 구조는 위와 같다. 그중 우리가 사용해야할 부분은 PromiseResult 인 것 같다.


await

console.log(await fetch('http://localhost:3001/api/users')) /*Response*/ 

Response 객체 속성

  • body: API에서 보낸 값이 들어있음. 바로 읽으려면 .json(), .text() 같은 메서드 써야 함.
  • bodyUsed: body가 이미 소비됐는지 확인. (true or false)
  • headers: 응답 헤더 정보 담고 있음. (response.headers.get('Content-Type'))
  • ok: 요청 성공 여부 (status가 200~299면 true)
  • redirected: 요청 리디렉션됐는지 확인 (true or false)
  • status: HTTP 응답 상태 코드
  • statusText: 응답 상태 텍스트 (예: OK, Not Found)
  • type: 응답 유형 (예: basic, cors, error, opaque)
  • url: 요청한 URL

Prototype에 들어있는 메서드

  • .json(): body를 JSON 형식으로 변환
  • .text(): body를 텍스트로 변환
  • .blob(): body를 Blob 형식으로 변환
  • .arrayBuffer(): body를 ArrayBuffer로 변환
  • .formData(): body를 FormData로 변환

PromiseResult의 값이 그대로 들어 있다

이런 식으로 구성이 된다.


.json()

console.log(result.json()) /*Promise*/

Promise Object임을 확인할 수 있다.

await이 PromiseResult를 따로 반환하는건데, PromiseResult에 우리가 원하는 값이 들어 있는 것을 볼 수 있다.

json() Method는 아래와 같은 역할을 하는 것이구나를 알 수 있는 대목이다.

json() 메서드는 HTTP 응답(Response)의 본문(body)을 JSON 객체로 변환하는 역할을 한다는 것을 알 수 있다.
response.json()은 Promise를 반환하며, 이는 응답 본문을 JSON으로 파싱한 결과를 제공한다.


await

console.log(result.json()) /*Promise*/

Array안에 우리가 원하는 Response.body의 값이 들어 있는 것을 알 수가 있었다.

결론

fetchResponse.json()비동기 작업스트림 처리라는 이유로 이런 구조로 만들어짐


비동기 작업 처리

  • fetch()는 네트워크 요청 결과를 바로 반환하지 않고, Promise를 반환

    • 요청이 완료될 때까지 기다리느라 코드 실행이 멈추지 않도록 하기 위함
      • 따라서 await을 사용해야 응답(Response) 값을 사용할 수 있음
  • Response.json()도 같은 원리

    • 응답의 body 데이터는 스트림 형태로 전달, 데이터를 한 번에 모두 가져올 수 없음
      • json() 메서드는 이 스트림 데이터를 비동기로 읽어서 JSON으로 변환하기 때문에 Promise를 반환

.json()이 Promise로 반환되는 이유

  • HTTP 응답 body스트림으로 전달되며, 데이터가 모두 준비되기 전까지 작업을 처리할 수 없음

    • 데이터를 비동기로 읽어와 JSON으로 변환해야 하므로 Promise로 반환
  • 네트워크 상황에 따라 데이터 준비 시간이 달라지기 때문에 동기 처리 방식으로는 안정성을 보장할 수 없음

    • Promise를 사용하면 안정적이고 효율적으로 데이터 변환 가능

결론적으로 await은 Promise 객체의 PromiseResult 값을 반환해준다!

0개의 댓글