AWS CDK と AWS CloudFormation で Amazon Location Service のリソースを構築する

2024-04-02
コミュニティ通信

Author : 桐本 靖規 (AWS DevTools Hero)

こんにちは、AWS DevTools Hero の桐本です。

本日は、AWS Cloud Development Kit (AWS CDK)AWS CloudFormation を用いて、AWSの環境下で位置情報アプリケーションを構築可能な、Amazon Location Service の構築方法を紹介します。そして、最近話題の CDK MigrateAWS CloudFormation IaCジェネレーター の例も紹介します。

AWS CDK と AWS CloudFormation を利用することで、インフラストラクチャをコードとして管理し、これにより開発プロセスを自動化し効率化することが可能です。AWS CDK はプログラミング言語を用いて、開発者に親しみやすく、コンポーネントの再利用を容易にします。AWS CloudFormation は、安定したリソース管理を実現し、JSON や YAML でテンプレートを作成できます。これらのツールを利用することで、コード化され再現可能なインフラストラクチャを構築するというメリットが得られます。

Amazon Location Service については、昨年リリースされた Amazon Location SDKAPI キー機能 を利用し、マップ・ジオコーディング・ルーティングの3機能を構築します。また、今年発表された「API キーとリソース管理の CloudFormation サポートを開始」についても、AWS CDK と AWS CloudFormation での実装を検証しました。

下記の流れで例を紹介します。リソースの構築には、AWS CDK か AWS CloudFormation のどちらかを選んでください。

ご注意

本記事で紹介する AWS サービスを起動する際には、料金がかかります。builders.flash メールメンバー特典の、クラウドレシピ向けクレジットコードプレゼントの入手をお勧めします。

*ハンズオン記事およびソースコードにおける免責事項 »

このクラウドレシピ (ハンズオン記事) を無料でお試しいただけます »

毎月提供されるクラウドレシピのアップデート情報とともに、クレジットコードを受け取ることができます。 


1. 事前準備

AWS CDK の環境をインストールします。今回、AWS CloudFormation を利用する方はインストール不要です。

執筆時の検証バージョン

  • node v20.0.0
  • npm v9.6.4

パッケージをインストールします。

npm install -g aws-cdk

バージョンを確認します。

cdk --version
2.127.0 (build 6c90efc)

2. Amazon Location Service のリソース構築 : AWS CloudFormation

はじめに、AWS CloudFormation で Amazon Location Service のリソースを構築します。

GitHub で作成した環境を公開しています。ご自身の環境に fork またはダウンロードしご利用ください。
aws-cloudformation-templates-showcase - location-service

create.yml

AWSTemplateFormatVersion: 2010-09-09
Description: Amazon Location Service Creation
Parameters:
  MapName:
    Description: Map Name
    Type: String
  PlaceIndexName:
    Description: PlaceIndex Name
    Type: String
  RouteCalculatorName:
    Description: RouteCalculator Name
    Type: String
  APIKeyName:
    Description: APIKey Name
    Type: String
Resources:
  LocationServiceMap:
    Type: AWS::Location::Map
    Properties:
      Configuration:
        Style: VectorHereExplore
      Description: Amazon Location Service Map
      MapName: !Sub ${MapName}
      PricingPlan: RequestBasedUsage
  LocationServicePlaceIndex:
    Type: AWS::Location::PlaceIndex
    Properties:
      DataSource: Here
      DataSourceConfiguration:
        IntendedUse: SingleUse
      Description: Amazon Location Service PlaceIndex
      IndexName: !Sub ${PlaceIndexName}
      PricingPlan: RequestBasedUsage
  LocationServiceRouteCalculator:
    Type: AWS::Location::RouteCalculator
    Properties:
      DataSource: Here
      Description: Amazon Location Service eRouteCalculator
      CalculatorName: !Sub ${RouteCalculatorName}
      PricingPlan: RequestBasedUsage
  LocationServiceAPIKey:
    Type: AWS::Location::APIKey
    Properties:
      Description: Amazon Location Service APIKey
      KeyName: !Sub ${APIKeyName}
      NoExpiry: true
      Restrictions:
        AllowActions: [geo:GetMap*, geo:SearchPlaceIndexForPosition, geo:CalculateRoute]
        AllowResources:
          - !Sub arn:aws:geo:${AWS::Region}:${AWS::AccountId}:map/${MapName}
          - !Sub arn:aws:geo:${AWS::Region}:${AWS::AccountId}:place-index/${PlaceIndexName}
          - !Sub arn:aws:geo:${AWS::Region}:${AWS::AccountId}:route-calculator/${RouteCalculatorName}
