[문제 해결] fetch로 받아온 데이터에 .json() 메서드를 사용하면 undefined로 나타나는 문제

가르송·2023년 3월 21일
0
post-thumbnail

문제 상황

뉴스 기사와 날씨 정보를 받아오는 getNewsAndWeather 함수를 작성하고 있었다.
Promise를 공부하고 있었기 때문에 의도적으로async/await 는 활용하지 않았다. 예상과 달리 이 함수가 의도대로 동작하도록 만드는 데에는 오랜 시간이 걸렸다.

아래의 두 코드는 같은 의사 코드로 작업했으나 서로 다른 결과를 낸다.

1. 의도한대로 동작하지 않는 코드

function getNewsAndWeather() {
  return fetch(newsURL)
    .then(news => {
      return fetch(weatherURL)
        .then(weather => {
          const newsJSON = news.json();
          const weatherJSON = weather.json();
          return { news: newsJSON.data, weather: weatherJSON };
        })
    })
// 실행 결과: { news: undefined, weather: {} }
}

2. 의도한대로 동작하는 코드

function getNewsAndWeather() {
  return fetch(newsURL)
    .then(news => news.json())
    .then(newsJSON => {
      return fetch(weatherURL)
        .then(weather => weather.json())
        .then(weatherJSON => {
          return {
            news: newsJSON.data,
            weather: weatherJSON
          };
        });
    })
  .catch((error) => console.log(error));
}
// 실행 결과: { news: [(뉴스 기사들)], weather: {(날씨 정보)}} }

두 코드 모두 fetch then의 전달 인자인 Response 객체(news data, weather data)에 .json() 메서드를 사용하여 자바스크립트 객체 형태로 바꿔준다. 그런데 왜 1번 코드는 newsJSON, weatherJSON에 아무것도 담기지 않을까?

함수는 작성했으나 이 문제의 원인을 규명하지 않으면 밤에 잠이 오지 않을 것 같았다. 눈에 띄는 차이점은 .json() 메서드를 사용하는 방식이 다르다는 점이었으므로 일단 .json() 메서드의 명세를 확인해 보았다.


문제 해결

결론부터 이야기 하자면 .json 메서드는 프로미스를 리턴하기 때문에 아래와 같이 사용하는 것은 잘못되었다.

function getNewsAndWeather() {
  return fetch(newsURL)
    .then(news => {
      return fetch(weatherURL)
        .then(weather => {
          // 의도와 달리 Promise 객체가 담김
          const newsJSON = news.json();
          const weatherJSON = weather.json();
          return { news: newsJSON.data, weather: weatherJSON };
        })
    })
// 실행 결과: { news: undefined, weather: {} }
}

이유

MDN Fetch API 안내서에 따르면 json()은 응답 본문 텍스트를 JSON으로 파싱한 결과로 이행하는, 또 다른 프로미스를 반환한다.

이 사실은 Response.json() 문서에 더 자세하게 소개되어 있다.

직역하면 json() 메서드는 프로미스를 리턴하며 body text를 JSON 형식으로 parsing한 결과값을 resolve한다. 즉, 의도한대로 resolve된 결과값을 활용하려면 const newsJSON = news.json() 과 같이 작성해선 안 된다.

profile
개발도 운동도 뜻대로 되지 않을 때에는? 산책을 합니다.

0개의 댓글