개발 시 유의사항

이 문서는 Nexacro 를 이용하여 Application을 개발 시 개발자가 자주 실수하는 부분을 정리하였습니다.

PrefixId

Service URL 경로는 Full 경로가 아닌 PrefixID를 이용합니다.

사용방법

transaction 메소드 사용 시 서버 URL 경로는 Full 경로가 아닌 PrefixID를 사용하여 작성합니다.

this.transaction("svcSelect",
    "http://demo.nexacro.com/edu/nexacroN/select_emp.jsp",
    "","ds_emp=out_emp","","fn_call");
this.transaction("svcSelect",
    "SvcURL::select_emp.jsp",
    "","ds_emp=out_emp","","fn_call");

PrefixId를 사용해야 하는 이유

Nexacro 는 TypeDefinition에 PrefixID를 정의하여 사용할 수 있습니다. 
PrefixID를 사용해야 하는 이유는 크게 두 가지로 정리할 수 있습니다.

Nexacro 는 제품 자체에 Cache기능을 제공합니다.

Service url에 기술한 Service경로가 바뀌는 경우 소스 수정범위

TypeDefinition의 User Service (CacheLevel 설정)

CacheLevel1

TypeDefinition의 User Service 중 Type이 JSP 즉 Data 통신을 담당하는 Service는 CacheLevel를 “none”으로 설정해야 합니다.

참고사항

nexacroStudio에서 실행 시 Cache동작은 none으로 실행이 되나, 실행환경에서는 CacheLevel 설정값이 반영된다.

개발자 분들이 자주 질문하는 내용 중 다음과 같은 내용이 있습니다.


서버 서비스 즉 (조회) 기능을 실행 시 처음 한번은 데이타가 잘 조회되지만,

재 조회를 하게 되면 이전 자료가 유지되며 새롭게 데이타를 못 가져 옵니다.


이때 해결할 수 있는 방법은 User Service의 CacheLevel이 "none"으로 설정합니다.


서비스(Server Service)는 한번의 호출로 n개의 Dataset을 가져온다.

서비스(Server Service)는 한 번의 호출로 n개의 Dataset을 전송하도록 작성합니다.

this.Form_Emp_exe_onload = function(obj:nexacro.Form,e:nexacro.LoadEventInfo)
{
	this.transaction("svcSelect1","SvcURL::select_code.jsp", 
                     "","ds_dept=out_dept","","fn_call");
	this.transaction("svcSelect2","SvcURL::select_code.jsp",
                     "","ds_pos=out_pos","","fn_call");
};
위의 소스를 보게 되면 두 개의 Dataset( ds_dept, ds_pos) 을 가져오기 위해 두 번의 transaction을 호출하도록 만들어져 있는데  위의 코딩 방식은 폼이 로딩 시 성능에 영향을 주게 됩니다.


따라서 다음과 같은 방식으로 한 번의 서비스 호출로 두 개의 Dataset( ds_dept, ds_pos)을 가져오도록 수정합니다.
this.transaction("svcSelect1","SvcURL::select_code.jsp",
                      "","ds_dept=out_dept ds_pos=out_pos", "","fn_call");

한번의 서비스로 N개의 Dataset을 가져와야 하는 이유

위에서 설명한 예시는 부서, 직위 두 개의 Dataset를 가져오기 때문에 크게 문제가 되지 않을 수 있습니다.

만약 가져와야 할 코드 종류가 많다면 
대표적으로 폼이 Loading 되는 (onload) 이벤트에서 10개의 코드 성 데이터를 가져오는 경우  
Service호출이 10번이 발생합니다.

서비스 호출이 많아지게 되면 데이타를 가져오는데 소요되는 시간보다 
http통신을 연결하고 끊는 시간이 많이 소요되어 결과적으로 많은 시간이 소요됩니다.

개발된 Application 입장에서 성능 향상을 위해서 최대한 서비스는 적게 만들고 Dataset은 최대한 많이 가져오도록 Service를 구성해야 성능을 보장할 수 있습니다.

참고사항

Parameter(조건) 전달 시 주의사항

서비스(Server Service)의 Parameter(조건)전달 시 반드시 nexacro.wrapQuote() 함수로 감싸야 합니다.

var strParemeter = "var1=" + nexacro.wrapQuote("홍 길 동") + 
                   " var2=" + nexacro.wrapQuote("이순신");

