클라이언트 측 웹 앱의 Earth Engine API

이 가이드에서는 Earth Engine에서 즉석으로 계산된 결과를 표시하는 대화형 지도가 포함된 웹페이지를 빌드하는 방법을 보여줍니다. 이 가이드는 HTML, CSS, JavaScript에 관한 초급 또는 중급 수준의 지식이 있는 사용자에게 적합합니다.

다음은 이 가이드에서 만들 대화형 지도의 데모입니다. Earth Engine에서 계산된 그랜드 캐니언의 지형 경사를 다양한 회색 음영으로 나타냅니다. 지도를 이동하고 확대/축소하여 추가 영역의 결과를 계산하고 표시할 수 있습니다. 데모에 로그인해야 합니다.

여기에 설명된 접근 방식은 일반적으로 단일 페이지 애플리케이션 (SPA) 을 만들 때 사용됩니다. SPA에서는 서버에서 페이지를 새로고침하지 않고도 웹브라우저에서 전체 앱을 사용할 수 있습니다. 따라서 이러한 앱에는 맞춤 서버 측 구성요소의 개발 및 호스팅이 필요하지 않습니다.

앱의 코드는 사용자의 웹브라우저에서 실행되므로 (클라이언트 측 실행이라고도 함) 개발자는 서비스 계정 비공개 키와 같은 민감한 사용자 인증 정보를 애플리케이션에 직접 삽입해서는 안 됩니다. 대신 애플리케이션 사용자는 Earth Engine 액세스를 위해 등록된 자체 계정을 사용하여 인증해야 합니다.

이 가이드에서는 다음과 같은 내용을 살펴봅니다.

  1. 사용자가 Earth Engine 계정을 사용하여 로그인할 수 있는 버튼을 표시합니다.
  2. Earth Engine에서 기본 분석을 정의합니다.
  3. Maps JavaScript API를 사용하여 결과를 표시하는 대화형 지도를 삽입합니다.

기본 요건

Cloud 프로젝트 설정

  1. 시작하기 전에 Earth Engine 지원 Cloud 프로젝트 설정의 안내를 따르세요. 'OAuth 2.0 설정' 섹션에서 가져온 클라이언트 ID를 기록해 둡니다. 애플리케이션에서 사용자가 자체 Google 계정으로 로그인할 수 있으므로 '서비스 계정 만들기 및 등록' 섹션을 건너뛸 수 있습니다.
  2. 프로젝트에 Maps JavaScript API를 사용 설정합니다.

지도 API 키 가져오기

웹 애플리케이션에서 Maps JavaScript API를 사용할 수 있는 API 키를 가져오는 방법을 알아보려면 Maps JavaScript API 참고 리소스의 API 키 가져오기를 참고하세요.

API 키로 승인된 요청만 실행되도록 하려면 API 키 제한 섹션의 안내도 따르는 것이 좋습니다.

자체 애플리케이션 구축

1단계: HTML 페이지 만들기

시작하려면 다음과 같이 기본 HTML 웹페이지를 정의합니다.

<!DOCTYPE html>
<html>
  <head>
    <style>
      /* Set the size of the div element that contains the map. */
      #map-container {
        height: 400px;
        width: 100%;
        background-color: #eee;
      }
    </style>
  </head>
  <body>
    <!-- The "Sign in with Google" button, initially hidden. -->
    <input
      id="g-sign-in"
      type="image"
      src="https://developers.google.com/identity/images/btn_google_signin_light_normal_web.png"
      onclick="onSignInButtonClick()"
      alt="Sign in with Google"
      hidden
    />

    <!-- Element where map will be added. -->
    <div id="map-container"></div>
    <script>
      // JavaScript code goes here.
    </script>
  </body>
</html>

