Vue.js Http Request

강정우·2023년 4월 3일
0

vue.js

목록 보기
21/72
post-thumbnail
post-custom-banner

fetch API

<script>
...
	// button 클릭해서 request 날리는 로직
	fetch(URL,{
    	method:"GET | POST | DELETE | PATCH | ...",
        header:{
        	'~':'~'
        },
        body:JSON.stringfy({
        	key:value(this.~~)
        })
    })
    
...
</script>
  • fetch 메서드의 첫번재 인수는 URL이고 2번째 인수로 request을 구성하는 JavaScript 객체이다.

  • 이 객체 안에 method 프로퍼티를 써 넣는다.

  • 기본으로 값은 GET 문자열이지만 POST로도 설정할 수 있다.

  • 그리고 발신 요청에 headers 즉 메타데이터도 추가해야 하는데 정확히 말하면 Content-Type 헤더를 application/json으로 설정해서 JSON 형식의 일부 데이터가 요청에 추가된 걸 서버에 알려야 한다.

  • 기본적으로 텍스트이지만 특정 방식으로 쓴 텍스트 형식으로 기기가 파싱하고 읽기 아주 쉽다.

  • body에 데이터를 실어서 보낼 때 JSON.stringfy로 보내면 JS 객체를 JSON 형식(문자열)으로 바꿔주는 메서드이다.

Get

<script>
...
	// button 클릭해서 request 날리는 로직
	fetch(URL,{
    	method:"GET | POST | DELETE | PATCH | ...",
    }).then(function(res){
    	if(res.ok){
        	return res.json();
        }
    });
    
...
</script>
  • Get method는 기본값이라 따로 써줄 필요가 없다.

  • 자 그럼 어떻게 결과값에 접근할 수 있을까 여기서 바로 Promise 개념이 도입된다.

  • JavaScript는 이전 코드의 결괏값이 도착할 때까지 코드 실행을 멈추고 기다리는 언어가 아니다.

  • fetch는 데이터가 도착하면 이를 수신할 수 있는 객체를 반환하고 그 후 데이터가 도착했을 때 코드를 설정 및 실행한다.

  • 이때 리스너는 fetch의 결괏값 뒤에 then 메서드를 추가하여 설정하는데 then 메서드에는 함수가 들어간다.

  • 이 함수는 결괏값이 나왔을 때 실행되는데 데이터가 도착하면 브라우저에서 자동으로 실행하는 함수이다.

  • 이 응답을 파싱할 수 있는데 if 문을 통해서 응답, 즉 response가 ok인 경우 자동으로 브라우저가 찾은 response 객체가 성공적인 요청인지 아닌지를 ok 프로퍼티로 가려낸다.
    서버가 404 코드를 반환하는 경우라면 ok가 아니고 반면 ok 상태라면 해당 응답을 통해서 데이터를 읽어들일 수 있다.

  • res.json() 메서드로 응답 데이터를 파싱할 수 있다.
    그리고 해당 응답 데이터를 반환할 수 있다. 이는 then 블록을 통해 생성된 프로미스를 반환할 수도 있고 첫 번째 then 메서드 다음에 또 다른 then 메서드를 추가할 수도 있다. 이 then 메서드는 return 프로미스가 완료되었을 때 트리거된다.

...
	// button 클릭해서 request 날리는 로직
	fetch(URL,{
    	method:"GET | POST | DELETE | PATCH | ...",
    }).then((res)=>{
    	if(res.ok){
        	return res.json();
        }
    }).then((data)=>{
    	const results = []
        for(const id in data){
        	results.puch({id:id, name:data[id].name, rating:data[id].rating});
        }
        this.데이터프롭 = results;
    });
    
...
</script>
  • then(function(data){}) 에는 response.json을 통해 반환된 실제 data를 입력한다.
    이때 data는 JS 객체이기 때문에 변환을 해주어야한다.

  • 그리고 TypeError : Cannot set property 'results' of undefined at eval error는 this. 키워드가 context 오류가 나서 생기는 문제인데 이때는 =>를 사용하여 해당 함수 내부에 있는 this 키워드가 외부에 있는 this 키워드와 동일한 컨텍스트를 참조하도록 하면 된다.

Axios

fetch API 코드

fetch('https://vue-http-demo-85e9e.firebaseio.com/surveys.json', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: this.enteredName,
    rating: this.chosenRating,
  }),
});

Axios 코드

import axios from 'axios'; 