Outputs:
  RegionName:
    Description: Region Name
    Value: !Sub ${AWS::Region}
  MapName:
    Description: Map Name
    Value: !Ref LocationServiceMap
  PlaceIndexName:
    Description: PlaceIndex Name
    Value: !Ref LocationServicePlaceIndex
  RouteCalculatorName:
    Description: RouteCalculator Name
    Value: !Ref LocationServiceRouteCalculator

AWS CloudFormationでデプロイ

作成したテンプレートを使って AWS CloudFormationでAmazon Location Service のリソースをデプロイします。

AWSマネジメントコンソール → AWS CloudFormation → 「スタックの作成」をクリックします。

クリックすると拡大します

新しいリソースを使用」をクリックします。

クリックすると拡大します

前提条件は「テンプレートの準備完了」を選択します。テンプレートの指定は「テンプレートファイルのアップロード」を選択しファイルをアップロード → 「次へ」をクリックします。CloudFormation テンプレートは「create.yml」を利用します。

クリックすると拡大します

任意のスタック名・APIキー名・マップ名・ジオコーディング名・ルーティング名を設定 → 「次へ」をクリックします。

クリックすると拡大します

スタックオプションは今回デフォルトで設定 → 「次へ」をクリックします。

クリックすると拡大します

設定を確認 → 「送信」をクリックします。

クリックすると拡大します

しばらくすると、スタックが作成されたのを確認できます。

クリックすると拡大します


3. Amazon Location Service のリソース構築 : AWS CDK

次に、AWS CDK で Amazon Location Service のリソースを構築します。

AWS CDKをはじめて利⽤するかたは、ワークショップ もぜひご確認ください。

GitHubで 作成した環境を公開しています。ご自身の環境に fork またはダウンロードしご利用ください。
aws-cdk-templates-showcase - location-service

ファイル構成

.
├── README.md
├── bin
│   └── location-service.ts
├── cdk.json
├── jest.config.js
├── lib
│   └── location-service-stack.ts
├── package-lock.json
├── package.json
├── test
└── tsconfig.json

package.json

{
  "name": "location-service",
  "version": "0.1.0",
  "bin": {
    "location-service": "bin/location-service.js"
  },
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "test": "jest",
    "cdk": "cdk"
  },
  "keywords": [],
  "author": "Yasunori Kirimoto",
  "license": "ISC",
  "devDependencies": {
    "@types/jest": "^29.5.12",
    "@types/node": "20.11.16",
    "jest": "^29.7.0",
    "ts-jest": "^29.1.2",
    "aws-cdk": "2.127.0",
    "ts-node": "^10.9.2",
    "typescript": "~5.3.3"
  },
  "dependencies": {
    "aws-cdk-lib": "2.127.0",
    "constructs": "^10.0.0",
    "source-map-support": "^0.5.21"
  }
}

/lib/location-service-stack.ts

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as location from 'aws-cdk-lib/aws-location';

export interface LocationServiceStackProps extends cdk.StackProps {
  readonly mapName: string;
  readonly placeIndexName: string;
  readonly routeCalculatorName: string;
  readonly apiKeyName: string;
}

/**
 * Amazon Location Service Creation
 */
