BacGyber's Tricks

'Extjs'에 해당되는 글 1건

  1. [issue solved] Loading Excel Data on ExtJs Grid using SheetJs

[issue solved] Loading Excel Data on ExtJs Grid using SheetJs

□ Tech (Software)



[solved] Loading Excel Data on ExtJs Grid using SheetJs


이런 저런 이슈처리를 많이 하는데 기록은 오랜만에 합니다.

기술적으로 참고도 가능할것이나.. 그보다는

현상을 분석하고 처리하는 사고 방식에 대해서도 참고가 되면 좋겠습니다.

사고방식 역시 특별한건 없습니다. 기본적인 것인데... 의외로 이것이 제대로 안되는 분들이 많습니다. 뭐 각자 잘하는 부분이 서로 다르니 그런것이겠죠...

# 현상 분석, 직접 정확히 하기


이번건의 경우 전달받은 현상은 제대로 파악이 된 경우였습니다.

아무튼 항상 현상을 직접 파악하는 것이 이슈 해결의 첫번째 단추 입니다.


시간상 직접하지 못한다면 질의를 통해 최대한 검증하고

의심이 갈 경우 직접 검증하는게 좋겠죠.


그렇게 할 시간조차 내기 애매한 경우엔 일단 전달받은 현상으로 접근하여 빠른 임시 조치후 다시 현상을 파악하던가 해야할 것입니다.


"일반적인 세상살이 현실"에서도 "전산"에서도 많은 사람들이 현상 자체를 제대로 분석하지 못하는 경우가 많으므로 문제해결 능력을 키우려는 분들은 정말 문제가 뭔지 파악하는게 가장 중요합니다.

아무도 믿지 마십시오. 현상을 전달해주는 기술자 말도 부정확합니다. 경험상 60~80%는 부정확하거나 오히려 잘못 짚고 있습니다. 

수사를 하듯, 데이터 모델링을 하듯 근본적인 것에 부터 확인을 하여 스스로 현상을 재정의 하십시오.

기존에 이 부분에 대해 알고 있지는 않았고 이슈 해결을 위해 단발성 지원을 하였습니다.

소스 변경하여 처리하는데는 2시간이 소요되었습니다. 컨디션 난조로 현상 분석을 좀 천천히 진행했습니다.

급하게 현상 분석시엔 문제 처리방향을 잘못 짚게 되어 결국 시간을 허비하게 되죠.

소스 변경 이후.... 해당 소스수정을 통해 확실히 이슈해결이 보장되는 것인지에 대한 검토, 

반복 테스트를 위해 추가적인 시간이 더 투입되었습니다.


* 환경

오픈소스 sheetjs 를 이용해 엑셀 (.xls, .xlsx) 을 읽는다.

이후 extjs 그리드상에 로딩.

* 이슈

엑셀 업로드가 되지 않는다.

* 현상

처음 업로드는 됨. 

안되는 경우는 프레임 새로고침 또는 해당 기능 화면을 닫았다 열어서 진행할 경우임.

테스트서버에서만 발생하며, 개발자 서버에선 발생하지 않음.

기존 타 프로젝트 환경에선 발생하지 않았다고 함

* Error Log in Client Javascript

Uncaught ReferenceError: XLS is not defined

=> XLS 는 sheet js 쪽의 오브젝트임

* 분석 1

클라이언트단에서 발생하는 것인데 왜 서버에 따라 다른가?

런타임상에서 분석결과 엑셀업로드시 스크립트를 서버를 통해 다운로드 하고 있다. ( 속도가 그리 느리진 않음. http 200 성공됨)

해당 XLS 인스턴스가 없어서 참조를 못하거나 있는데도 찾아가질 못하거나 그런것이겠지

* 분석 2- 원인

해당 화면 리로드나 닫아서 다시 열었을때 해당 인스턴스가 destroy 되는것 같다.

그런데 로딩 타이밍에서 

1) Extjs 또는 WebWorker 에서 있다고 판단하여 다시 생성되지 않거나

2) 로딩이 되더라도 어디에선가는 최초 로딩과 조금 다른 로직으로 인해 로딩이 늦게 되거나 하는 시간차

3) 최종 이용부분이 빨리 호출되던가 하는 시간차

결국 SheetJs 에서 로딩시에는 XLS 가 없거나 있더라도 참조할수 있는 구조가 뒤틀려 에러가 나는거 같다.

* 처리

* 기존 로딩 순서 파악

* 어떤 순서로 로딩이 되어야 하는것이 맞는지 소스 분석 및 재정리

* 그 순서에 맞게 될 수 있는 방법 검토 및 소스 변경

** 관련 과정에서 ExtJs, SheetJs, WebWorker (SheetJs 에서 이용) 쪽을 살펴보았습니다.

초반 개발한 분이 잘했으나 아마 급하게 진행하다보니 이런 구멍이 있었을거 같네요.

전체적인 메카니즘에 대해 핵심적인 파악을 했다면 더 좋은 버젼이 되었겠죠

* 처리 - 변경전후 소스