this.transaction("svcSelect","SvcURL::select_code.jsp",
                 "","ds_dept=out_dept ds_pos=out_pos", strParemeter,"fn_call");
transaction호출 시 전달하는 변수가 여러 개인 경우 변수와 변수 구분은 공백(" ")으로 구분이 합니다.
이때 변수값에 공백(" ")이 포함되어 있는 경우 nexacro.wrapQuote()함수로 감싸주지 않으면 데이타에 포함된 공백(" ")은 변수값 구분으로 인식하여 오류가 발생할 수 있습니다.

따라서 조회 조건에 들어가는 값은 반드시 nexacro.wrapQuote() 함수로 감싸야 합니다.

Dataset과 Dataset의 구분은 공백(" ")으로 처리한다.

this.transaction("svcSelect","SvcURL::select_code.jsp",
                 "","ds_dept=out_dept ds_pos=out_pos", strParemeter,"fn_call");
transaction호출 시 n개의 Dataset을 받을수 있는데 이 때 Dataset의 구분은 공백입니다.
예) ds_dept=out_dept(공백) ds_pos=out_pos 부분을 확인해 보기 바랍니다.

간혹 (ds_dept=out_dept) 기술 시 = 부호의 앞/뒤(ds_dept = out_dept)를 공백으로 처리하는 경우가 있어 오류 나는 경우가 있으니 공백이 없도록 주의하시기 바랍니다.

서비스(Server Service)호출 시 Dataset 컬럼 Layout 정보 필요

transaction이용하여 서비스 호출 시 서비스에서는 기본 Dataset Layout(컬럼 정보) 와 Data 정보를 함께 리턴해 주어야 합니다.

정상적인 Dataset Layout

<?xml version="1.0" encoding="utf-8"?>
<Root xmlns="http://www.nexacro.com/platform/dataset" ver="5000">
	<Parameters>
		<Parameter id="ErrorCode" type="int">0</Parameter>
		<Parameter id="ErrorMsg" type="string">SUCC</Parameter>
	</Parameters>
	<Dataset id="out_emp">
		<ColumnInfo>
			<Column id="EMPL_ID" type="string" size="10"/>
			<Column id="FULL_NAME" type="string" size="50"/>
			<Column id="DEPT_CD" type="string" size="10"/>
			<Column id="POS_CD" type="string" size="10"/>
			<Column id="GENDER" type="string" size="10"/>
			<Column id="HIRE_DATE" type="date" size="10"/>
			<Column id="MARRIED" type="string" size="10"/>
			<Column id="SALARY" type="int" size="10"/>
			<Column id="MEMO" type="string" size="10"/>
		</ColumnInfo>
		<Rows>
			<Row>
				<Col id="EMPL_ID">DD222</Col>
				<Col id="FULL_NAME">d</Col>
				<Col id="DEPT_CD"></Col>
				<Col id="POS_CD"></Col>
				<Col id="GENDER"></Col>
				<Col id="MARRIED"></Col>
				<Col id="SALARY">0</Col>
				<Col id="MEMO"></Col>
			</Row>
			... 중략 ... 
		</Rows>
	</Dataset>
</Root>

잘못된 Layout

서버 프레임워크에서 호출한 서비스가 데이타가 없는 경우 
Dataset 기본 Layout(컬럼)을 만들지 않고 리턴해 주는 경우가 있다.
<?xml version="1.0" encoding="utf-8"?>
<Root xmlns="http://www.nexacro.com/platform/dataset" ver="5000">
	<Parameters>
		<Parameter id="ErrorCode" type="int">0</Parameter>
		<Parameter id="ErrorMsg" type="string">SUCC</Parameter>
	</Parameters>
	<Dataset id="out_emp">		
	</Dataset>
</Root>
Nexacro 는 transaction 호출 후 서버에서 보내온 Dataset Layout 정보를 이용하여 Client(UI)에서 작성한 Dataset Layout으로 치환합니다.

 따라서 조회하는 데이타가 없는 경우에도 반드시 컬럼 정보를 리턴해 주어야 합니다.

서비스 호출 시 서버에서 받아온 Dataset으로 치환됨

서비스(Server Service)는 데이타가 없는 경우라도 반드시 컬럼 Layout를 생성해 주어야 한다.