export class LocationServiceStack extends cdk.Stack {
  public constructor(scope: Construct, id: string, props: LocationServiceStackProps) {
    super(scope, id, props);
    // Amazon Location Service APIKey
    const locationServiceApiKey = new location.CfnAPIKey(this, 'LocationServiceAPIKey', {
      description: 'Amazon Location Service APIKey',
      keyName: `${props.apiKeyName!}`,
      noExpiry: true,
      restrictions: {
        allowActions: [
          'geo:GetMap*',
          'geo:SearchPlaceIndexForPosition',
          'geo:CalculateRoute',
        ],
        allowResources: [
          `arn:aws:geo:${this.region}:${this.account}:map/${props.mapName}`,
          `arn:aws:geo:${this.region}:${this.account}:place-index/${props.placeIndexName}`,
          `arn:aws:geo:${this.region}:${this.account}:route-calculator/${props.routeCalculatorName}`,
        ],
      },
    });
    // Amazon Location Service Map
    const locationServiceMap = new location.CfnMap(this, 'LocationServiceMap', {
      configuration: {
        style: 'VectorHereExplore',
      },
      description: 'Amazon Location Service Map',
      mapName: props.mapName,
      pricingPlan: 'RequestBasedUsage',
    });
    // Amazon Location Service Place Index
    const locationServicePlaceIndex = new location.CfnPlaceIndex(this, 'LocationServicePlaceIndex', {
      dataSource: 'Here',
      dataSourceConfiguration: {
        intendedUse: 'SingleUse',
      },
      description: 'Amazon Location Service PlaceIndex',
      indexName: props.placeIndexName,
      pricingPlan: 'RequestBasedUsage',
    });
    // Amazon Location Service Route Calculator
    const locationServiceRouteCalculator = new location.CfnRouteCalculator(this, 'LocationServiceRouteCalculator', {
      dataSource: 'Here',
      description: 'Amazon Location Service eRouteCalculator',
      calculatorName: props.routeCalculatorName,
      pricingPlan: 'RequestBasedUsage',
    });
    // Outputs
    new cdk.CfnOutput(this, 'CfnOutputRegionName', {
      description: 'Region Name',
      value: this.region,
    });
    new cdk.CfnOutput(this, 'CfnOutputMapName', {
      description: 'Map Name',
      value: locationServiceMap.ref,
    });
    new cdk.CfnOutput(this, 'CfnOutputPlaceIndexName', {
      description: 'PlaceIndex Name',
      value: locationServicePlaceIndex.ref,
    });
    new cdk.CfnOutput(this, 'CfnOutputRouteCalculatorName', {
      description: 'RouteCalculator Name',
      value: locationServiceRouteCalculator.ref,
    });
  }
}

/bin/location-service.ts

#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { LocationServiceStack } from '../lib/location-service-stack';

const app = new cdk.App();
new LocationServiceStack(app, 'location-service', {
  env: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.CDK_DEFAULT_REGION,
  },
  apiKeyName: 'LocationServiceApiKey',
  mapName: 'LocationServiceMap',
  placeIndexName: 'LocationServicePlace',
  routeCalculatorName: 'LocationServiceRoute',
});

AWS CDK でデプロイ

作成したプロジェクトを使って AWS CDK で Amazon Location Service のリソースをデプロイします。

ディレクトリを移動します。

cd aws-cdk-templates-showcase/location-service

パッケージをインストールします。

npm install

デプロイ前に初回のみ下記コマンドを実行します。リージョンを変更した時にも実行します。

cdk bootstrap

クリックすると拡大します

プロジェクトをデプロイします。

cdk deploy

クリックすると拡大します


4. Amazon Location Service のリソース確認

AWS CDK または AWS CloudFormation のデプロイが反映されているかを確認します。

AWS マネジメントコンソール → Amazon Location Service → 各リソースを確認します。

クリックすると拡大します

マップ・ジオコーディング・ルーティングの設定が反映されています。次のアプリケーション構築で利用するため、マップ名・ジオコーディング名・ルーティング名をコピーします。

クリックすると拡大します

API キーの設定が反映されています。次のアプリケーション構築で利用するため、リージョン名・API キー値をコピーします。外部公開時は、API キーのリファラー設定も必要となります。

クリックすると拡大します

ここまでで、AWS CDK または AWS CloudFormation で Amazon Location Service の環境構築が完了しました。次に、Amazon Location Service のアプリケーションを構築します。


5. Amazon Location Service のアプリケーション構築

スターターのインストール

既存のスターターを利用し、Amazon Location Service のフロントエンド環境を構築します。このスターターは、マップライブラリをシンプルに利用できる構成になっています。ご自身の環境に fork またはダウンロードしインストールをしてください。

MapLibre GL JS & Amazon Location Service スターター

https://github.com/mug-jp/maplibregljs-amazon-location-service-starter

執筆時の検証バージョン

  • node v20.0.0
  • npm v9.6.4
