본문 바로가기
  • soldonii's devlog
Javascript 공부/TIL

200130(목) : Fetch API

by soldonii 2020. 1. 30.

이번주는 바닐라코딩 break week이고, 다음 주부터 3주간 리액트를 배우기에 복습 차원에서 리액트로 아주 간단한 앱을 미니 프로젝트로 살짝 만들어보려고 했다. 그런데 처음부터 난관에 부딪혔다;; componentDidMount() 메소드 내부에서 fetch를 이용해서 원하는 데이터를 요청하고 받아와서 state에 저장하려고 했는데, 아래와 같은 에러가 계속 떴다.

 

너 때문에.. 내가 이 고생을...

사실 쉽게 해결할 수 있는 방법은 stackoverflow에서 찾을 수 있어서(해결책 링크) 계속 앱을 만들어봐도 되지만... ken님은 항상 모든 에러 메시지를 면밀히 살펴보고 꼼꼼히 조사해보기를 권장한다. 사실 그게 맞긴 하지만 항상 시간 내에 뭔갈 하다보면 그게 쉽지 않은데, 그래도 이번에 break 주간인 김에 내가 원하는 걸 못 만들어보더라도 에러메세지를 파보자 싶었다.

 

그런데 파도 파도 끝이없다;; 계속 파다간 미니 프로젝트는 시작도 못 할것 같지만 왠지 이번에 제대로 파고 가지 않으면 날 계속 괴롭힐 것 같고 쉬어가는 주간이 아니면 이런거 공부할 시간도 없을 것 같아서, 프로젝트 완성을 못하더라도 차라리 이 에러에 대해서 깊게 공부해보려고 한다.

 

그래서 시작된 이 글!은 Fetch API를 이해하는 것부터 시작된다. mdn 문서를 보면 documentation이 계속 link되어 있어서 끝이 없어보이는데.. 게다가 대부분 MDN에서 번역이 안 되어 있는 재앙적 상황이지만 열심히 mdn 문서를 번역하면서 정리해보겠다... 이 노력이 언젠간 큰 도움이 되기를...🤣

 

1. Fetch API란?

  • Fetch API는 네트워크 통신을 포함한 리소스 취득을 위한 인터페이스가 정의되어 있다.
  • Fetch API의 핵심은 인터페이스의 추상화이다! Fetch의 인터페이스에는 'Body', 'Headers', 'Request', 'Response'가 포함되어 있는데, 이들이 모두 자바스크립트의 객체 형태로 추상화되어 있기 때문에 이들을 더욱 쉽게 활용할 수 있도록 도와준다.
  • 또한 Fetch API 내부에는 fetch() 메소드가 내장되어 있어서 리소스에 대한 요청을 보내고 응답을 받으면 이를 Promise에 담아 return한다. 자세한 것은 아래에 더 풀어서 작성하겠다.

 

1) Body 인터페이스
  • 'Body' : response/request의 body를 나타내는 객체이며, content type과 그것이 어떻게 처리되어야 할지를 정의할 수 있도록 하는 인터페이스이다.
  • Body는 response와 request에 의해서 이행(?)되는데 따라서 각 response와 request 객체 내부에서 body 프로퍼티에 접근이 가능하다.
  • Body는 ArrayBuffer, ArrayBufferView, Blob, 문자열, URLSearchParams, FormData의 타입들 중 하나의 인스턴스이다.

 

2) Headers 인터페이스
  • Header 인터페이스는 HTTP 요청과 응답 header에 대해 다양한 액션을 할 수 있도록 돕는다.
  • Header 객체는 새롭게 인스턴스를 생성하면 최초에는 비어있는데, Headers.append() 같은 메소드를 이용해서 값을 추가할 수 있다.
  • Header 객체는 또한 'guard'라는 기능을 포함하는데, guard는 'immutable', 'request', 'request-no-cors', 'response', 'none' 등의 값을 가진다. 이 값들은 Header가 사용되고 있는 장소에 따라서 값이 설정된다.(기본 설정일 때에는 'none'이다.)
  • Request.headers, Response.headers 를 통해서 Request 또는 Response 객체 내부의 Header 객체에 접근이 가능하다.

