본문으로 건너뛰기

10. 로직 & 스크립팅

기본 구조 이해

  • 스크립트는 순수 JavaScript(ES6+)입니다 → 표준 언어 기능이 모두 그대로 동작합니다:
    • 조건문(if/else, switch)
    • 반복문(for, while)
    • 삼항 연산자
    • 배열과 객체
    • JSON.parse, JSON.stringify
    • 표준 문자열·수학 연산
  • 페이지의 라이프사이클은 라이프사이클 이벤트로 관리합니다. 전역 객체로는 데이터, 화면 이동, 애니메이션을 다룹니다. 위젯 객체로는 위젯의 속성을 조작해 겉모습을 세밀하게 제어하고, 다른 위젯에서 일어난 사용자 조작에 따라 그 모습이나 동작을 바꿉니다. 이 셋을 함께 사용해 페이지에 생명을 불어넣습니다.

라이프사이클 이벤트

  • 화면이 생성되고, 사용되고, 닫히는 흐름에 맞춰 Lucy가 자동으로 호출하는 콜백이 있습니다.
함수호출 시점과 역할
onStart(arg)화면이 시작될 때 가장 먼저 호출됩니다. 여기서 데이터를 초기화하고 이벤트 바인딩을 설정합니다.
onClose()화면이 닫힐 때 호출됩니다. 자원을 해제하고 정리 작업을 수행합니다.
onReceiveDone()데이터 수신이 성공적으로 끝나면 호출됩니다. 받은 데이터로 UI를 갱신합니다.
onReceiveError()데이터 수신이 실패하면 호출됩니다. 네트워크 오류 같은 예외를 처리합니다.

전체 라이프사이클 이벤트 목록과 각 이벤트의 상세 설명은 11. 스크립트 API 문서의 LifeCycle Events 섹션을 참고하세요.

전역 객체

  • 전역 객체는 Lucy Studio가 미리 만들어 제공하는 객체입니다. import나 별도 설정이 필요 없고, 앱 전체에서 공유되며 언제든 바로 사용할 수 있습니다.
전역 객체제어 대상
$app앱 전체 동작: 화면 이동, 다이얼로그, 저장된 데이터, 테마, 기기 정보
$form현재 화면과 폼: 변수, 메시지 전달, 화면 이동
$vm데이터: 데이터 소스 읽기·쓰기, 데이터 요청과 구독
$http외부 API로 보내는 네트워크 요청(get, post, put 등)
$log디버깅용 로그 메시지 출력(d, i, w, e)
$mqtt실시간 메시지 통신(connect, subscribe, publish)
$act'animation mode' 탭에 등록한 액션이나 상태 전환 실행
$log.d("Button was tapped!"); // 디버그 로그 출력

$app.openPage("dashboard"); // dashboard 페이지로 이동

$http.get("https://api.example.com/user", function(res) {
$log.i(res); // 응답을 사용해 처리
});

각 전역 객체($app, $form, $vm, $act, $log, $http, $mqtt)의 전체 메서드와 속성은 11. 스크립트 API 문서의 Global Objects 섹션에서 확인하세요.

위젯 객체 제어

  • 캔버스 영역에 배치한 특정 위젯을 가리킵니다 — Button, Text, Checkbox 등입니다. 이 객체는 자신이 속한 화면에만 존재하며, ID로만 접근할 수 있습니다. 모든 위젯 객체는 속성, 메서드, 이벤트라는 세 종류의 멤버로 기능을 제공합니다. 이 셋을 이해하면 어떤 위젯이든 스크립트로 다룰 수 있습니다 — 패턴을 한 번 익히면 모든 위젯이 같은 방식으로 동작합니다.