<?xml version="1.0" encoding="utf-8"?>
<Root xmlns="http://www.nexacro.com/platform/dataset" ver="5000">
	<Parameters>
		<Parameter id="ErrorCode" type="int">0</Parameter>
		<Parameter id="ErrorMsg" type="string">SUCC</Parameter>
	</Parameters>
	<Dataset id="out_emp">
		<ColumnInfo>
			<Column id="EMPL_ID" type="string" size="10"/>
			<Column id="FULL_NAME" type="string" size="50"/>
			<Column id="DEPT_CD" type="string" size="10"/>
			<Column id="POS_CD" type="string" size="10"/>
			<Column id="GENDER" type="string" size="10"/>
			<Column id="HIRE_DATE" type="date" size="10"/>
			<Column id="MARRIED" type="string" size="10"/>
			<Column id="SALARY" type="int" size="10"/>
			<Column id="MEMO" type="string" size="10"/>
		</ColumnInfo>
	</Dataset>
</Root>

Dataset 속성 useclientlayout 제대로 알기

Dataset 속성 중 useclientlayout 속성을 제공합니다. 
기본값은 false로 설정되어 있으며, 많은 분들이 이 속성에 대한 사용 용도를 정확히 알지 못하고 있어 정리합니다.

서비스를 먼저 만들지 않아도 Dataset 를 이용하여 개발 가능

Nexacro 는 Dataset이라는 invisible Object를 이용하여 서버 서비스를 만들지 않고서도 프로그램을 할 수 있는 장점이 있습니다. 

즉 화면을 구성하기 위해 서버 서비스를 먼저 만들고 Dataset 및 Layout 정보와 데이타를 가져온 후 화면을 구성해야 하지만, 서비스를 만들지 않고 nexacroStudio에서 Dataset를 미리 만들어 개발이 가능합니다.

transaction 호출 시 서버에서 넘겨 받은 Dataset으로 Layout 및 데이타가 치환된다.

nexacroStudio에서 만들어 사용하는 Dataset은 개발을 하기 위한 임시 디자인 및 테스트를 위해 사용하게 되면 실제 Dataset Layout과 데이타는 transaction을 통해 서버에서 넘겨받은 값으로 치환이 됩니다.

참고사항

Dataset 속성 useclientlayout를 true로 설정하여 nexacroStudio에서 만든 Dataset Layout을 사용할 수 있다.

Dataset Layout은 서버 서비스 단에서 넘겨주는 Layout 사용을 권장합니다.

useclientlayout를 ture로 사용하는 경우

  1. 서버에서 컬럼 정보 추가가 어려운 경우

  2. 서버에서 넘겨주는 컬럼의 Type이 DB Table와 다른 경우 (예: Int Type이 string으로 넘어오는 경우)

위의 경우를 제외하고는 가능한 useclientlayout 값은 Default false를 사용합니다.

Dataset 컬럼 Type의 중요성

Nexacro 는 서버에서 넘겨주는 Dataset Layout 중 컬럼 Type이 정확해야 합니다. 
즉 서버 서비스(DB Query)를 통해 가져오는 컬럼은 DB Table의 컬럼 Type과 동일해야 합니다. 
컬럼 Type은 각종 계산 등에서 중요한 역할을 합니다.

그리드 합계 구하기

getSum(“SALARY”)  -> getSum("nexacro.toNumber(SALARY)")
만약 서비스에 넘겨준 컬럼 SALARY를 이용하여 데이타의 합계를 구한다고 가정해 보자 
만약 Dataset의 SALARY 컬럼 TYPE이 숫자형(Int)이면 Dataset Method를 이용하여 바로 
getSum("SALARY") 형태로 프로그램을 완성할 수 있다, 

그러나 Dataset의 SALARY 컬럼 TYPE이 문자형(String)을 넘겨 받게 되면 Type을 변환해서 계산해야 하는 문제가 발생합니다.
getSum("nexacro.toNumber(SALARY)")

Dataset기능 중 Sort 기능 구현 시 Type의 중요성

Dataset의 다양한 기능 중 자주 사용하는 기능으로 Sort(정렬) 기능을 제공합니다. 
이때 Sort는 Type을 변경할 수 없으며, 무조건 Dataset의 컬럼 Type을 기준으로 Sort가 됩니다.

따라서 정확한 Sort 결과를 얻기 위해서는 Dataset의 컬럼 Type이 중요하다.

Sort는 Column의 Type이 기준이 되며, 형 변환 불가

참고사항

서버 서비스 프레임워크를 설계하는 분은 UiAdaptor 작성 시 반드시 위의 내용을 숙지해야 합니다.