아마도 리액트에서 내 API 요청이 이 부분에서 에러를 일으키는게 아닐까 싶다..?

 

3) Request 인터페이스
  • Request는 요청에 대한 리소스(정보)를 담고 있는 객체이다.
  • 다음과 같은 프로퍼티와 메소드를 가지고 있다.(MDN Request)

 

4) Response 인터페이스
  • Response는 request에 대한 response 정보를 담고 있는 객체이다.
  • Request와 마찬가지로 Body가 request에 의해서 implementing 되고, 따라서 body의 메소드를 이용하여 응답을 원하는 데이터로 변환할 수 있다.(?)
  • 보통 fetch한 이후 다음 .then에서 .then(response => response.json()) 과 같은 코드를 통해 응답을 json 형태로 변환하는데, 아마 이 과정에서 response 내부에서 이행된 body의 데이터를 json으로 변환하는 것이 아닐까 싶은 생각..(100% 이해가 안되서 틀릴 수 있슴다..)

 

5) fetch() 메소드
  • fetch() 메소드는 리소스에 대한 요청을 보내고, 응답을 받으면 이를 fulfilled된 상태의 Promise에 담아 return시키는 역할을 한다.
  • 참고로 fetch() 메소드가 리턴하는 Promise는 HTTP 에러(ex. 404 에러 등)에 대해서는 reject되지 않으며, 오직 네트워크 요청 실패에 대해서만 reject된다. HTTP 에러에 대해서는 Response의 ok 상태가 false인 resolve가 반환된다.
  • HTTP 에러를 확인하려면 .then을 이용해서 확인해야 한다.(ex. .then(response => if (response.status === '404') {...})와 같은 식..?)
  • fetch()의 첫번째 인자로는 요청할 대상 resource를 반드시 전달해줘야 한다. 이 resource는 URL과 같은 주소도 가능하고, 또는 따로 생성한 Request 객체를 전달하는 것도 가능하다.

 

정확한건지는 솔직히 잘 모르겠지만, 한 3시간 동안 이와 관련된 모든 MDN 문서를 읽으면서 이해한 내용을 토대로 Fetch API의 작동방식(?)에 대해 정리해보자면...

 

1) fetch('some urls...')를 통해서 특정 주소에 대한 HTTP request를 보낸다.
2) Fetch API에 내장된 Request 인터페이스에 의해서 해당 request에 대한 객체가 생성된다.(해당 객체 내부에는 요청에 대한 Header와 Body 정보가 담긴 객체가 존재한다.)
3) 서버로부터 응답을 받으면 마찬가지로 Fetch API에 내장된 Response 인터페이스에 의해 응답에 대한 response 객체가 생성된다.(마찬가지로 response 객체 내부에는 응답에 대한 Header와 Body 정보가 담긴 객체가 존재한다.)
4) 이제 받은 응답을 원하는 형태로 가공(ex. .then(response => response.json()) 등)하여 작업을 이어간다.

 

즉 Fetch API에서 정의된 fetch() 메소드를 통해 1)번 ~ 4)번의 과정을 수행할 수 있고, 이 과정에서 Fetch API에서 정의된 Header, Body, Response, Request 같은 인터페이스가 사용된다.

 

이 과정을 원래는 XMLHTTPRequest를 사용해서 복잡하게 하거나, 혹은 jQuery를 이용했어야 했는데, 이제 자바스크립트 자체에 Fetch API가 생김으로써 HTTP 요청/응답을 더욱 간편하게 하기 위해 만들어진 것이라고 정리하고 싶다.

 

결론적으로 fetch() 메소드 덕에 손쉽게 요청을 보내고 받을 수 있으며, 인터페이스(Header, Body, Request, Response) 덕분에 요청과 응답을 자바스크립트 형태로 받아서 손쉽게 다룰 수 있도록 도와주는 것이 Fetch API의 본질이 아닐까 생각된다.

 

자 그럼 이제.. 어떤 식으로 구동되는지 알아봤으니,, 다음 글에서 내가 맞닥뜨린 오류가 무엇인지, 그 원인은 무엇인지, 해결방법은 무엇인지 정리해보고자 한다... 그건 또 몇시간이 걸릴진 모르겠지만🤣

 

댓글