DataObject

DataObject 오브젝트 소개

오브젝트 형태의 데이터를 직접 작성하거나 서비스를 호출해서 관리할 수 있습니다. Dataset 오브젝트와 바인딩해서 사용하는 경우 기존 Dataset 오브젝트를 사용하는 컴포넌트와 같이 사용할 수 있습니다.

간단한 데이터 표시하기

직원 목록을 JSON으로 받아와서 Grid 컴포넌트에 표시합니다.

데이터는 아래 URL에서 제공하는 샘플 데이터를 사용합니다.

http://demo.nexacro.com/developer_guide/N/FileSample/data_sample_dataobject_01.json

크롬 등 일부 브라우저에서는 CORS 정책에 따라 샘플 데이터 URL에 접근하지 못할 수 있습니다. 아래 첨부 파일을 내려받아 접근할 수 있는 서버에 놓고 확인해보세요.

data_sample_dataobject_01.json

예제

특정 서비스에서 제공하는 JSON 데이터를 가져와 Dataset 오브젝트에 바인딩하고 Grid 컴포넌트에 표시합니다.

sample_dataobject_01.xfdl

예제에서 사용한 핵심 기능

binddataobject

Dataset 오브젝트와 바인딩할 DataObject 오브젝트를 선택합니다. 실제 적용되는 값은 dataobjectpath 설정에 따라 달라질 수 있습니다.

dataobjectpath

DataObject 오브젝트 데이터 중에서 실제 반영할 데이터를 필터링하기 위해 설정하는 값입니다. 배열 또는 오브젝트를 선택하면 해당하는 값의 목록을 반환합니다.

예제 구현 방법

데이터를 가져올 url 설정하기

1

DataObject 오브젝트를 추가합니다.

DataObject 오브젝트는 Invisible Object로 추가됩니다.

2

DataObject 오브젝트의 url 속성값을 아래와 같이 설정합니다.

url: ../FileSample/data_sample_dataobject_01.json

Dataset 오브젝트와 DataObject 오브젝트 연결하기

1

Dataset 오브젝트를 추가합니다.

2

Dataset 오브젝트를 선택하고 속성창에서 binddataobject 속성값을 "DataObject00"으로 선택합니다.

3

속성창에서 dataobjectpath 속성 옆에 있는 버튼을 클릭하고 [Data Path Editor]를 실행합니다.

4

[Data Path Editor] 창에서 URL 항목을 체크하고 [Get] 버튼을 클릭합니다.

URL 값은 이전 단계에서 DataObject 오브젝트의 url 속성값으로 설정한 값이 보여집니다. 하단 Json Contents 영역에 서버에서 가져온 JSON 데이터를 보여줍니다.

5

Json Contents 데이터에서 "data [24]"로 표시된 항목을 선택하고 오른쪽 마우스 클릭 후 [Set Dataobject Root Path] 항목을 선택합니다.

6

DataObject Path에 선택한 항목에 루트 경로가 새로 설정된 것을 확인하고 [Refresh json contents] 버튼을 클릭합니다.

7

새로 설정된 루트 경로 아래의 데이터가 [Filtered Contents] 탭에 표시됩니다.

8

Json Contents 데이터에서 id 항목을 선택하고 오른쪽 마우스 클릭 후 [Add Column] 항목을 선택합니다. 또는 Columns 항목 옆에 있는 버튼을 클릭해서 칼럼 항목을 추가할 수 있습니다.

9

순서대로 id, employee_name, employee_salary, employee_age 항목을 칼럼으로 추가합니다.

10

[OK] 버튼을 클릭합니다. 속성창에서 dataobjectpath 값이 설정된 것을 확인할 수 있습니다.

Grid 컴포넌트에 데이터 표시하기

1

Grid 컴포넌트를 화면에 배치합니다.

2

Grid 컴포넌트와 Dataset 오브젝트를 바인딩합니다.

3

Button 컴포넌트를 추가하고 아래와 같이 onclick 이벤트 함수를 작성합니다.

this.Button00_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
	this.DataObject00.load();
};

4

QuickView(Ctrl + F6)로 실행한 후 버튼 클릭 시 정보가 조회되는 것을 확인합니다.

다국어로 Button 라벨 표시하기