Dataset의 이벤트 스크립트 작성시 주의사항

Dataset의 이벤트 중 onload, onrowsetchanged, onworposchanged  3개의 이벤트에는
Event 객체에 reason 프로퍼티가 존재합니다. 
reason 프로퍼티 이벤트는 해당 이벤트가 여러 경우에 발생할 수 있음을 의미합니다.

따라서 정확한 이벤트 정보에 맞도록 분기 처리를 하여 스크립트를 작성해야 합니다.

코드 작성 예시)

this. ds_emp_onrowposchanged = 
     function(obj:nexacro.NormalDataset,e:nexacro. DSRowPosChangeEventInfo)
{
    if(e.reason == 12) // append    
    {
       //Dataset에 append 이벤트가 발생시 진행할 스크립트 작성 	
    } else if(e.reason == 20) // delete
      //Dataset에 delete 이벤트가 발생시 진행할 스크립트 작성 	
    } else if(e.reason == 30) // sort
      //Dataset에 sort 이벤트가 발생시 진행할 스크립트 작성 	
    }
};

reason 속성이 있는 이벤트에서 해당 이벤트에 맞는 분기 처리를 하지 않을 경우

예기치 않은 스크립트가 동작할 수 있다.

Dataset 정보 스크립트로 변경 시 enableevent 속성 활용하기

Dataset을 이용하여 데이타 정보를 변경하는 경우가 자주 발생하게 하게 됩니다. 
Nexacro Dataset을 이용하여  스크립트 코딩 없이 컴포넌트에 데이타를 표현할 수 있는 바인딩 기능을 제공합니다. 

즉 하나의 Dataset은 여러 컴포넌트에 동시에 바인딩 하여 데이타를 표현할 수 있다. 
이때 다음과 같이 for문 등을 이용하여 여러 건에 컬럼 값을 변경한다고 가정해 보자
for(var i=0;i<100;i++)
{
    Dataset명.setColumn(i, ”컬럼”, ”값“);
}
위와 같이 for 문을 수행하면서 Dataset의 컬럼 값을 변경하게 되면 
Nexacro 엔진단에서는 해당 Dataset과 연결되어 있는 컴포넌트를 대상으로 repaint하는 
기능을 수행하게 됩니다.  

따라서 Dataset의 컬럼이 변경되면 시각적으로 표현되지 않지만 내부 엔진을 여러가지 기능을 수행하게되며, 성능에 영향을 줄 수 있다.

Dataset Event 멈추기

for문 등을 이용하여 컬럼정보를 바꿀 때는 enableevent 속성을 이용하여 Dataset 이벤트를 멈출 수 있다.
Dataset명.set_enableevent(false);
for(var i=0;i<100;i++)
{
    Dataset명.setColumn(i, ”컬럼”, ”값“);
}
Dataset명.set_enableevent(true);

Dataset Event 실행

set_enableevent(false); 를 통해 Dataset 이벤트를 멈추었다면 스크립트 수행 후에는 반드시 
set_enableevent(true); 를 이용하여 Event를 다시 실행해 주어야 합니다.

만약 set_enableevent(false); 후 set_enableevent(true);를 하지 않으면 제품에서 자동으로 처리해 주던 Dataset 기능을 set_enableevent(false); 이후 부터는 개발자가 책임을 져야 합니다.

데이타 통신방식

Nexacro(Client UI)와 서버 서비스단 간의 데이타를 주고받는 통신방식에는 크게 3가지 Type를 제공합니다

통신방식

XML

가장 기본이 되는 통신방식으로 개발시 디버깅이 용이하나, 데이타가 많은 경우 불필요한 XML Tag로 이해 통신패킷량이 많아 통합테스트 및 운영단계에서 사용은 권장하지 않습니다.

SSV

nexacro platform Web 버전 과 Mobile 버전 연동을 위하여 CSV 포맷을 확장한 포맷으로 
구분자 변경(콤마 -> US, 줄바꿈(CR/LF) -> RS) > Empty String과 undefined 의 구분을 위하여 undefined
는 ETX(end of text)[code:0x03] 값으로 대체되어 서버로 전송
HTML5환경에서는 통합 테스트 단계 및 운영 시에는 데이타 통신을 SSV를 권장합니다.

binary

바이너리 포멧을 제공합니다. 
단 해당 통신방식은 nexacroBrowser(NRE) 환경에서만 사용이 가능합니다.

