ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • vue에서 got 모듈 에러 핸들링하기
    Frontend 2019. 11. 18. 17:57

    vue에서 HTTP 요청을 위해 다양한 방법을 사용하는데, 대부분 axios를 많이 사용한다.

    국내 레퍼런스, 책에서 대부분 axios를 사용하는걸로 알고있다.

     

    프로젝트 특성 상 header에 cookie값을 넣어야 하는데, axios는 해당 내용을 지원하지 않아서 got 모듈을 사용하게 되었다.

    주로 사용되는 모듈들의 스펙을 비교하는 표를 참고하면, 프로젝트에 알맞는 모듈을 선택할 수 있다.

      got request node-fetch axios superagent
    HTTP/2 support ✔**
    Browser support ✔*
    Electron support
    Promise API
    Stream API Node.js only
    Request cancelation
    RFC compliant caching
    Cookies (out-of-box)
    Follows redirects
    Retries on failure
    Progress events Browser only
    Handles gzip/deflate
    Advanced timeouts
    Timings
    Errors with metadata
    JSON mode
    Custom defaults
    Composable
    Hooks

    출처 : https://www.npmjs.com/package/got#comparison

     

    HTTP 통신을 하다보면 이런저런 이유로 에러가 throw되는 상황이 있는데, 그럴때마다 로그 남기기 + 에러메세지 뿌리기를 하긴 하지만

    클라이언트 입장에서 좀 더 유저 친화적인 메세지를 던지고 싶었다.

     

    워낙 HTTP통신 하는 부분이 많기 때문에 vue에서 간단하게 핸들링하고자 했고, 그 과정을 블로그에 남긴다.

    에러 핸들링 자체를 처음 해보는 초급개발자이기 때문에 참고만 부탁드리고, 더 좋은 방법이 있다면 공유부탁드립니다~

     

     

    에러뿜어내기

    got 모듈을 사용하는곳에 try catch를 걸어 error를 throw해준다.

    function myFunction(url) {
        try {
            return require('got').post(url, {
               ....
            })
        } catch (error) {
            throw error;
        }
    }

     

    서버 구성에 따라, catch로 넘어가지 않는 오류들도 throw해준다.

     require('got').stream(url, {
            headers: {
            	...
            },
            hooks: {
                afterResponse: [
                    response => {
                            if (response.statusCode != 200) {
                                throw { ErrorCode: response.statusCode, message: response.statusMessage }
                            }
                    }
                ]
            }
        });

     

    나의 경우에는 reponse를 어느정도 가공해서 던저주었다.

     

     

    렌더러에서 catch하기

    vue 코드 즉, renderer에서는 got모듈을 사용하는 function에서 catch를 걸어준다.

     callGot(arg)
       .then(value => {
         ...
       }
       .catch(error => {
       	//throw한 error!
       	console.log(error)
       });

     

     

    에러를 받아서 console.log하거나 alert으로 노출 해줄수도 있겠지만, 클라이언트에 맞는 UI로 나타내고 싶다면

    에러를 핸들링 할 component를 하나 제작한다.

    <script>
    //에러를 예쁘게 뿌려줄 component
    import MessageBox from "./MessageBox.vue";
    const got = require("got");
    export default {
      data() {
        return {
          errorMessage: ""
        };
      },
      methods: {
        $handleError(r) {
          console.error("[ERROR] " + r);
          if (r) {
            if (r.gotOptions) {
              this.errorMessage = "요청에 실패하였습니다.";
              if (r.code)
                this.errorMessage = "[" + r.code + "] " + this.errorMessage;
            } else {
              this.errorMessage = r.message;
            }
          }
          this.$modal.show(
            MessageBox,
            {
              message: this.errorMessage
            },
            {
              height: "auto",
              width: "300",
              backgroud: "transparent"
            }
          );
        }
      }
    };
    </script>

    e에러를 핸들링 할 handleError 메소드를 작성한 후, 원하는 errorMessage를 작성한다.

    나의 경우에는 기존에 사용되던 messageBox 컴포넌트를 활용하여, modal로 띄웠다.

     

    메소드 이름 앞에 달러($) 표시를 붙여줬는데, main.js 에서 mixin으로 등록하여, 모든 파일에서

    this.$handleError() 형태로 접근하기 위해서다.

    달러 표시를 붙히지 않고 this.handleError()로 접근해도 되지만, 해당 파일의 로컬 메소드가 아닌, global한 mixin 메소드임을 표시하기 위함이다.

     

     

    mixin

    위에 언급한 바와 같이, 모든 vue 파일에서 접근 가능하도록 main.js에서 mixin 등록을 해보자.

    에러핸들링은 거의 모든 파일에서 이뤄져야 하기 때문에, 각 컴포넌트마다 각각 mixins를 등록하기가 어렵다.

    따라서 global처럼 사용하려고 한다.

    import Vue from 'vue'
    import {
        router
    } from './router/router';
    import App from './App'
    import store from '../store/index'
    import VModal from 'vue-js-modal'
    import ErrorHandler from "./components/Common/ErrorHandler.vue"
    
    Vue.use(VModal, {
        dynamic: true,
        injectModalsContainer: true
    })
    Vue.mixin(ErrorHandler)
    
    new Vue({
        components: {
            App
        },
        template: '<App/>',
        router,
        store,
    }).$mount('#app')

    간단하게 Vue.mixin(컴포넌트) 와 같이 넣어주면 된다.

     

    mixin이 등록 된 후, 앞에 작성되었던 renderer에서 catch하는 부분을 아래와 같이 수정해준다.

     callGot(arg)
       .then(value => {
         ...
       }
       .catch(error => {
       	this.$handleError(error);
       });

     

     

    ++) got 모듈 자체에서 보내주는 error 타입들은 아래에 정리되어있다.

    https://www.npmjs.com/package/got#errors

     

    got

    Simplified HTTP requests

    www.npmjs.com

     

    커스텀 에러의 구분은 r.gotOption의 유무로 체크 할 수 있고, 그 안에서도 에러를 구분하기 위해서는 아래와 같이 작성하면 된다.

    if (r.gotOptions) {
    	if(r instanceof got.CacheError){
        	//캐시 에러 핸들링
        }else if(r instanceof got.RequestError){
        	//요청 실패 핸들링
            //r.code로 오류 클래스를 뽑아낼 수 있음
        }else if(r instanceof got.ReadError){
        	//응답 스트림 에러 핸들링
        }else if(r instanceof got.ParseError){
        	//json parse 에러 핸들링
        }else if(r instanceof got.HTTPError){
        	//응답코드 2xx 이외 핸들링
        }else if(r instanceof got.MaxRedirectsError){
        	//최대 리디렉션 에러 핸들링
        }else if(r instanceof got.UnsupportedProtocolError){
        	//지원되지 않는 프로토콜 에러 핸들링
        }else if(r instanceof got.CancelError){
        	//요청 중단 핸들링
            //.calcel()이 불렸을 때
        }else if(r instanceof got.TimeoutError){
        	//타임아웃 핸들링
        }
    } else {
    	...
    }

     

     

    댓글

Designed by Tistory.