DataObject 오브젝트의 데이터는 외부 서비스에서 받아올 수도 있지만, 직접 편집할 수도 있습니다. 이번 예제에서는 데이터를 직접 추가하고 추가한 데이터를 2개의 Dataset 오브젝트에 바인딩해서 다른 용도로 사용합니다.

예제

Combo 컴포넌트에서 언어를 선택하면 선택한 언어로 Button 컴포넌트 라벨을 표시합니다.

sample_dataobject_02.xfdl

예제에서 사용한 핵심 기능

data

오브젝트 또는 문자열 값을 받아서 데이터 오브젝트로 처리합니다. 넥사크로 스튜디오에서는 데이터를 편집할 수 있는 도구를 제공합니다.

dataobjectpath

DataObject 오브젝트 데이터 중에서 실제 반영할 데이터를 필터링하기 위해 설정하는 값입니다. 스크립트 내에서 값을 변경하면 즉시 반영되어 처리합니다.

예제 구현 방법

JSON 데이터 작성하기

1

DataObject 오브젝트를 추가합니다.

2

data 속성 옆에 있는 버튼을 클릭하고 [Json Contents Editor]를 실행합니다.

3

(empty object)로 표시된 항목을 선택하고 [Add Item] 버튼을 클릭하면 항목이 추가되며 설정할 수 있는 상태가 됩니다.

4

type 항목을 Object 또는 Array로 변경하면 하위 아이템을 추가할 수 있습니다.

5

Source 탭을 클릭하면 JSON 코드값을 직접 입력할 수 있습니다.

예제에서는 아래와 같은 코드를 입력합니다.

{
	"code" : [
		{
			"locale" : "ko",
			"label" : "Korean"
		},
		{
			"locale" : "ja",
			"label" : "Japanese"
		},
		{
			"locale" : "en",
			"label" : "English"
		}
	],
	"data" : {
		"ko" : {
			"btn_submit" : "전송",
			"btn_save" : "저장",
			"btn_cancel" : "취소"
		},
		"ja" : {
			"btn_submit" : "送信",
			"btn_save" : "保存",
			"btn_cancel" : "キャンセル"
		},
		"en" : {
			"btn_submit" : "Submit",
			"btn_save" : "Save",
			"btn_cancel" : "Cancel"
		}
	}
}

Contents 탭에서는 아래와 같이 표시됩니다.

Combo 컴포넌트에 표시할 기준 데이터 가져오기

1

Dataset 오브젝트를 추가하고 binddataobject 속성값을 "DataObject00"으로 지정합니다.

2

속성창에서 dataobjectpath 속성 옆에 있는 버튼을 클릭하고 [Data Path Editor]를 실행합니다.

3

데이터에서 "code [3]" 항목을 선택하고 오른쪽 마우스 클릭 후 [Set Dataobject Root Path] 항목을 선택합니다.

데이터 중에서 code 배열 아래의 오브젝트 값을 Combo 컴포넌트의 innerdataset으로 사용할 겁니다.

4

DataObject Path 값이 "$.code[*]"로 설정되면 [Refresh json contents] 버튼을 클릭하고 [Filtered Contents] 탭에 아래와 같이 데이터가 표시되는 것을 확인합니다.

5

locale, label 항목을 선택하고 칼럼으로 추가한 후 에디터를 닫습니다.

6

Combo 컴포넌트를 추가합니다.

7

앞에서 설정한 Dataset 오브젝트를 Combo 컴포넌트의 InnerDataset으로 설정합니다.

codecolumn 속성값은 "locale", datacolumn 속성값은 "label"로 설정합니다.

8

QuickView(Ctrl + F6)로 실행한 후 Combo 컴포넌트의 데이터가 추가됐는지 확인합니다.

Button 컴포넌트에 연결되는 라벨 데이터 가져오기

1

Dataset 오브젝트를 추가하고 binddataobject 속성값을 "DataObject00"으로 지정합니다.

2

속성창에서 dataobjectpath 속성 옆에 있는 버튼을 클릭하고 [Data Path Editor]를 실행합니다.

3

데이터에서 "data {3}" 항목 아래에 있는 "ko {3}" 항목을 선택하고 오른쪽 마우스 클릭 후 [Set Dataobject Root Path] 항목을 선택합니다.

