본문 바로가기
개발자 :-)

[대시보드 개발] 극악의 속도 개선하기

by 뚜생첨 2023. 1. 27.

이번에 대시보드를 개발하면서 처음 버전은

기본 화면 호출 -> ajax 로 사용자의 그리드 설정값 가져오기 -> 그리드 배치에 따라 HTML 이어붙여서 화면 그리기

방식으로 개발을 했다. 

(* 우리 파트 외에 기본 화면 호출(/page) -> ajax로 데이터 호출(/list) 방식으로 개발이 되어있어서 그 포멧을 따름)

 

근데 라이센스를 샀는데도 느린 amchart랑 느린 iframe을 같이 쓰니 속도가 말도 안되게 느렸다.

첫번째 페이지가 로드되는 중에 다음 페이지로 롤링되는 ㄷㄷ

 

그래서 속도 개선하겠다고 대시보드(센터메인-속도개선ver) 로 새로 개발을 했고, 

iframe 대신 기존의 위젯 소스를 최대한 수정하지 않기 위해

jsp:include 를 사용해보기로 했다.

 

1. ajax + HTML append + iframe 방식

for(var count = 0; count < 3; count++){ //차트 로딩속도 -> 미리 탭*3 그리기
		for(var i = 0; i < dataDt.length; i++){
			if(dataDt[i]["SEQ"]==1){
				switch(dataDt[i]["TAB_TYPE"]){
				case 21 : html += fn_tabType1(dataDt, i);
						i += 2;
					break;
				case 32 : html += fn_tabType2(dataDt, i);
						i += 4;
					break;
				case 33 : html += fn_tabType3(dataDt, i);
						i += 5;
					break;
				}
			}
		}
	}
    
 ...
 
 function fn_tabType1(data, i){
	var html = '';
	html += '<div class="widget widget__2x1">'
		+ fn_widget_box(data[i])
		+ fn_widget_box(data[i+1])
		+ fn_widget_box_col2(data[i+2])
		+ '</div>';
	return html;
}

...

function fn_widget_box(data){
	var tmp_html ='';
	if(data["WIDGET_NM"] == 'empty'){
		tmp_html += '<div class="widget__box no-link">';
	} else {
		tmp_html += '<div class="widget__box">';
	}
	tmp_html += '<div class="widget__header">'
					+ '<div class="widget__header--title">' + data['WIDGET_NM']+ '</div>'
					+ '<div class="widget__header--wrap">';
					if(data["TAB_FLAG"]!='N'){
						tmp_html += '<div class="tab">';
						if(data["TAB_FLAG"]==1){//당일/당월
							tmp_html += '<button class="tab__btn active"><spring:message code="LABEL.BIZ.DASH.CURR.DT" /></button>'
									+ '<button class="tab__btn"><spring:message code="LABEL.BIZ.DASH.CURR.MN" /></button>'
									;
						} else{//2 : 일별/월별
							tmp_html += '<button class="tab__btn active"><spring:message code="LABEL.BIZ.DASH.GUBUN.DAY" /></button>'
									+ '<button class="tab__btn"><spring:message code="LABEL.BIZ.DASH.GUBUN.MONTH" /></button>'
									;
						}
						tmp_html+= '</div>';
					}
					tmp_html += '</div>'
				+ '</div>'
				+ '<div class="widget__area">'
		        	+ '<div class="widget__item">'
		        		+ '<div class="iframe-area main__contents" id="_iframeDiv">'
							+ '<div id="'+data['WIDGET']+'">'
								+ '<iframe src="${contextPath}'+data["WIDGET_URL"]+'?'+addParam+'&TYPE=1" scrolling="auto" frameborder="0"></iframe>'
							+ '</div>'
						+ '</div>'
		        	+ '</div>'
					;
					if(data["TAB_FLAG"]!='N'){
					tmp_html += '<div class="widget__item">'
					+ '<div class="iframe-area main__contents" id="_iframeDiv">'
						+ '<div id="'+data['WIDGET']+'_2'+'">'
							+ '<iframe src="${contextPath}'+data["WIDGET_URL"]+'?'+addParam+'&TYPE=2" scrolling="auto" frameborder="0"></iframe>'
						+ '</div>'
					+ '</div>'
					+ '</div>'
					;
					}
				tmp_html += '</div>'
			+ '</div>';
	return tmp_html;
}

 

2. 첫번째 시도 :  ajax + HTML append 방식은 jsp:include 가 안먹는듯 하다,,

 

3. 두번째 시도 : 기본 화면 호출시 사용자그리드 설정값까지 가져오기 -> JSTL 로 jsp:include 그리기

소스 일부는 요러케,, 너무 길고 길지만 

5개 짜리 탭이 로드되는데 10분정도 걸렸던거같은데 이렇게 바꾸고 나니 10초 이내로 줄일 수 있었다!