이 기본 HTML은 다음과 같은 작업을 실행합니다.

  • CSS 스타일을 사용하여 초기화 중에 표시되는 지도의 크기와 배경 색상을 정의합니다.
  • 클릭 시 onSignInButtonClick() 함수를 호출하는 'Google 계정으로 로그인' 버튼을 정의합니다. 이 함수는 다음 섹션의 JavaScript에서 정의됩니다.
  • 초기화되면 지도가 포함될 빈 요소를 정의합니다.
  • 아래에 정의된 JavaScript 코드를 보관할 빈 <script> 블록을 추가합니다.

2단계: JavaScript에서 동작 정의

다음 단계에서는 JavaScript 코드를 <script> 태그 내에 직접 배치할 수 있습니다.

API 및 지도 설정 콜백 정의

사용자가 로그인한 후 작업을 실행하는 함수를 정의합니다. Earth Engine API는 사용자가 인증된 후에만 초기화하고 호출할 수 있습니다. 자세한 내용은 곧 제공됩니다.

이 예에서는 Earth Engine 및 지도 API를 초기화하고, 요청 시 지형 경사를 계산하는 타일 소스를 만들고, Maps JavaScript API에서 표시하는 오버레이로 타일 소스를 지도에 추가합니다.

// Initializes Maps JavaScript API and Earth Engine API, instructing the map
// to pull tiles from Earth Engine and to overlay them on the map.
function setUpMap() {
  // Hide the sign-in button.
  document.getElementById("g-sign-in").setAttribute("hidden", "true");

  // Initialize the Earth Engine API. Must be called once before using the API.
  ee.initialize(null, null, null, null, null, 'my-project');

  // Get a reference to the placeholder DOM element to contain the map.
  const mapContainerEl = document.getElementById("map-container");

  // Create an interactive map inside the placeholder DOM element.
  const embeddedMap = new google.maps.Map(mapContainerEl, {
    // Pan and zoom initial map viewport to Grand Canyon.
    center: {lng: -112.8598, lat: 36.2841},
    zoom: 9,
  });

  // Obtain reference to digital elevation model and apply algorithm to
  // calculate slope.
  const srtm = ee.Image("CGIAR/SRTM90_V4");
  const slope = ee.Terrain.slope(srtm);

  // Create a new tile source to fetch visible tiles on demand and display them
  // on the map.
  const mapId = slope.getMap({min: 0, max: 60});
  const tileSource = new ee.layers.EarthEngineTileSource(mapId);
  const overlay = new ee.layers.ImageOverlay(tileSource);
  embeddedMap.overlayMapTypes.push(overlay);
}

로그인 버튼 클릭 핸들러 정의

다음으로 로그인 버튼을 클릭할 때 로그인 팝업을 표시하는 함수를 추가합니다. 성공하면 setUp() 메서드가 호출됩니다.

// Handles clicks on the sign-in button.
function onSignInButtonClick() {
  // Display popup allowing the user to sign in with their Google account and to
  // grant appropriate permissions to the app.
  ee.data.authenticateViaPopup(setUpMap);
}

이 콜백은 onclick 속성을 통해 위의 HTML에 있는 버튼과 연결됩니다. 이 예에서는 페이지가 로드될 때 로그인 버튼이 처음에는 숨겨져 있습니다. 다음 섹션에서는 버튼을 표시하기 전에 사용자가 로그인했는지 확인합니다.

기본 진입점 정의

이제 페이지가 로드될 때 먼저 실행될 최상위 코드를 정의합니다. Earth Engine의 기본 제공 인증 도우미 함수 ee.data.authenticateViaPopup() 을 사용하여 사용자가 이미 로그인했는지 확인합니다. 사용자가 로그인한 경우 함수는 적절한 권한을 요청하고 성공하면 setUp()을 호출하여 Earth Engine 및 지도 API를 초기화합니다.

대신 사용자가 로그인하지 않은 경우 로그인 버튼이 표시됩니다. 그러면 사용자가 버튼을 클릭하여 onSignInButtonClick()을 트리거할 수 있으며, 이 함수는 팝업을 표시하고 setUp()을 호출하여 작업을 시작합니다.