4

DataObject Path 값이 "$.data.ko"로 설정되면 [Refresh json contents] 버튼을 클릭하고 [Filtered Contents] 탭에 아래와 같이 데이터가 표시되는 것을 확인합니다.

5

btn_submit, btn_save, btn_cancel 항목을 선택하고 칼럼으로 추가한 후 에디터를 닫습니다.

6

Button 컴포넌트를 3개 추가합니다.

7

앞에서 설정한 Dataset 오브젝트를 Button 컴포넌트의 Bind Item으로 설정합니다. text 속성과 각 칼럼을 아래와 같이 연결합니다.

8

Combo 컴포넌트의 onitemchanged 이벤트 함수를 아래와 같이 작성합니다. 선택한 locale 항목에 따라 Button 컴포넌트에 바인딩된 Dataset 오브젝트의 dataobjectpath 속성값을 변경합니다.

this.Combo00_onitemchanged = function(obj:nexacro.Combo,e:nexacro.ItemChangeEventInfo)
{
	this.Dataset01.set_dataobjectpath("$.data."+e.postvalue);
};

9

QuickView(Ctrl + F6)로 실행한 후 Combo 컴포넌트에서 locale 항목 변경 시 Button 컴포넌트에 표시되는 텍스트가 변경되는지 확인합니다.

메소드 파라미터 지정해서 request 메소드 실행하기

load 메소드는 GET 메소드 파라미터가 설정한 상태로 동작합니다. 하지만 호출하려는 API에 따라서 POST나 PUT 등의 메소드를 설정해야 하는 경우가 있습니다. 또한 인증을 해야 하거나 데이터를 전송하는 경우 postdata를 설정해야 합니다.

예제

예제에서는 https://jsonplaceholder.typicode.com/ 에서 제공하는 데이터를 사용합니다.

Create 실행 시 실제 데이터가 생성되지는 않고 성공 여부만 반환합니다.

해당 사이트 운영 상황에 따라 예제가 실행되지 않을 수도 있습니다.

id 입력 없이 [Search] 버튼 클릭 시 전체 데이터를 조회하고 1~100 사이의 id 값을 입력하면 해당 id에 해당하는 값만 조회합니다.

userId, title, body 값을 입력하고 [Create] 버튼 클릭 시 입력한 값을 설정한 메소드 파라미터로 처리합니다. 실행 결과는 TextArea 컴포넌트에 표시합니다.

sample_dataobject_03.xfdl

예제에서 사용한 핵심 기능

request

메소드 파라미터를 지정할 수 있습니다. header, postdata, async 정보를 저장한 JSON 오브젝트를 추가로 설정할 수 있습니다.

예제 구현 방법

화면 구성하기

1

Edit, TextArea, Grid, Button 컴포넌트, Dataset, DataObject 오브젝트를 추가합니다.

2

Edit, TextArea 컴포넌트의 displaynulltext 속성값을 설정합니다.

request 메소드 준비하기

1

[Create] Button 컴포넌트의 onclick 이벤트 함수를 아래와 같이 작성합니다.

[Create] 버튼 클릭 시에는 입력한 값과 메소드 파라미터를 설정해서 처리합니다.

this.btn_Create_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
	var header = {"Content-Type" : "application/json; charset=UTF-8"};
	var strPostdata = JSON.stringify(
		{
			"userId":this.edituserId.value,
			"title":this.edittitle.value,
			"body":this.textAreabody.value
		}
	);
	this.DataObject00.request("CREATE", "POST", "https://jsonplaceholder.typicode.com/posts", 
		{
			"httpheader":header, 
			"postdata":strPostdata
		}
	);
};

2

[Search] Button 컴포넌트의 onclick 이벤트 함수를 아래와 같이 작성합니다.

[Search] 버튼 클릭시에는 "GET" 메소드 파라미터값을 설정합니다.

this.btn_Search_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
	var strId = this.editid.value;
	this.DataObject00.request("SEARCH", "GET", "https://jsonplaceholder.typicode.com/posts"+(strId?"/"+strId:""));
};

이벤트 처리하기

request 메소드 실행 시에는 onsuccess 이벤트가 먼저 발생하고 그 다음에 data 속성값에 데이터가 설정되고 onload 이벤트가 발생합니다.

