1. 사용 배경

 1) Ajax를 컨트롤할 때 각종 옵션을 개발자 및 화면마다 다 직접 입력하다보니 Csrf, Xss 등의 보안 처리를 개별적으로 하다보면 오류 발생시 대처 어려움

 

  2) 이러한 현상으로 인해 개발자마다 개발 방식의 공통 부재는 기본이거니와 유지보수 때에도 추적이 어렵다. (유지보수비용 과다 발생 원인 중 하나)

2. 사용 방법

 1) 아래 소스를 이용하고자한다면 서버에서 Exception 오류등의 발생시 무조건 동일 구조로 Response를 내려주는 기본 인터페이스가 선행되어야한다.

  필자의 경우 Java를 이용 중이므로 GlobalExceptionHandler 및 Jackson Json을 이용하여 공통 Vo를 사용하여 아래 구조를 필히 응답한다.

/** 웹 API 커스텀  */
const ajax = {
    logPrefix: "[ADMIN-API] -- "
    , params: {
        type: 'POST'
        , contentType: 'application/json;'
        , dataType: 'json'
        , includeHeader: true
        , hasLoading: true
        , errAlert: false
        , data: {}
        , beforeSend: function (xhr) {
            xhr.setRequestHeader(app.csrf.headerName, app.csrf.token);
        }
    }
    , call: function (opts) {
        // 고정 변수를 복제한다.
        let ajaxParams = _.clone(ajax.params);

        // 기존 Ajax Options 정보를 덮어 씌운다.
        _.extend(ajaxParams, opts);

        console.log(ajax.logPrefix + "Request Start");
        console.log(ajax.logPrefix + "Request  - " + ajaxParams.url);

        if (typeof ajaxParams.data === 'object') {
            let data = JSON.stringify(ajaxParams.data, null, 4);
            console.log(ajax.logPrefix + "Request params - " + data);
            ajaxParams.data = data;
        }

        ajaxParams.success = function (resultData, status, xhr) {
            let resParam = {
                "type": 1
                , "ajaxParams": ajaxParams
                , "userOpts": opts
                , "resultData": resultData
                , "status": status
                , "xhr": xhr
            }
            ajax.callSuccessAction(resParam);
        };

        ajaxParams.error = function (xhr, status, errorThrown) {
            let resParam = {
                "type": -1
                , "ajaxParams": ajaxParams
                , "userOpts": opts
                , "resultData": xhr.responseText
                , "status": status
                , "xhr": xhr
                , "errorThrown": errorThrown
            }
            console.log(ajax.logPrefix + "Response : Error - ", xhr, status, errorThrown);
            ajax.callFailureAction(resParam);
        };

        ajaxParams.complete = function (xhr) {
            console.log(ajax.logPrefix + "===============[ End ]==");
        };

        $.ajax(ajaxParams);
    }
    /***************************************************************************
     * @param {
                "ajaxParams": ajaxParams
                , "userOpts": opts
                , "resultData": resultData
                , "status": status
                , "xhr": xhr
            }
     */
    , callSuccessAction: function (param) {

        // Function이 구현되어있는 경우.
        try {
            let header = param.resultData.header;
            let body = param.resultData.body;
            let ajaxParams = param.ajaxParams;
            let userParams = param.userOpts;

            console.log(ajax.logPrefix + "Response : success - ", JSON.stringify(body, null, 4));
            if (header.isSuccess) {
                if (ajaxParams.includeHeader) {
                    userParams.success(param.resultData, param.status, param.xhr)
                } else {
                    userParams.success(body, param.status, param.xhr);
                }
                // 무조건 Complete 실행
                ajax.callCompleteAction(param)
            } else {
                // Failure 구현식을 Function 아닌 경우
                throw cmm.getMessageCode(-100);
            }
        } catch (e) {
            console.error("ERR - ", e);
            param.errorThrown = e;
            ajax.callFailureAction(param);
            return;
        }
    }
    /***************************************************************************
     * @param {
                "ajaxParams": ajaxParams
                , "userOpts": opts
                , "resultData": xhr.responseText
                , "status": status
                , "xhr": xhr
                , "errorThrown": errorThrown
            }
     */
    , callFailureAction: function (param) {
        console.log(ajax.logPrefix + "Response : failure - ", JSON.stringify(param, null, 4));
        let json;
        try {
            if (typeof param.resultData == 'object') {
                json = param.resultData;
            } else if (typeof param.resultData == 'string') {
                json = JSON.parse(param.resultData);
            } else {
                json = new Object();
            }

            if (param.ajaxParams.errAlert) {
                alert(json.header.message);
            }

            _.isFunction(param.userOpts.error) ? param.userOpts.error(json) : function () {
                alert(json.header.message);
                let forwardUrl = json.header.forwardUrl;
                if (!_.isEmpty(forwardUrl)) {
                    location.href = forwardUrl;
                }
            };
        } finally {
            ajax.callCompleteAction(param);
        }
    }

    , callCompleteAction: function (param) {
        // Function이 구현되어있는 경우.
        if (_.isFunction(param.userOpts.complete)) {
            param.userOpts.complete();
        } else {
            // TODO 필요시 공통 구현. (현재는 사용용도 없음)
        }
    }
};

3. 결과

  1) 성공

{
  header: {
      resultCode : 1 or -1
      ,resultDetailCode : 100 or 200
      ,message : "SUCCESS" OR "FAIL"
  }
  , result : Array or Object
}

  2) 실패

{
  "header" : {
    "isSuccess" : false,
    "statusCode" : -1,
    "statusDetailCode" : 401,
    "message" : "Permission is Not Empty"
  }
}
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기