위젯별 전체 속성·메서드·이벤트 목록은 11. 스크립트 API 문서의 Widget 섹션(Widget and Component Reference)에서 확인하세요.

  1. 속성: 위젯의 상태를 읽고 바꿉니다 — 사용자 이벤트에 따라 속성을 설정하거나 가져올 수 있습니다(예: Button을 클릭해 지정한 Text의 색상을 바꿉니다).

    1. 속성은 여러 메서드로 설정하고 가져올 수 있습니다. 단축 메서드가 없는 속성은 .setProperty와 .getProperty를 사용합니다. 설정하거나 가져올 속성을 매개변수로 넘깁니다.

      // 속성 이름을 매개변수로 넘겨 특정 속성을 설정합니다
      // 속성 이름을 매개변수로 넘겨 특정 속성을 가져옵니다
      textWidgetId.setProperty(propertyName, value);
      textWidgetId.getProperty(propertyName);

      textWidgetId.setProperty("text", "Hello World");
      var textProp = textWidgetId.getProperty("text");

      // 자주 쓰는 일부 속성에는 단축 메서드도 있습니다(아래 Methods 참고).
      // 예를 들어 .setText("Hello World")는
      // .setProperty("text", "Hello World")의 단축형입니다. 모든 속성에
      // 단축 메서드가 있는 것은 아니므로, 없을 때는 .setProperty / .getProperty를 사용합니다.
    2. 스크립트로 스타일 속성도 설정하고 가져올 수 있습니다 — SizedBox, Padding, DecoratedBox 같은 속성입니다. 스크립트에서 다루려면 해당 스타일 속성이 위젯에 이미 적용되어 있어야 하며, 그렇지 않으면 스크립트가 아무 효과를 내지 않습니다.

      // 스타일 속성을 설정하려면 그 스타일이 이미 적용되어 있어야 합니다
      widgetId.setStyleProperty(styleName, styleProperty, value);
      widgetId.getStyleProperty(styleName, styleProperty);

      // 색상을 설정할 때는 hex 값을 쓰거나
      // color theme에 등록한 색상 이름을 쓸 수 있습니다
      widgetId.setStyleProperty("DecoratedBox", "decoration.color", "#FFFFFF");
      widgetId.getStyleProperty("DecoratedBox", "decoration.color");
  2. 메서드: 위젯에 내장된 동작으로, 주로 괄호를 붙여 호출합니다 — 위젯에 무엇을 할지 지시합니다. 인자를 넘길 수 있고, 일부 메서드는 결과를 반환해 저장할 수 있습니다.

    위젯메서드
    TimerwidgetId.start();
    CalendarwidgetId.goToToday();
    ListViewwidgetId.insert(index);
    Text(속성 단축 메서드)widgetId.setText(”Hello World”);
    • 참고: 각 위젯에서 사용할 수 있는 속성·메서드·이벤트의 전체 목록은 Properties, Methods & Events 레퍼런스 전체를 참고하세요: 11. 스크립트 API 문서
  3. 이벤트: 함수를 할당하는 대상입니다

    • 사용자가 위젯을 조작하면 이벤트가 발생합니다. 이에 반응하려면 이벤트에 함수를 할당합니다. 그러면 이벤트가 발생할 때마다 Lucy가 그 함수를 실행합니다. 일부 함수는 매개변수를 받으므로, 이를 추가 처리에 활용할 수 있습니다.
    • 페이지가 사용자에게 반응하는 주된 방식입니다. 전체 이벤트 목록과 전달되는 인자, 실제 바인딩 예시는 다음 절 이벤트 처리에서 확인하세요.

이벤트 처리: 탭, 입력 변경 등

바인딩 동작 방식

  • 사용자가 위젯을 조작하면 이벤트가 발생합니다. 이에 반응하려면 이벤트에 함수를 할당합니다. 그러면 이벤트가 발생할 때마다 Lucy가 그 함수를 실행합니다.
  • 바인딩은 항상 onStart 함수 안에서 설정합니다. 그러면 페이지가 초기화될 때 함수가 바로 이벤트에 연결됩니다.
  • onChanged, onSelected, onSubmitted 같은 이벤트는 핸들러에 인자를 넘길 수 있다는 점에 유의합니다(예: value, index, date).

자주 쓰는 위젯 이벤트

  • 위젯에 이미 지정된 이벤트가 있으면, 그 위젯을 클릭할 때 Properties 패널에 표시됩니다. 이런 이벤트는 보통 'on'으로 시작합니다. 아무 이벤트도 보이지 않으면 그 위젯에는 지정된 이벤트가 없다는 뜻이며, 이때는 onTap 이벤트를 사용할 수 있습니다.
위젯이벤트전달되는 인자
ButtononClick
Checkbox, TextFieldonChangedvalue
TextFieldonSubmittedvalue
ListViewonSelectedindex
Text, Icon, Row, Column 등onTap

위젯 타입별 상세 목록

그룹이벤트
Button·선택 계열onClick, onSelected
텍스트 입력(TextField)onChanged, onSubmitted, onEditingComplete, onTap, onFocusOut
토글·피커onChanged (Checkbox, Switch, DropDown, Slider, Radio)
슬라이더onChangeStart, onChangeEnd
리스트·스크롤onScrollEnd, onReorder, onOverflowChanged
화면 이동·시간onPageChanged, onDateSelected, onExpired (Timer)

핸들러 바인딩

  • 이벤트에 함수를 연결하는 방법은 두 가지입니다. 인라인으로 정의하거나, 따로 선언한 뒤 이름으로 참조합니다 — 두 방식은 동일하게 동작합니다.
// 1) 인라인: onStart() 안에서 핸들러를 직접 정의합니다
function onStart() {
widgetId.onClick = function() {
$log.d("submit tapped");
};

widgetId.onChanged = function(value) {
$log.d("field is now: " + value);
}
}