// If the user is signed in, display a popup requesting permissions needed to
// run the app, otherwise show the sign-in button.
ee.data.authenticateViaOauth(
  // The OAuth Client ID defined above.
  CLIENT_ID,
  // Callback invoked immediately when user is already signed in.
  setUpMap,
  // Show authentication errors in a popup.
  alert,
  // Request permission to only read and compute Earth Engine data on behalf of
  // user.
  /* extraScopes = */ ['https://www.googleapis.com/auth/earthengine.readonly'],
  // Show sign-in button if reusing existing credentials fails.
  () => document.getElementById("g-sign-in").removeAttribute("hidden"),
  // Don't require ability to write and access Cloud Platform on behalf of the
  // user.
  /* opt_suppressDefaultScopes = */ true
);

체험해 보기

이 가이드에 제시된 전체 솔루션은 다음과 같습니다. 샘플 코드의 오른쪽 상단에는 세 개의 버튼이 있습니다. 가장 왼쪽에 있는 버튼을 클릭하여 JSFiddle에서 샘플을 엽니다.

YOUR_API_KEYYOUR_CLIENT_ID를 기본 요건에서 가져온 지도 API 키 및 OAuth 클라이언트 ID로 바꿉니다 (기본 요건 아래 코드에서 이러한 자리표시자를 클릭하면 자동으로 삽입됨). 또한 'my-project'를 Google Cloud 프로젝트 ID로 바꿉니다.

<!-- Load Maps JavaScript API. For production apps, append you own ?key=YOUR_API_KEY. -->

<script src="https://maps.googleapis.com/maps/api/js?key="></script>
<script src="https://ajax.googleapis.com/ajax/libs/earthengine/0.1.365/earthengine-api.min.js"></script>
<!-- The "Sign in with Google" button, initially hidden. -->
<input
  id="g-sign-in"
  type="image"
  src="https://developers.google.com/identity/images/btn_google_signin_light_normal_web.png"
  onclick="onSignInButtonClick()"
  alt="Sign in with Google"
  hidden
/>

<!-- Element where map will be added. -->
<div id="map-container"></div>
/* Set the size of the div element that contains the map. */
  #map-container {
    height: 400px;
    width: 100%;
    background-color: #eee;
  }
// The OAuth Client ID from the Google Developers Console.
// REMINDER: Be sure to add a valid ID here!
const CLIENT_ID = "";

// Initializes Maps JavaScript API and Earth Engine API, instructing the map
// to pull tiles from Earth Engine and to overlay them on the map.
function setUpMap() {
  // Hide the sign-in button.
  document.getElementById("g-sign-in").setAttribute("hidden", "true");

  // Initialize the Earth Engine API. Must be called once before using the API.
  ee.initialize(null, null, null, null, null, 'my-project');

  // Get a reference to the placeholder DOM element to contain the map.
  const mapContainerEl = document.getElementById("map-container");

  // Create an interactive map inside the placeholder DOM element.
  const embeddedMap = new google.maps.Map(mapContainerEl, {
    // Pan and zoom initial map viewport to Grand Canyon.
    center: {lng: -112.8598, lat: 36.2841},
    zoom: 9,
  });

  // Obtain reference to digital elevation model and apply algorithm to
  // calculate slope.
  const srtm = ee.Image("CGIAR/SRTM90_V4");
  const slope = ee.Terrain.slope(srtm);

  // Create a new tile source to fetch visible tiles on demand and display them
  // on the map.
  const mapId = slope.getMap({min: 0, max: 60});
  const tileSource = new ee.layers.EarthEngineTileSource(mapId);
  const overlay = new ee.layers.ImageOverlay(tileSource);
  embeddedMap.overlayMapTypes.push(overlay);
}

// Handles clicks on the sign-in button.
function onSignInButtonClick() {
  // Display popup allowing the user to sign in with their Google account and to
  // grant appropriate permissions to the app.
  ee.data.authenticateViaPopup(setUpMap);
}

