본문으로 건너뛰기

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"));