<c:if test="${not empty ds_layout.data}">
    <c:forEach items="${ds_layoutDt.data}" var="layoutDt" varStatus="status">
        <c:if test="${layoutDt.TAB_TYPE eq 21}">
            <c:choose>
            <c:when test="${layoutDt.SEQ eq 1}">
                <div class="widget widget__2x1" data-index="${layoutDt.TAB_NO}">
                    <c:if test="${layoutDt.WIDGET_NM eq 'empty'}">
                        <div class="widget__box no-link">
                    </c:if>
                    <c:if test="${layoutDt.WIDGET_NM ne 'empty'}">
                        <div class="widget__box">
                    </c:if>
                    <div class="widget__header">
                        <div class="widget__header--title">${layoutDt.WIDGET_NM}</div>
                        <div class="widget__header--wrap">
                            <c:choose>
                            <c:when test="${layoutDt.TAB_FLAG eq 1}">
                                <div class="tab">
                                    <button class="tab__btn active" id="${layoutDt.WIDGET}_1">
                                        <spring:message code="LABEL.BIZ.DASH.CURR.DT" />
                                    </button>
                                    <button class="tab__btn" id="${layoutDt.WIDGET}_2">
                                        <spring:message code="LABEL.BIZ.DASH.CURR.MN" />
                                    </button>
                                </div><!-- tab -->
                            </c:when>
                            <c:when test="${layoutDt.TAB_FLAG eq 2}">
                                <div class="tab">
                                    <button class="tab__btn active" id="${layoutDt.WIDGET}_1">
                                        <spring:message code="LABEL.BIZ.DASH.GUBUN.DAY" />
                                    </button>
                                    <button class="tab__btn" id="${layoutDt.WIDGET}_2">
                                        <spring:message code="LABEL.BIZ.DASH.GUBUN.MONTH" />
                                    </button>
                                </div><!-- tab -->
                            </c:when>
                            <c:when test="${layoutDt.TAB_FLAG eq 3}">
                                <div class="tab">
                                    <button class="tab__btn active" id="${layoutDt.WIDGET}_1">
                                        <spring:message code="LABEL.BIZ.DASH.CURR.DT" />
                                    </button>
                                    <button class="tab__btn" id="${layoutDt.WIDGET}_2">
                                        <spring:message code="LABEL.BIZ.DASH.D+1" />
                                    </button>
                                </div><!-- tab -->
                            </c:when>
                            <c:when test="${layoutDt.TAB_FLAG eq 0}">
                                <div class="tab">
                                </div><!-- tab -->
                            </c:when>
                            <c:otherwise>
                                <div class="tab">
                                </div><!-- tab -->
                            </c:otherwise>
                            </c:choose>
                        </div><!-- widget__header--wrap -->
                    </div><!-- widget__header -->
                    <div class="widget__area">
                        <div class="widget__item">
                            <jsp:include page="/WEB-INF/jsp/aui/biz/dash/widget/${layoutDt.WIDGET_URL}" flush="false">
                                <jsp:param name="CENT_CD" value="${g_centCd}" />
                            </jsp:include>
                        </div>
                    </div>
                </div><!-- widget__box -->
            </c:when>

 

4. 최최종,,버전 (iframe은 알아서 재조회하는데 jsp:include 는 안된다,,)

개발 예시 : 총 3개의 페이지가 있고 3개를 1분 주기로 계속 롤링하게 한다면

롤링 script는 3개의 페이지에서 현재 2페이지를 보고있고 3으로 넘어갈때

1번 페이지를 clone 하여 3 다음에 붙이고 맨앞페이지를 삭제하는 방식이었는데

 

iframe 은 계속 새로운 iframe 을 복사하고 iframe 으로 호출이 될 때 마다 자동으로 위젯의 스크립트 $(document).ready(function~~) 이 실행되는 방식이었다.

 

근데 jsp:include 는 맨처음에 로드될때는 $(document).ready(function~~)을 수행하지만 

clone을 할 때마다 그냥 해당페이지의 HTML 만 복사되어 대시보드의 실시간데이터가 아니라는 문제가 발생했다.

 

그래서 결국엔 각 페이지 div에 data-index="${layoutDt.TAB_NO}" 요런거를 추가해서 

현재페이지의 위젯만 재조회하는 로직을 추가해야했다.

(단,, 위젯의 모든 프로세스는 위젯 이름으로 된 함수 안에 넣어야했다는,, 함정,, 이거는 어떻게 개선해야할지 고민중)

 

아래 처럼 (* 스크립트에서 JSTL 을 사용할 수 있다는 것도 처음알았다 ㅎㅎ)

롤링 스크립트에는 현재 페이지div를 찾아 data-index 값을 넘겨주는 소스

var widget_now = widgetArea.find('.widget');
var now = widget_now.eq(1).data('index');
dataReloadFunctions(now);

 

현재 페이지 번호를 받아서 위젯을 재조회하는 소스

function dataReloadFunctions(tab_no) {
    var widgetFuncStr;
    <c:forEach items="${ds_layoutDt.data}" var="item">
        widgetFuncStr = "${item.WIDGET}";
        widgetTabNo = "${item.TAB_NO}";
        widgetFuncStr = widgetFuncStr + "("+"1"+");";
    	if(tab_no == ''){
            eval(widgetFuncStr);
        }
        if(widgetTabNo == tab_no){
            eval(widgetFuncStr);
        }
	</c:forEach>
}

 

근데 eval은 안쓰는 게 좋다던디,, 어떻게 바꿔야할지 고민이다~~

728x90
반응형

'개발자 :-)' 카테고리의 다른 글

1년만에 본사출근한 SI 개발자썰  (0) 2024.11.20

댓글