// If the user is signed in, display a popup requesting permissions needed to
// run the app, otherwise show the sign-in button.
ee.data.authenticateViaOauth(
  // The OAuth Client ID defined above.
  CLIENT_ID,
  // Callback invoked immediately when user is already signed in.
  setUpMap,
  // Show authentication errors in a popup.
  alert,
  // Request permission to only read and compute Earth Engine data on behalf of
  // user.
  /* extraScopes = */ ['https://www.googleapis.com/auth/earthengine.readonly'],
  // Show sign-in button if reusing existing credentials fails.
  () => document.getElementById("g-sign-in").removeAttribute("hidden"),
  // Don't require ability to write and access Cloud Platform on behalf of the
  // user.
  /* opt_suppressDefaultScopes = */ true
);
<!DOCTYPE html>
<html>
  <head>
    <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/earthengine/0.1.365/earthengine-api.min.js"></script>
    <style>
      /* Set the size of the div element that contains the map. */
      #map-container {
        height: 400px;
        width: 100%;
        background-color: #eee;
      }
    </style>
  </head>
  <body>
    <!-- The "Sign in with Google" button, initially hidden. -->
    <input
      id="g-sign-in"
      type="image"
      src="https://developers.google.com/identity/images/btn_google_signin_light_normal_web.png"
      onclick="onSignInButtonClick()"
      alt="Sign in with Google"
      hidden
    />

    <!-- Element where map will be added. -->
    <div id="map-container"></div>
    <script>
      // The OAuth Client ID from the Google Developers Console.
      const CLIENT_ID = "YOUR_CLIENT_ID";
      
      // Initializes Maps JavaScript API and Earth Engine API, instructing the map
      // to pull tiles from Earth Engine and to overlay them on the map.
      function setUpMap() {
        // Hide the sign-in button.
        document.getElementById("g-sign-in").setAttribute("hidden", "true");
      
        // Initialize the Earth Engine API. Must be called once before using the API.
        ee.initialize(null, null, null, null, null, 'my-project');
      
        // Get a reference to the placeholder DOM element to contain the map.
        const mapContainerEl = document.getElementById("map-container");
      
        // Create an interactive map inside the placeholder DOM element.
        const embeddedMap = new google.maps.Map(mapContainerEl, {
          // Pan and zoom initial map viewport to Grand Canyon.
          center: {lng: -112.8598, lat: 36.2841},
          zoom: 9,
        });
      
        // Obtain reference to digital elevation model and apply algorithm to
        // calculate slope.
        const srtm = ee.Image("CGIAR/SRTM90_V4");
        const slope = ee.Terrain.slope(srtm);
      
        // Create a new tile source to fetch visible tiles on demand and display them
        // on the map.
        const mapId = slope.getMap({min: 0, max: 60});
        const tileSource = new ee.layers.EarthEngineTileSource(mapId);
        const overlay = new ee.layers.ImageOverlay(tileSource);
        embeddedMap.overlayMapTypes.push(overlay);
      }
      
      // Handles clicks on the sign-in button.
      function onSignInButtonClick() {
        // Display popup allowing the user to sign in with their Google account and to
        // grant appropriate permissions to the app.
        ee.data.authenticateViaPopup(setUpMap);
      }
      
      // If the user is signed in, display a popup requesting permissions needed to
      // run the app, otherwise show the sign-in button.
      ee.data.authenticateViaOauth(
        // The OAuth Client ID defined above.
        CLIENT_ID,
        // Callback invoked immediately when user is already signed in.
        setUpMap,
        // Show authentication errors in a popup.
        alert,
        // Request permission to only read and compute Earth Engine data on behalf of
        // user.
        /* extraScopes = */ ['https://www.googleapis.com/auth/earthengine.readonly'],
        // Show sign-in button if reusing existing credentials fails.
        () => document.getElementById("g-sign-in").removeAttribute("hidden"),
        // Don't require ability to write and access Cloud Platform on behalf of the
        // user.
        /* opt_suppressDefaultScopes = */ true
      );
    </script>
  </body>
</html>