서버 측 스크립팅

서버 측 스크립트는 자바스크립트에서 Google Apps Script 스크립트로 실행됩니다. 이는 Apps Script APIApp Maker의 서버 측 객체 및 API에 대한 액세스 권한이 있습니다. Google Advanced Services는 사용 설정해야 사용할 수 있습니다.

서버 측 스크립팅 기본사항

시간 소모적인 계산을 수행해야 하는 경우(UI 차단을 방지하기 위해) 또는 크기가 크거나 보안 문제로 인해 클라이언트에 전송하지 않으려는 정보에 액세스해야 하는 경우 서버 측 스크립트를 사용해야 합니다.

서버 스크립트 호출

서버 스크립트를 호출하려면 google.script.run을 사용합니다. 자세한 내용은 클라이언트 측 스크립팅 문서를 참조하세요.

매개변수 및 반환 값

값은 google.script.runwithSuccessHandler(function) 메소드에서 반환됩니다. 유효한 매개변수 및 반환 값은 Number, Boolean, String과 같은 자바스크립트 기본 요소와 기본 요소, 객체, 배열로 구성된 자바스크립트 객체 및 배열입니다.

예를 들어 Date 객체, Function, Record, App Maker 위젯을 전달하려고 시도하는 경우 요청에 실패합니다. 더 복잡한 객체를 전달하는 일반적인 전략 중 하나는 JSON.stringifyJSON.parse를 사용하는 것입니다.

서버 스크립트 숨기기

서버 스크립트에서 정의하는 함수는 UI에서 노출하지 않는 경우에도 애플리케이션의 모든 사용자에게 표시됩니다. 다른 서버 스크립트에서 호출할 수 있는 유틸리티 함수를 작성하려는 경우 이름에 밑줄을 추가해야 합니다. 예를 들어 다음 메소드는 공개이므로 클라이언트가 전달된 사용자의 급여를 가져올 수 있습니다.

function calculateUserSalary(user) {
  // Gets the salary of the user...
  return salary;
}

위와 달리 다음과 같이 표시되어야 합니다.

function calculateUserSalary_(user) {
  // Gets the salary of the user...
  return salary;
}

보안

서버 스크립트를 숨기는 것이 유용하지만 경우에 따라 서버 스크립트가 민감한 데이터를 클라이언트에 노출해야 할 수도 있습니다. 이 경우 스크립트에 보안을 설정하는 것이 중요합니다. 모델 및 뷰에 권한이 있지만 서버 스크립트의 경우에는 직접 구현해야 합니다. 위의 예를 사용하여 사용자가 호출할 수 있지만 사용자가 직접 요청하거나 관리자가 요청하는 경우에만 사용자의 급여를 반환한다고 가정해 보겠습니다.

function calculateUserSalary(user) {
  var currentUser = Session.getActiveUser().getEmail();
  if (currentUser !== user && !isManager(currentUser, user) {
    throw new Error(currentUser +
        " does not have access to salary for " + user);
  }

  // Gets the salary of the user...
  return salary;
}

데이터 다루기

서버 스크립트를 사용하면 App Maker 모델과 일반적인 방식으로 상호작용할 수 있습니다. 이를 통해 새 레코드를 만들거나 쿼리하거나 관계를 수정할 수 있습니다.

레코드 만들기

// Assume a model called "Fruits" with a string field called "Name".
var newRecord = app.models.Fruits.newRecord();
newRecord.Name = "Kiwi";  // properties/fields can be read and written.
app.saveRecords([newRecord]);  // The changes won't be committed to the
                               // database unless you remember to save.

레코드 쿼리

var query = app.models.Person.newQuery();
query.filters.Name._equals = "John";

var records = query.run();
console.log("Found " + records.length + " Johns.");

for (var i in records) {
    var person = records[i];
    console.log("Found person named John " + person.FamilyName);
}

관계 작업

다음 예에서는 관련 레코드를 만들고 쿼리하는 방법을 보여줍니다. '국가' 모델과 다대일 관계가 있는 '주소' 모델이 있다고 가정해 보겠습니다.

var address1 = app.models.Address.newRecord();
address1.zip = 94040;
var address2 = app.models.Address.newRecord();
address2.zip = 94041;
app.saveRecords([address1, address2]); // Save created records.

var query = app.models.Country.newQuery();
query.filters.Name._equals = countryName;
var country = query.run()[0];

country.Address.push(address1, address2);
app.saveRecords([country]); // Save updated relation.

아래 코드 스니펫에서와 같이 관련 필드로 필터링할 수도 있습니다.

function addressesForCountry(countryName) {
  var query = app.models.Address.newQuery();
  query.filters.Country.Name._equals = countryName;

  var records = query.run();
  return records;
};

자세한 내용은 관계 필터링 섹션에서 확인할 수 있습니다.

CloudSQL 트랜잭션 제어

다음 예에서는 서버 스크립트를 사용하여 Cloud SQL 트랜잭션을 제어하는 방법을 보여줍니다. 이 API를 사용하면 다음을 수행할 수 있습니다.

  • 트랜잭션 시작 및 관련 레코드 잠금 설정
  • 데이터베이스에 새 변경사항 적용
  • 트랜잭션 롤백
function submitOrder(orderKey) {

  // Sets a rollback point and starts a new transaction.
  app.transaction.cloudSql.start();

   // Locks all records that are read in the transaction until the end of the transaction.
  app.transaction.cloudSql.setLockOnRead(app.transaction.cloudSql.lockOnRead.UPDATE);

  var orderQuery = app.models.Order.newQuery();
  orderQuery.filters._key._equals = orderKey;
  var order = orderQuery.run()[0];

  // Read related order items
  var orderItems = order.OrderItems;

  var products = [];
  for (var i = 0; i < orderItems.length; i++) {
    // Read related product
    var product  = orderItem.Product;

    if (product.InStockQuantity < orderItem.Quantity) {
      // Insufficient stock to complete an order; transaction is rolled back.
      app.transaction.cloudSql.rollback();
      throw new app.ManagedError("Not enough " + product.Name + " in stock. " +
                                 product.InStockQuantity + " Order: " +
                                 orderItem.Quantity + " can't be completed.");
    }

    // Reduce inStock quantity
    product.InStockQuantity = product.InStockQuantity - orderItem.Quantity;
    products.push(product);
  }

  order.Status = "Submitted";
  app.saveRecords(products);
  app.saveRecords([order]);

  // Order is successfully processed; database changes committed.
  app.transaction.cloudSql.commit();

  return "Order submitted: " + orderKey;
}

문제해결

App Maker는 입력할 때 구문 오류를 표시하고 빨간색으로 강조 표시합니다. 또한 일반적인 문제(예: 사용되지 않은 변수)를 감지하여 경고로 보고합니다.

스크립트가 예상대로 작동하지 않는 경우도 있습니다. 이 경우 App Maker가 관련 정보를 로깅하는 데 사용할 수 있는 console 객체를 제공합니다, 예를 들면 다음과 같습니다.

function getRecordsForCurrentUser() {
  var currentUser = Session.getActiveUser().getEmail();
  var query = app.models.Person.newQuery();
  query.filters.Email._equals = currentUser;

  var records = query.run();
  console.log("Found " + records.length + " records for " + currentUser);
  return records;
};

로그는 애플리케이션 배포마다 별도로 볼 수 있습니다.