1

onsuccess 이벤트 함수를 아래와 같이 작성합니다.

onsuccess 이벤트 함수 내에서는 실행된 serviceid 값을 확인하고 변수에 저장합니다.

Create 실행 시에는 statuscode가 201로 반환됩니다. 이때에는 onload 이벤트를 처리하지 않고 TextArea 컴포넌트에 결과값만 표시합니다.

var serviceid;
this.DataObject00_onsuccess = function(obj:nexacro.DataObject,e:nexacro.DataObjectEventInfo)
{
	serviceid = e.serviceid;
	trace(e.serviceid + ":" + e.statuscode);

    if (e.statuscode == 200)
        trace("getAllResponseHeaders:"+ obj.getAllResponseHeaders())
    else if(e.statuscode > 200)
    {
        e.preventDefault();
		this.TextArea00.set_value(obj.getResponse());
    }
};

2

onload 이벤트 함수를 아래와 같이 작성합니다.

onload 이벤트 함수 내에서는 바인딩할 Dataset 오브젝트의 칼럼 정보를 생성하고 binddataobject, dataobjectpath 속성을 설정합니다. Grid 컴포넌트의 binddataset 속성값을 설정하고 createFormat 메소드를 실행합니다.

this.DataObject00_onload = function(obj:nexacro.DataObject,e:nexacro.DataObjectLoadEventInfo)
{
	if(e.reason == 2)
	{
		this.Dataset00.clear();
		var objData;
		var strDataobjectpath;
		if(serviceid == "SEARCH")
		{
			if(obj.data.length > 1)
			{
				objData = obj.data[0];
				strDataobjectpath = "$[*]";
			} else {
				objData = obj.data;
				strDataobjectpath = "$";			
			}
		}
		for(var key in objData)
		{
			var objColinfo = new ColumnInfo();
			objColinfo.set_type("String");
			objColinfo.set_datapath("@."+key);
			this.Dataset00.addColumnInfo(key, objColinfo);
		}
		this.Dataset00.set_binddataobject(obj.id);
		this.Dataset00.set_dataobjectpath(strDataobjectpath);
		this.Grid00.set_binddataset(this.Dataset00.name);
		this.Grid00.createFormat();
		this.TextArea00.set_value("");
	}
};

3

onerror 이벤트 함수를 아래와 같이 작성합니다.

오류가 발생한 경우에는 onerror 이벤트 함수에서 에러 메시지를 TextArea 컴포넌트에 표시해줍니다.

this.DataObject00_onerror = function(obj:nexacro.DataObject,e:nexacro.DataObjectErrorEventInfo)
{
	trace(e.statuscode +":"+e.errormsg);
	this.TextArea00.set_value(e.statuscode +":"+e.errormsg);
};

실행 결과 확인하기

QuickView(Ctrl + F6)로 실행한 후 실행 결과를 확인합니다.

[Search] 버튼 클릭 시에는 전체 데이터를 조회합니다. 간단한 데이터 표시하기 예제와 비슷한 방식이지만, 이번 예제에서는 request 메소드를 사용했고, Dataset 오브젝트와 Grid 컴포넌트 설정을 동적으로 처리했습니다.

양방향 통신 적용하기

DataObject 오브젝트를 사용해서 가져온 데이터를 화면 내에서 수정하고 수정된 정보를 서버에 반영해야 하는 경우 양방향 통신을 적용할 수 있습니다.

Dataset 오브젝트에서 데이터가 변경되면 DataObject 오브젝트에서 이벤트가 발생하고 변경된 정보를 확인할 수 있습니다.

예제

예제에서는 https://jsonplaceholder.typicode.com/ 에서 제공하는 데이터를 사용합니다.

실행 시 실제 데이터가 수정되거나 삭제되지는 않고 성공 여부만 반환합니다.

해당 사이트 운영 상황에 따라 예제가 실행되지 않을 수도 있습니다.

  1. [Search] 버튼을 클릭하고 데이터를 조회합니다.

  2. 선택한 데이터를 수정하거나 [Delete] 버튼을 클릭해 삭제합니다.

  3. [Apply] 버튼을 클릭하면 변경된 데이터를 처리합니다.

  1. updatecontrol 체크박스를 해제해서 false 상태로 만듭니다.

  2. 선택한 데이터의 title 또는 body 칼럼 데이터를 수정합니다.

  3. PATCH 메소드 파리미터를 설정하고 request를 요청합니다 (정상적으로 요청은 보내지만 에러로 반환됩니다).