ファイル構成
.
├── LICENSE
├── README.md
├── dist
│   ├── assets
│   └── index.html
├── docs
├── img
├── index.html
├── package-lock.json
├── package.json
├── src
│   ├── main.ts
│   ├── style.css
│   └── vite-env.d.ts
├── tsconfig.json
└── vite.config.ts

.env

デプロイした環境のリージョン・API キー・マップ名を env ファイルに設定します。

VITE_REGION = xxxxx
VITE_MAP_API_KEY = v1.public.xxxxx
VITE_MAP_NAME = xxxxx

ディレクトリを移動します。

cd maplibregljs-amazon-location-service-starter

パッケージをインストールします。

npm install

ローカルサーバーで確認します。

npm run dev

マップが表示されます。

Amazon Location SDK のインストール

次に、Amazon Location SDK の必要なライブラリをインストールします。インストールすることで、API の認証や MapLibre GL JS との組み合わせが手軽になります。

client-location

AWS SDK をインストールします。"client-location" は Amazon Location Service を操作できる SDK です。

npm install @aws-sdk/client-location

amazon-location-utilities-auth-helper

"amazon-location-utilities-auth-helper" をインストールします。Amazon Location Service の API キーと Amazon Cognito の認証が手軽になるライブラリです。

npm install @aws/amazon-location-utilities-auth-helper

amazon-location-utilities-datatypes

"amazon-location-utilities-datatypes" をインストールします。Amazon Location Service のレスポンスを GeoJSON 形式に変換してくれるライブラリです。

npm install @aws/amazon-location-utilities-datatypes

"amazon-location-utilities-datatypes" について、MapLibre GL JS と組み合わせると一部利用しにくかったため、先日オプション機能を追加するコントリビュートをしました。

AWS Geospatial

アプリケーションの構築

最後に、実際に Amazon Location Service のマップ・ジオコーディング・ルーティング機能を API キーを用いて構築する方法を紹介します。

package.json

{
  "name": "maplibregljs-amazon-location-service-starter",
  "version": "4.0.0",
  "description": "",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "keywords": [],
  "author": "MapLibre User Group Japan",
  "license": "ISC",
  "devDependencies": {
    "typescript": "^5.3.3",
    "vite": "^5.1.1"
  },
  "dependencies": {
    "@aws-sdk/client-location": "^3.511.0",
    "@aws/amazon-location-utilities-auth-helper": "^1.0.3",
    "@aws/amazon-location-utilities-datatypes": "^1.0.5",
    "maplibre-gl": "^4.0.0"
  }
}

.env

デプロイした環境のリージョン・API キー・マップ名・ジオコーディング名・ルーティング名を env ファイルに設定します。

VITE_REGION = xxxxx
VITE_API_KEY = v1.public.xxxxx
VITE_MAP_NAME = xxxxx
VITE_PLACE_NAME = xxxxx
VITE_ROUTE_NAME = xxxxx

main.ts

import './style.css'
import 'maplibre-gl/dist/maplibre-gl.css';
import maplibregl from 'maplibre-gl';
// Amazon Location SDKを設定
import { LocationClient, SearchPlaceIndexForPositionCommand, CalculateRouteCommand } from "@aws-sdk/client-location";
import { placeToFeatureCollection, routeToFeatureCollection } from '@aws/amazon-location-utilities-datatypes';
import { withAPIKey } from '@aws/amazon-location-utilities-auth-helper';

const region = import.meta.env.VITE_REGION;
const apiKey = import.meta.env.VITE_API_KEY;
const mapName = import.meta.env.VITE_MAP_NAME;
const placeName = import.meta.env.VITE_PLACE_NAME;
const routeName = import.meta.env.VITE_ROUTE_NAME;

