클라이언트 스크립팅

클라이언트 스크립트는 사용자 컴퓨터에서 브라우저의 자바스크립트 런타임에서 실행됩니다. 이는 UI 이벤트를 처리하고 DOM 요소 및 위젯 속성을 변경하는 데 효과적입니다.

또한 클라이언트 스크립트는 App Maker API를 통해 서버와의 상호작용을 트리거할 수도 있습니다. 예를 들어 클라이언트 스크립트는 데이터베이스에서 데이터를 가져와서 수정하거나 서버 스크립트를 호출할 수 있습니다.

비동기 작업 및 콜백 함수

클라이언트 스크립트는 앱 사용자 인터페이스(UI)의 응답성을 유지하기 위해 App Maker에서 비동기식으로 실행될 수 있습니다. 일부 브라우저 앱에서는 작업이 외부 리소스에 대해 대기해야 하는 경우 전체 앱이 함께 대기합니다. UI도 대기하고 응답하지 않습니다.

비동기 코드를 사용하면 UI 및 기타 앱 작업의 응답성이 유지되지만 스크립트는 작성된 순서로 실행되지 않을 수 있습니다. 작업 결과를 처리하는 코드와 같은 비동기 작업이 완료된 후 스크립트를 실행하려면 콜백 함수를 사용하세요.

콜백 함수는 작업이 완료될 때 실행되는 클라이언트 스크립트입니다. 작업이 성공할 때 실행되는 함수나 성공 및 실패 시나리오에 다른 함수를 실행하는 객체를 지정할 수 있습니다.

성공 전용 콜백 함수

성공 전용 콜백 함수를 포함시키면 작업이 성공한 경우에만 콜백 함수가 실행됩니다. 작업이 실패하면 아무 것도 실행되지 않습니다. 간단한 예로 createItem ()과 비동기식으로 레코드를 만들고 이에 대한 알림을 전송할 수 있습니다.

widget.datasource.createItem(function (record) {
  alert('Record with ID ' + record.id + ' was created in the database.');
});

성공 및 실패 콜백 함수

이전 사례의 확장으로, 이 메소드를 사용하여 실패를 알리고 오류 보고, 삭제, 롤백을 수행합니다.

widget.datasource.createItem({
  success: function (record) {
    alert('Record with ID ' + record.id + ' was created in the database.');  // executes if record was created
  },
  failure: function (error) {
    console.info("No new record for you!"); // executes if record wasn't created
  }
});

콜백 함수 없음

콜백을 생략하거나 null을 콜백으로 전달하는 경우 작업이 완료될 때까지 기다리지 않고 코드가 계속 작동합니다. 예를 들면 다음과 같습니다.

    widget.datasource.createItem();
    console.info("warning, record is probably not yet created!");

문제해결

다음은 오류를 찾고 수정하여 클라이언트 스크립트 문제를 해결하는 몇 가지 전략입니다.

  • 스크립트 편집기에서 구문 오류를 찾습니다. App Maker 스크립트 편집기는 입력과 동시에 구문 문제를 자동으로 경고합니다. 스크립트의 줄 번호 왼쪽에 있는 경고 라벨을 확인합니다. 경고를 통해 괄호 누락과 같은 일반적인 오류를 발견합니다.

  • 브라우저의 자바스크립트 콘솔에서 런타임 오류를 찾습니다. 앱의 미리보기 인스턴스 또는 배포된 버전을 열고 브라우저의 자바스크립트 콘솔을 엽니다. Chrome의 경우 Ctrl+Shift+j 또는 Alt-Cmd-j를 눌러서 자바스크립트 콘솔을 엽니다. 일반적인 런타임 예외는 null 역참조 또는 확인되지 않은 예외 throw 문입니다. debugger; 문을 스크립트에 추가하여 스크립트 실행을 중지하고 문제 영역을 확인할 수 있습니다(debugger; 문을 적용하려면 DevTools를 열어야 함). 자세한 디버깅 방법은 Chrome DevTools에서 자바스크립트 디버깅 시작하기를 참조하세요.

  • 로그 및 알림을 사용하여 스크립트의 실행을 추적합니다. 브라우저의 기본 제공 console.log() 함수를 사용하여 로그를 자바스크립트 콘솔에 전송합니다. 또는 alert()를 사용하여 스크립트를 닫을 때까지 스크립트 실행을 중지하는 알림 상자를 엽니다.

클라이언트 스크립트의 예

결합 표현식에서 스크립트 사용

자바스크립트를 사용하여 결합 표현식에서 계산을 수행할 수 있습니다. 예를 들어 Name 필드가 비어 있거나 Age 필드의 값이 18 미만인 경우 버튼의 enabled 속성에서 다음 표현식이 비활성화됩니다.