sample_dataobject_04.xfdl

예제에서 사용한 핵심 기능

ondatachanged

DataObject 오브젝트의 데이터가 변경됐을때 발생하는 이벤트입니다. EventInfo 오브젝트 내 배열 형태의 infoarray 속성값에서 변경된 데이터를 확인할 수 있습니다.

dataobjectbindmode

Dataset 오브젝트와 DataObject 오브젝트 사이의 통신 방식을 설정합니다. 속성값을 "twoway"로 설정하면 변경된 데이터 정보를 전달할 수 있습니다.

예제 구현 방법

데이터 가져오기

1

Edit, TextArea, Grid, Button 컴포넌트, Dataset, DataObject 오브젝트를 추가합니다.

2

DataObject 오브젝트의 url 속성값을 아래와 같이 설정합니다.

https://jsonplaceholder.typicode.com/posts

3

Dataset 오브젝트의 binddataobject 속성값을 설정합니다.

4

Dataset 오브젝트의 dataobjectpath 속성 옆에 있는 버튼을 클릭하고 [Data Path Editor]를 실행합니다.

5

Target Source를 URL로 체크하고 [Get] 버튼을 클릭해 데이터를 가져옵니다.

6

DataObject Path는 "$[*]"로 설정하고 새로고침 버튼을 클릭해 데이터를 확인합니다.

7

userId, id, title, body 항목을 칼럼으로 추가합니다.

8

Dataset 오브젝트를 Grid 컴포넌트에 바인딩해줍니다.

9

Edit 컴포넌트에 각 칼럼을 바인딩해줍니다.

10

[Search] 버튼 클릭 시 실행할 이벤트 핸들러 함수 코드를 작성합니다.

this.btn_Search_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
	this.DataObject00.load();
};

11

데이터 로딩 시 성공, 실패를 처리할 이벤트 핸들러 함수 코드를 작성합니다.

var serviceid;
this.DataObject00_onsuccess = function(obj:nexacro.DataObject,e:nexacro.DataObjectEventInfo)
{
	serviceid = e.serviceid;
	trace(e.serviceid + ":" + e.statuscode);

    if (e.statuscode == 200 && (e.method == "POST" || e.method == "GET"))
        trace("getAllResponseHeaders:"+ obj.getAllResponseHeaders());
	else
    {
        e.preventDefault();
		this.TextArea00.insertText("=================="+"\n");
		this.TextArea00.insertText(e.serviceid + ":" + e.statuscode+"\n");
		this.TextArea00.insertText(obj.getResponse()+"\n");		
    }
};

this.DataObject00_onerror = function(obj:nexacro.DataObject,e:nexacro.DataObjectErrorEventInfo)
{
	trace(e.statuscode +":"+e.errormsg);
	this.TextArea00.deleteText();
	this.TextArea00.insertText("=================="+"\n");
	this.TextArea00.insertText(e.statuscode +":"+e.errormsg+"\n");
};

12

QuickView(Ctrl + F6)로 실행한 후 데이터가 조회되는지 확인합니다.

양방향 통신 설정하기

1

Dataset 오브젝트의 dataobjectbindmode 속성값을 "twoway"로 설정합니다.

2

userId, id를 표시하는 Edit 컴포넌트의 readonly 속성값을 true로 설정합니다.

userId, id는 업데이트 시 키값으로 사용하기 때문에 수정할 수 없도록 설정합니다.

3

[Delete] 버튼 클릭 시 선택한 Row를 삭제하기 위해 이벤트 핸들러 함수를 작성합니다.

this.btn_Delete_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
	this.Dataset00.deleteRow(this.Dataset00.rowposition);
};

4

데이터 수정, 삭제 후 변경된 상태를 처리하기 위해 [Apply] 버튼 클릭 시 applyChange 메소드를 실행하도록 이벤트 핸들러 함수를 작성합니다.