async function initialize() {
    // APIキーの認証設定
    const authHelper = await withAPIKey(apiKey);
    const client = new LocationClient({
        region: region,
        ...authHelper.getLocationClientConfig()
    });

    // 指定位置からリバースジオコーディング
    const inputPlace = {
        IndexName: placeName,
        Position: [139.767, 35.681],
    };
    const commandPlace = new SearchPlaceIndexForPositionCommand(inputPlace);
    const responsePlace = await client.send(commandPlace);
    // ジオコーディングのレスポンスをGeoJSONに変換
    const featureCollectionPlace = placeToFeatureCollection(responsePlace, {
        flattenProperties: true
    });

    // 指定位置でルート検索
    const inputRoute = {
        CalculatorName: routeName,
        DeparturePosition: [139.7558, 35.6767],
        DestinationPosition: [139.8160, 35.6830],
        IncludeLegGeometry: true,
    };
    const commandRoute = new CalculateRouteCommand(inputRoute);
    const responseRoute = await client.send(commandRoute);
    // ルーティングのレスポンスをGeoJSONに変換
    const featureCollectionRoute = routeToFeatureCollection(responseRoute, {
        flattenProperties: true
    });

    // マップを設定
    const map = new maplibregl.Map({
        container: 'map',
        style: `https://maps.geo.${region}.amazonaws.com/maps/v0/maps/${mapName}/style-descriptor?key=${apiKey}`,
        center: [139.767, 35.681],
        zoom: 11,
    });
    map.addControl(
        new maplibregl.NavigationControl({
            visualizePitch: true,
        })
    );

    map.on('load', function () {
        // ジオコーディング結果のスタイル設定
        map.addSource("search-result", {
            type: "geojson",
            data: featureCollectionPlace
        });
        map.addLayer({
            'id': "search-result",
            'type': 'circle',
            'source': 'search-result',
            'layout': {},
            'paint': {
                'circle-color': '#007cbf',
                'circle-radius': 10
            }
        });
        // ジオコーディング結果の情報表示
        map.on('click', 'search-result', (e) => {
            const coordinates = e.lngLat;
            const description = e.features![0].properties['Place.Label'];
            new maplibregl.Popup()
                .setLngLat(coordinates)
                .setHTML(description)
                .addTo(map);
        });
        map.on('mouseenter', 'search-result', () => {
            map.getCanvas().style.cursor = 'pointer';
        });
        map.on('mouseleave', 'search-result', () => {
            map.getCanvas().style.cursor = '';
        });
        // ルーティング結果のスタイル設定
        map.addSource("route-result", {
            type: "geojson",
            data: featureCollectionRoute
        });
        map.addLayer({
            'id': "route-result",
            'type': 'line',
            'source': 'route-result',
            'layout': {
                'line-join': 'round',
                'line-cap': 'round'
            },
            'paint': {
                'line-color': '#FF0000',
                'line-width': 10,
                'line-opacity': 0.5
            }
        });
        // ルーティング結果の情報表示
        map.on('click', 'route-result', (e) => {
            const coordinates = e.lngLat;
            const description = `${e.features?.[0]?.properties['Distance'] ?? ''}km`;
            new maplibregl.Popup()
                .setLngLat(coordinates)
                .setHTML(description)
                .addTo(map);
        });
        map.on('mouseenter', 'route-result', () => {
            map.getCanvas().style.cursor = 'pointer';
        });
        map.on('mouseleave', 'route-result', () => {
            map.getCanvas().style.cursor = '';
        });
    });
}
initialize();

ローカルサーバーで確認します。

npm run dev

Amazon Location Service のマップ・ジオコーディング・ルーティング機能が表示されます

ここまでで、Amazon Location Service のアプリケーション構築が完了しました。次に、CDK Migrate と IaC ジェネレーターについて紹介します。


6. CDK Migrate の紹介

CDK Migrate を利用することで、AWS CloudFormation のテンプレートを AWS CDK のプロジェクトに自動で変換できます。今回のプロジェクトも CDK Migrate を利用して作成し、ほとんどのコードをそのまま利用できました。ただ、このプロジェクトはシンプルな構成のため、複雑な構成になると課題はでるかもしれません。

cdk migrate コマンドで AWS CloudFormation のテンプレートを AWS CDK のプロジェクトに変換します。

cdk migrate --stack-name location-service --from-path ./create.yml --language typescript

画像をクリックすると拡大します


7. AWS CloudFormation IaCジェネレーターの紹介

AWS CloudFormation IaCジェネレーター を利用することで、AWS CloudFormation テンプレートを作成し既存のリソースをインポートできます。これは、AWS マネジメントコンソールでリソースを作成してテンプレート化する際に便利になります。今回作成した CloudFormation テンプレートは、一部参考になる点がありましたが、基本的には新たに作成する必要がありました。