// ================================================================
// 2) 분리: 함수를 선언하고 이름으로 참조합니다
function onStart() {
widgetId.onClick = button_onClick;
widgetId.onChanged = checkbox_onChanged;
}

function button_onClick() {
$log.d("button clicked!");
}

function checkbox_onChanged(value) {
$log.d("field is now " + value);
}

조건 분기, 반복, 유틸 함수 사용

자주 쓰는 패턴 (스크립트에서 쓰는 JavaScript 기초)

JavaScript가 처음이라면, 아래 예시로 표준 언어 기능을 핸들러 안에서 어떻게 쓰는지 확인하세요. 이미 익숙하다면 넘어가도 됩니다 — 순수 JavaScript이므로 따로 익혀야 할 전용 문법은 없습니다.

조건문 — 조건이 충족될 때만 무언가를 실행합니다(예: Checkbox 값을 읽어 다른 위젯을 보이거나 숨깁니다).

function checkbox_onChanged(value) {
if(value === true) {
detailsBox.setProperty("visible", true);
detailsBox.visible = true; // visible 속성은 이렇게 설정해도 됩니다
} else {
detailsBox.setProperty("visible", false);
detailsBox.visible = false; // visible 속성은 이렇게 설정해도 됩니다
}
}

삼항 연산자 — 두 값 중 하나를 반환하는 짧은 if/else입니다.

function checkbox_onChanged(value) {
// 체크되어 있으면 "On", 그렇지 않으면 "Off"를 표시합니다
statusLabel.setText(value === true ? "On" : "Off");
}

반복문 — 동작을 반복합니다. 예를 들어 리스트에 여러 행을 추가합니다.

function onStart() {
var fruits = ["Apple", "Banana", "Cherry"];
for (var i = 0; i < fruits.length; i++) {
$log.d("Item " + i + ": " + fruits[i]);
}
}

객체와 JSON 다루기 — 응답을 파싱한 뒤 필드를 읽습니다.

function onStart() {
var jsonText = '{ "name": "Jane", "age": 30 }';
var user = JSON.parse(jsonText); // 텍스트 -> 객체
nameLabel.setText(user.name); // "Jane"

var backToText = JSON.stringify(user); // 객체 -> 텍스트
$log.d(backToText);
}

공유한 스크립트 사용

공유 모듈 만들기

프로젝트가 커지면 여러 화면에서 같은 스크립트 블록(로그인, 헬퍼 함수 등)이 필요해집니다. 같은 코드를 페이지마다 스크립트 창에 복사해 붙이는 대신, 공유할 수 있는 스크립트 파일에 넣어 둡니다. 그 파일의 코드를 가져오면 거기 선언한 함수를 여러 화면에서 사용할 수 있습니다.

  • Script 탭에서 새 .js 파일을 만듭니다(예: common.js).
  • 이 파일은 다른 스크립트와 함께 프로젝트의 script 에셋 폴더에 저장됩니다.
  • 가져오는 쪽 파일에서는 require('jsFileName')맨 위에 두고, 파일 이름을 매개변수로 넘깁니다.
  • 가져올 수 있는 파일 수에는 제한이 없습니다.
  • 함수는 다음과 같이 선언합니다:
const Util = {
getToday : function() {
let today = new Date();
return today;
},
getTime : function() {
let today = new Date();

let hour = ("0" + today.getHours()).slice(-2); // 시
let min = ("0" + today.getMinutes()).slice(-2); // 분
let sec = ("0" + today.getSeconds()).slice(-2); // 초

return hour+ "" +min+ "" +sec;
}
}

가져오기 — 스크립트 맨 위, 다른 코드보다 앞에 두고 필요한 곳에서 호출합니다:

require('common.js');

function onStart() {
button.onClick = setCurrentTime;
}

function setCurrentTime() {
let time = Util.getTime(); // Util은 common.js에서 가져온 것입니다

time_txt.setProperty("text", time);
}

스크립트 디버깅

자주 쓰는 디버깅 패턴

함수가 호출되는지 확인하기

가장 간단한 확인 방법입니다 — 실행되지 않는 것 같은 함수 맨 위에 로그를 추가합니다:

function myButton_onClick() {
$log.d("myButton_onClick fired");
// 나머지 로직
}

데이터 흐름 추적하기

주요 동작 전후에 로그를 남겨 데이터가 어디서 바뀌거나 멈추는지 찾습니다:

$log.d("before sort: " + $vm.getDSValue("myDS.body.items[0].title"));
$vm.sortString("myDS", "body.items.title", "ascending");
$log.d("after sort: " + $vm.getDSValue("myDS.body.items[0].title"));