(@widget.parent.children.NameTextBox.value).length != 0 &&
@widget.parent.children.AgeTextBox.value >= 18

App Maker 파서는 먼저 @로 시작되는 결합 표현식을 해석하여 NameAge 값을 찾습니다. 그러면 이 값이 표현식에서 해당 값을 대체하고 나머지 자바스크립트를 평가합니다.

첫 번째 줄의 괄호는 결합 표현식의 끝을 나타냅니다. 괄호가 없으면 App Maker에서 value 속성이 아니라 변경할 length 속성을 사용하게 됩니다.

서버 스크립트 호출

App Maker API를 사용하여 클라이언트 스크립트에서 서버 스크립트를 호출할 수 있습니다. 서버 스크립트 호출은 비동기 작업이므로 스크립트 결과를 처리하려면 콜백을 사용해야 합니다.

아래 클라이언트 스크립트는 서버 스크립트를 호출하여 Google 주식의 현재 가격을 가져온 다음 콜백을 사용하여 결과를 알림 메시지로 표시합니다.

클라이언트 스크립트:

function getGoog() {
  google.script.run.withSuccessHandler(function(result) {
    var quote = result.trim().split("\n").pop().split(",").pop();
    alert(quote);
  }).getGoogleStockInfo();
}

서버 스크립트:

function getGoogleStockInfo() {
  var url = "https://www.google.com/finance/getprices?f=d,c&q=GOOG";
  var response = UrlFetchApp.fetch(url);
  return response.getContentText();
}

외부 스크립트 동적 로드

많은 타사 스크립트를 외부 자바스크립트 라이브러리와 동기식으로 로드할 수 있지만 일부 스크립트는 추가 작업이 필요합니다. Google API 클라이언트 라이브러리와 같은 콜백 매개변수가 필요한 라이브러리는 스크립트를 Settings > General > onAppStart에 추가하여 동적으로 로드해야 합니다.

다음 스크립트는 Google+ 라이브러리를 로드합니다.

// Suspends app loading until after the Google Client API loads.
loader.suspendLoad();
// Defines a callback function, for the client API. It must be global,
// so it's explicitly attached to the window object.
window.OnGapiClientLoad = function() {
  // Uses the Google Client API to load the Google+ library.
  gapi.client.load("plus", "v1", function() {
    // Continues loading the app once Google+ loads.
    loader.resumeLoad();
  });
};

var script = document.createElement("script");
script.setAttribute("type", "text/javascript");

// Specifies the name of the callback function in the "onload"
// parameter of the URL.
var url = "https://apis.google.com/js/client.js?onload=OnGapiClientLoad";
script.setAttribute("src", url);

document.getElementsByTagName("head")[0].appendChild(script);

Google API 호출

다음은 보다 자세히 살펴볼 수 있는 마지막 예로 실제 App Maker 스크립트가 어떻게 표시되는지를 보여줍니다. 이는 Google JavaScript API를 사용합니다.

스크립트는 Google 지도를 페이지에 표시하고 사용자 입력을 기반으로 업데이트합니다. 스크립트는 다음 위젯을 포함하는 지도라는 페이지에서 작동합니다.

  • StreetZip이라는 2개의 텍스트 필드
  • loadMaps()를 호출하는 onAttach 이벤트가 있는 MapDiv라는 200x200 HtmlArea
  • updateMap()을 호출하는 onClick() 핸들러가 있는 버튼

스크립트:

var map;
var geocoder;
var marker;

// Called by loadMaps() to set up widgets.
function createMap() {
  var div = app.pages.Map.descendants.MapDiv.getElement();
  map = new google.maps.Map(div, {
    center: new google.maps.LatLng(-34.397, 150.644),
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    zoom: 10,
  });
  geocoder = new google.maps.Geocoder();
  marker = new google.maps.Marker({map: map});
}

// Returns an address string from Street and Zip text fields.
function getAddress() {
  var page = app.pages.Map;
  var street = page.descendants.Street.value;
  var zip = page.descendants.Zip.value;
  return street + ", " + zip;
}

// Positions the map at the given location coordinates.
function showLocation(locations, status) {
  if (locations.length > 0) {
    var latLng = locations[0].geometry.location;
    map.panTo(latLng);
    marker.setPosition(latLng);
  }
}

// Sets up the Google Maps library.
function loadMaps() {
  google.load("maps", "3", {callback: createMap});
}

function updateMap() {
  geocoder.geocode({address: getAddress()}, showLocation);
}

스크립트 하이라이트:

  • MapDiv는 onAttach() 핸들러를 사용하여 Google Maps API를 설정합니다.
  • 스크립트는 getAddress()를 사용하여 Street 및 Zip 필드에서 데이터를 가져와서 사용자 입력에 액세스합니다.