AWS マネジメントコンソール → AWS CloudFormation → 「IaC ジェネレーター」をクリック → 「新しいスキャンを開始」をクリック → スキャン完了後「テンプレートを作成」をクリックします。

クリックすると拡大します

新しいテンプレートから開始」を選択 → テンプレート名を設定 → 「次へ」をクリックします。

クリックすると拡大します

スキャンされた中からテンプレート化したいリソースを選択します。今回は Amazon Location Service 関係のリソースを選択 → 「次へ」をクリックします。

クリックすると拡大します

次へ」をクリックします。

クリックすると拡大します

設定を確認 → 「テンプレートを作成」をクリック。

クリックすると拡大します

指定したリソースのテンプレートが作成されます。

Metadata:
  TemplateId: "arn:aws:cloudformation:ap-northeast-1:xxxxx:generatedTemplate/c686423c-b0d2-4d87-bfe3-ea"
Resources:
  LocationRouteCalculator00SampleRouting00Myobr:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::Location::RouteCalculator"
    DeletionPolicy: "Retain"
    Properties:
      CalculatorName: "SampleRouting"
      PricingPlan: "RequestBasedUsage"
      Description: ""
      Tags: []
      DataSource: "Here"
  LocationMap00SampleMap00QfNM7:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::Location::Map"
    DeletionPolicy: "Retain"
    Properties:
      PricingPlan: "RequestBasedUsage"
      MapName: "SampleMap"
      Configuration:
        Style: "VectorHereExplore"
        CustomLayers: []
      Tags: []
  LocationPlaceIndex00SampleGeocoding002C7JQ:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::Location::PlaceIndex"
    DeletionPolicy: "Retain"
    Properties:
      IndexName: "SampleGeocoding"
      PricingPlan: "RequestBasedUsage"
      Description: ""
      DataSourceConfiguration:
        IntendedUse: "SingleUse"
      Tags: []
      DataSource: "Here"

クリックすると拡大します


8. 各リソースの削除

最後に、各リソースの削除方法を紹介します。

AWS CloudFormation でリソース削除

AWS マネジメントコンソール → AWS CloudFormation → location-service を選択 →「削除」をクリックします。

クリックすると拡大します

削除」をクリックします。

クリックすると拡大します

AWS CDK でリソース削除

cdk destroy コマンドでリソースを削除します。

cdk destroy

クリックすると拡大します


まとめ

Amazon Location Service の API キーとリソース管理の CloudFormation サポートが開始されたことで、環境構築の自動化やテンプレート化の選択肢が広がりました。今後のアップデートも楽しみです !

また、AWS CDK では Amazon Location Service の L2 コンストラクトは、2024 年 3 月現在 アルファ版 で Place Index のみが提供されています。そのため、基本的には L1 コンストラクトでの定義が必要になります。

今回の例が、AWS で位置情報アプリケーションを構築しようと考えている方々の参考になれば幸いです !

非公式ではありますが、Amazon Location Service のアップデート情報を毎月配信しています。

Monthly Amazon Location Service Updates (JPN)
Monthly Amazon Location Service Updates (ENG)


builders.flash メールメンバーへ登録することで
AWS のベストプラクティスを毎月無料でお試しいただけます

筆者プロフィール

桐本 靖規
Co-Founder and COO of MIERUNE
AWS DevTools Hero | Amplify Japan User Group | MapLibre User Group Japan |
MapLibre Voting Member | OSGeo Charter Member | Owner of dayjournal

2004 年から位置情報分野に携わり、2016 年に MIERUNE を共同創業。独自のカルチャーを持つプロフェッショナルなチーム作りや、プロダクト成功のための組織マネジメントに注力し日々模索中。個人活動では、オープンソースへの貢献や、コミュニティの運営メンバーとしてカンファレンスやワークショップを開催。専門は GIS (Geographic Information System) と FOSS4G (Free and OpenSource Software for Geospatial)。AWS と位置情報技術の組み合わせを日々模索中。

好きな AWS サービス: Amazon Location Service / AWS Amplify

Twitter: @dayjournal_nori
GitHub: @dayjournal
LinkedIn: @YasunoriKirimoto

AWS を無料でお試しいただけます

AWS 無料利用枠の詳細はこちら ≫
5 ステップでアカウント作成できます
無料サインアップ ≫
ご不明な点がおありですか?
日本担当チームへ相談する