참고사항

통신방식 옵션 중 Compress 기능(압축)을 제공합니다, 
하지만 해당 옵션은 binary 통신과 같이 nexacroBrowser(NRE) 환경에서만 제공합니다.

HTML5환경에서는 binary통신과 Compress(압축) 기능은 사용할 수 없습니다.

Nexacro 스크립트 작성 시 기준잡기

프로그램 코딩(스크립트)을 할 때는 해당 제품의 사상을 정확히 이해하고 코딩을 해야 
최상의 스크립트를 작성할 수 있습니다.  물론 코딩 방법에는 정석은 없으나, 가능한 해당 제품에서 추구하는 코딩 방식으로 작업을 한다면 소스코딩 및 성능면에서도 좋은 결과를 얻을 수 것으로 봅니다. 

다음의 내용을 참고하시기 바랍니다.
1. 가능한 스크립트로 코딩하기 전 Dataset 기능 중 바인딩으로 해결합니다. 
2. 바인딩으로 해결되지 않는 경우 각 컴포넌트의 이벤트에서 스크립트를 기술해 주게 되는데 
   스크립트 작성의 경우에도 Dataset의 이벤트에서 우선 처리가 가능한지 확인합니다. 
3. 1,2번으로 해결되지 않는 경우 각각의 컴포넌트의 이벤트를 이용하여 스크립트를 작성하도록 합니다.

최소 위의 3가지 내용만 참고하여 코딩을 해도 불필요한 코딩(스크립트)를 줄일 수 있습니다.

시큐어코딩 관련하여 eval 함수 대체방법

eval 함수 사용건 보안솔루션 업체에서 시큐어코딩 소스 점검에서 eval를 사용하는 경우 다른 함수로 대체하라는 검수결과가 나오고 있어 소스를 수정하는 일이 발생한 사례 (최근 보안이슈로 인해 실제 고객사에서 발생하고 있는 이슈)

해결방법

eval은 어떤 코드라도 무조건 실행하기 때문에 보안 문제도 있다. 따라서 신뢰하지 못하거나 모르는 코드가 포함되어 있을 경우 절대로 사용해서는 안된다.
eval은 사용하지 않는 게 좋다. eval을 사용하는 모든 코드는 성능, 보안, 버그 문제를 일으킬 수 있다. 만약 eval이 필요해지면 설계를 변경하여 eval이 필요 없게 만들어야 한다.

최근 실제 사이트에서 소스를 재개발하는 사례가 발생함

var sGridID = this.Grid3.name;
trace(sGridID + " : " + typeof sGridID);
결과 -> string 

var objGrid = this.components[sGridID]; 
//var objGrid = this.objects[sGridID]; //invisible 컴포넌트 
//var objGrid = this.all[sGridID]; //visible, invisible 컴포넌트 모두 가능 

trace(objGrid + " : " + typeof objGrid);
결과-> [object Grid] : object

변수 Scope

변수 Scope 란 현재 위치에서 접근이 가능한 변수를 결정하는 방법이다.
자신의 Scope 안에 있다면 접근이 가능하여 변수를 읽거나 쓸 수 있는 것이고, Scope 밖이라면 해당하는 변수는 접근이 불가능하게 된다.

변수의 종류는 크게 두가지로 구분 할 수 있다.
전역변수(Global Variable) : 
Function밖에서 선언한 변수로 현재 화면의 어디에서나 접근가능

지역변수(Local Variable) : 
Function안에서 선언한 변수, Function안에서만 접근가능

Scope미지정시 Global로 처리되므로 Variant 사용 시 반드시 Scope을 명시하여야 한다.

사용 예)

a1 = 3; //global의 a1으로 동작함
var a2 = 4; //기존에는 form의 member였으나, nexacro에서는 form member가 아님
this.a3 = 5; //form의 member로 동작하려면 이와 같이 this를 명시해야 함 

this.Button00_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
	var a4 = 3;
	trace(a4); //local scope는 자바스크립트와 동일
	trace(a1); //global scope와 동일
	trace(this.a3); //form의 member variant를 접근하기 위해서는 this명시 
	trace(this.a2); //form의 member variant가 아님으로 form member로 적근이 불가 
};

참고사항

투비소프트 제품 중 MiPlatform은 var 미선언 시 Form 변수로 동작하며,

Nexacro 는 var 미선언 시 Gloval변수로 동작합니다.