...
axios.post('https://vue-http-demo-85e9e.firebaseio.com/surveys.json', {
  name: this.enteredName,
  rating: this.chosenRating,
});
  • 장점 : 자동으로 Content-Type헤더를 설정하고 본문 데이터를 JSON으로 자동 변환한다.
    단점 : 출하하는 웹 앱의 크기가 증가한다

  • fetch()는 프로미스를 반환하므로 then(), catch() 및 async/ await 을 사용할 수 있다.
    Axios의 경우 Promise도 반환한다는 점에서 동일하다.

자동로드

  • 이제는 페이지가 로드될 때 자동으로 데이터를 꺼내와서 보여주는 코드를 작성해보자.

  • 이는 우리가 배웠던 생명주기를 이용하면 된다!!

  • 우선 mounted 훅을 사용해보자. mounted 훅은 Vue 앱이 마운트되었을 때 트리거된다.
    그래서 기존에 methods에 http req 메서드를 this.로 참조하여 실행하게끔 하면 된다.

로딩 페이지

  • 우선 로딩 state를 하나 만들어서 data(){} 속성에 추가해준다.

  • 그리고 methods에 http method에 각 fetch API마다 loading state를 true로 만들어준다.

  • 이때 주의할 점이 있는데 fetch가 모두 끝난 지점에 추가하면 fetch 메서드가 끝나기도 전에 바로 실행이 되기 때문에 fetch 메서드 내부에 작성해야한다.

  • 그리고 <template>에 v-if, v-else 속성을 사용하여 로딩 상태를 구현해주면 된다.

데이터 없음.

  • 데이터가 없는 것은 res의 http 응답 번호가 200번 대 라는 것이고 이는 오류는 아니다. 따라서 이를 따로 검증해줘야하는데 이부분은 methods 로직이아닌 <template>영역에서 .length와 v-if, v-else-if, v-else로 구분해주어야한다.

오류 처리.

...
// button 클릭해서 request 날리는 로직
methods:{
  httpReqMethod(){
    this.isLoading = true
    this.error = null
	fetch(URL,{
    	method:"GET | POST | DELETE | PATCH | ...",
    }).then((res)=>{
    	if(res.ok){
        	return res.json();
        }
    }).then((data)=>{
    	const results = []
        for(const id in data){
        	results.puch({id:id, name:data[id].name, rating:data[id].rating});
        }
  		// data(){} 에 http res data 넣는 부분
        this.데이터프롭 = results;
    }).catch((error)=>{
  		this.에러프롭 = '예를들어 데이터를 가져오는데 실패함. 다시 ㄱㄱ';
	});
  }
}
  • .catch()는 앞서 작성한 .then 블럭이나 fetch() API에서 발생한 오류들을 포착하여 처리한다.

  • 그리고 개발자는 console.log에 찍힌 error를 사용자에게 알려줄 필요가 있다.
    그리고 이것을 구현하기위해 data(){} state를 하나 더 만들어 관리해줄 필요가 있다. 예를들어 error:null

  • 물론 해당 에러를 구체적으로 에러메시지를 표시해줄 수도 있다.

  • 또한 새로운 요청을 전송할 때마다 error가 리셋되어있어야한다. 따라서 methods에 http req 메서드에 error를 항상 초기화해주는 구문이 있어야한다.

  • 또한 해당 로직을 loading => error => 데이터 없음 => 데이터 표시 순으로 <tamplate> 로직을 짜주면 좋다.

.catch()의 맹점 (서버 사이드 오류 응답 처리)

  • 400,500 번대의 상태코드 응답은 위와같이 사용하면 catch가 잡아내지 못한다. 그래서 존재하는 것이 Error 객체이다.
...
// button 클릭해서 request 날리는 로직
methods:{
  httpReqMethod(){
    this.isLoading = true
    this.error = null
	fetch(URL,{
    	method:"GET | POST | DELETE | PATCH | ...",
    }).then((res)=>{
    	if(res.ok){
        	return res.json();
        }
    }).then((data)=>{
    	const results = []
        for(const id in data){
        	results.puch({id:id, name:data[id].name, rating:data[id].rating});
        }
  		// data(){} 에 http res data 넣는 부분
        this.데이터프롭 = results;
    }).then(res=>{
      if(res.ok){
        //...
      } else {
        throw new Error('에러 구문');
      }
    }).catch((error)=>{
  		this.에러프롭 = '예를들어 데이터를 가져오는데 실패함. 다시 ㄱㄱ';
	});
  }
}
  • 이 Error 생성자는 JavaScript 내장 생성자로 새로운 오류를 발생시켜서 자동으로 catch 블록이 이를 인식하게 만든다.
profile
智(지)! 德(덕)! 體(체)!
post-custom-banner

0개의 댓글