this.btn_Apply_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
	this.Dataset00.applyChange();
};

applyChange 메소드가 실행되면 DataObject 오브젝트에 변경 정보가 전달되며 ondatachanged 이벤트가 발생합니다.

5

ondatachanged 이벤트 핸들러 함수를 아래와 같이 작성합니다.

this.DataObject00_ondatachanged = function(obj:nexacro.DataObject,e:nexacro.DataObjectDataChangedEventInfo)
{
   var updatelist = e.infoarray;
   for (var i =0; i<updatelist.length; i++)
   {
		var item = updatelist[i];
		var uid = item.uid;
		var method = (item.type == "update")?"PUT":"DELETE";
		var senddata = JSON.stringify(item.data);	
		var id = item.data.id;
		var param = {
			'httpheader' : {'Content-Type': 'application/json; charset=UTF-8'}, 
			'postdata' : senddata 
		}
		if(method == "PUT")
		{
			this.DataObject00.request(uid, method, this.DataObject00.url+"/"+id, param);
		} else {
			this.DataObject00.request(uid, method, this.DataObject00.url+"/"+id);
		}
	}
};

예를 들어 2개 데이터를 수정하고 1개 데이터를 삭제한 후 실행했을 때 EventInfo 오브젝트를 살펴보면 아래와 같은 형태입니다.

infoarray 배열에 3개의 데이터가 담겨있고 type 정보가 변경된 data 정보를 확인할 수 있습니다. ondatachanged 이벤트 핸들러 함수에서는 해당 데이터 길이만큼 반복하며 서버에 업데이트 또는 삭제 요청을 처리합니다.

6

QuickView(Ctrl + F6)로 실행한 후 데이터를 조회한 후 데이터를 수정하거나 삭제하고 [Apply] 버튼 클릭 시 데이터가 전송되는 것을 확인할 수 있습니다.

데이터 변경 시 바로 처리하기

위의 예제에서는 Dataset 오브젝트의 applyChange 메소드 실행 이후 데이터를 처리했는데 데이터 변경 시 바로 처리하도록 기능을 추가해보겠습니다.

1

화면에 CheckBox 컴포넌트를 추가해줍니다.

2

CheckBox 상태 변경 시 Dataset 오브젝트의 updatecontrol 속성값을 변경하도록 이벤트 핸들러 함수를 작성합니다.

this.CheckBox00_onchanged = function(obj:nexacro.CheckBox,e:nexacro.CheckBoxChangedEventInfo)
{
	this.Dataset00.set_updatecontrol(e.postvalue);
};

Dataset 오브젝트의 updatecontrol 속성값이 false인 경우 특정 칼럼 데이터 변경 시 DataObject 오브젝트에 변경 정보가 전달되며 onvaluechanged 이벤트가 발생합니다.

3

onvaluechanged 이벤트 핸들러 함수를 아래와 같이 작성합니다.

this.DataObject00_onvaluechanged = function(obj:nexacro.DataObject, e:nexacro.DataObjectValueChangedEventInfo)
{
	var id = obj.getObjectByPath(e.dataobjectpath)[e.index]["id"];
	var uid = e.uid;
	var method = "PATCH";
	var objddata = {};
	objddata[e.key] = e.value;
	var senddata = JSON.stringify(objddata);
	
    var param = {
		'httpheader' : {'Content-Type': 'application/json; charset=UTF-8'}, 
		'postdata' : senddata 
	}
	this.TextArea00.deleteText();
	this.DataObject00.request(uid, method, this.DataObject00.url+"/"+id, param);
};

예를 들어 3번째 Row의 title 항목을 수정했을 때 EventInfo 오브젝트를 살펴보면 아래와 같은 형태입니다.

변경된 index 정보와 key, value 값을 확인할 수 있습니다. onvaluechanged 이벤트 핸들러 함수에서는 해당 데이터에 대한 업데이트를 요청합니다.

현재 예제에서 사용하는 https://jsonplaceholder.typicode.com/ 서버에서 PATCH 메소드 사용을 제한하고 있습니다. 때문에 PATCH 메소드 설정 후 request 실행 시 에러가 발생합니다.

onvaluechanged 이벤트 핸들러의 동작 방식을 설명하기 위한 예제로 참고해주세요.