몇개의 소스를 수정하였습니다.

분산되어 js 로딩하면서 생기는 구멍을 깔끔히 정리하였습니다.

아래는 초기에 순차적으로 nested callback 으로 js 들을 로딩하고 마지막 callback 에서 동작해야할 method 를 호출하도록 한 소스 입니다.

그 method 가 호출되면  sheetjs 를 통해 읽은 data 가 자체적으로 구현한 method 에 전달되어 해당 data 가 그리드에 로딩이 됩니다. 


        if(fileExt == ".XLS")

       {

               // OLD - "XLS undefined"

//                Ext.Loader.loadScript({url : '/view/common/js/sheetjs/xls/xls-read.js', onLoad : function(){xlsLoad(e);}});

               

               // NEW

               Ext.Loader.loadScript(

                               {

                                       url : '/view/common/js/sheetjs/xls/shim.js', 

                                       onLoad : function(){

                                               //xlsLoad(e);

                                               Ext.Loader.loadScript(

                                                               {

                                                                       url : '/view/common/js/sheetjs/xls/xls.js', 

                                                                       onLoad : function(){

                                                                               //xlsLoad(e);

                                                                               Ext.Loader.loadScript(

                                                                                               {

                                                                                                       url : '/view/common/js/sheetjs/xls/xls-read.js', 

                                                                                                       onLoad : function(){

                                                                                                               xlsLoad(e);

                                                                                                       }

                                                                                               }

                                                                               );

                                                                       }

                                                               }

                                               );

                                       }

                               }

               );

       }

       else if(fileExt == ".XLSX")

       {

               // OLD - "XLS undefined"

//                Ext.Loader.loadScript({url : '/view/common/js/sheetjs/xlsx/xlsx-read.js', onLoad : function(){xlsxLoad(e);}});

               

               // NEW

               Ext.Loader.loadScript(

                               {

                                       url : '/view/common/js/sheetjs/xlsx/shim.js', 

                                       onLoad : function(){

                                               //xlsLoad(e);

                                               Ext.Loader.loadScript(

                                                               {

                                                                       url : '/view/common/js/sheetjs/xlsx/jszip.js', 

                                                                       onLoad : function(){

                                                                               //xlsLoad(e);

                                                                               Ext.Loader.loadScript(

                                                                                               {

                                                                                                       url : '/view/common/js/sheetjs/xlsx/xlsx.js', 

                                                                                                       onLoad : function(){

                                                                                                               //xlsLoad(e);

                                                                                                               Ext.Loader.loadScript(

                                                                                                                               {

                                                                                                                                       url : '/view/common/js/sheetjs/xlsx/xlsx-read.js', 

                                                                                                                                       onLoad : function(){

                                                                                                                                               xlsxLoad(e);

                                                                                                                                       }

                                                                                                                               }

                                                                                                               );

                                                                                                       }

                                                                                               }

                                                                               );

                                                                       }

                                                               }

                                               );

                                       }

                               }

               );

       }

       else

       {

               Ext.MessageBox.show({

            msg: Lang.get('EXCEL_FILE_ONLY'),

            buttons: Ext.MessageBox.OK,

            icon: Ext.MessageBox.ERROR,

            fn : function(){

                    ExcelLoader.formCmp.up("[xtype=window]").close();

            }

        });

       } 



* 부연1

이 app는 Single Page Application 구조로 개발되지 않았습니다.

만약 SPA 라면... 이와 같은 현상은 발생하지 않았을것 같습니다.

SheetJs 쪽을 분석해봐야 알겠으나... 지금과 같이 ExtJs 를 이용한 동적로딩이 아닌...

현재 MPA 구조에서는... Excel 업로드 이용하는 화면마다 

정적으로 관련 js 를 로딩하여도 문제는 해결될 것 같습니다.

단 그 경우 ap 전반적인 수정이 필요하므로

진행하기 좀 애매한 점이 있습니다.

* 부연2 - 기존에는 발생하지 않았다? 

로딩 부분 개선 이후 여러차례 테스트 결과 전혀 기존 현상이 발생하지 않았습니다.


기존 타 서버에서 발생치 않았다고 하는데.... 그것이 정말 사실이라면... 조금 설명이 애매해진다고 볼 수도 있습니다.

하지만... "기존 타 환경에서의 서버 처리및 서버 클라이언트 사이의 속도가 늘 빨랐다" 라는 가정을 한다면 그리 이상할것도 없습니다.


클라이언트에서 관련 처리 속도가 아주 빠르므로...
클라이언트 - 서버간의 로딩 시간이 타 환경 서버들보다 아주 조금 더 늦다해도 이런 현상은 있을수 있습니다.

XLS 인스턴스를 로딩하는 xls.js 의 경우 0.2 초라는 적지 않은 시간이 소요되고 있습니다.



Reference

ExtJs

http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.Loader-method-loadScript


SheetJs

https://github.com/SheetJS/js-xlsx

webworker

https://developer.mozilla.org/en-US/docs/Web/API/Worker

https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API