Jetpack Composeでアプリ開発

Androidアプリを作ってみる。

"なろう"などのオフラインリーダーとして利用していた某Androidアプリの更新が止まってしまい、昨今の仕様変更で利用できなくなってしまったけれど、替えのいいアプリが見つからなかったので、せっかくだからと自分で作ってみている。

コードは

GitHub - paihu/narouviewer

に置いてある。

Androidアプリ開発をメインにしている知人に聞いたところ、今からAndroidStudioでアプリをつくるならJetpack Composeを利用したほうがいい。とのことで

Composableを活用して作成している。

ViewModelを使わず、 WebフロントエンドのReactなどの宣言的UIチックなコードになって、比較的なじみがある感じで助かっている面もあるが、設定の保存などに苦労したり、まだまだ難しさがある。

なじみがあるとはいえ、kotlinの型や関数に不慣れなため、補完やlintに助けてもらいながら書いている。

現状、最低限の実装はできて、普段使いを始めており、欲しい機能を順に実装している段階ではある。

Google Play storeに並べた方がインストールしやすくていいのだけれど、アイコンなどを考えるのがめんどくさくてあとまわしにしてしまっている。

今年中にはstoreに並べてインストールを楽にしたい。

GCPとAWSでmTLS with Terraform

GCPAWSともにロードバランサーでmTLSを利用してclient証明書検証ができるようになったので試してみた。

完成コードはGitHub - paihu/mtls-sample

どちらも普通に動くけれど、

GCPのほうは、検証しつつ、failしてもバックエンドに渡すことができる。

AWSのほうは、検証する場合は、failしたら通さない。検証しない場合は、証明書情報を丸ごとバックエンドに渡すので、自分で検証する。

というオプションが用意されている。

このあたり、微妙に思想の違いがあって面白い。

また、証明書の検証は、GCPのほうが厳密。証明書の用途などがおかしかったりすると、うまく検証できなかったりするので、ちゃんと証明書を作る必要があった。

どちらもうまく動きはしたし、ばっくえんどサービスに証明書のシリアルなど、必要な情報を渡せたので、本運用につなげることができそうだった。

フロントエンドのテスト環境を作った

概要

フロントエンド(SPA)のQA環境を AWS CloudFront + CloudFront Function + S3 で作成した話。

なぜフロントエンドのQA環境用にあらたな仕組みをつくったのか

フレームワークの移行作業により、多数のフロントエンド改修が走っていたが、バックエンドも含めたQA環境の数がすくなく、QAスケジュールに難が出てきたため。

また、今後もフロントエンドのみの改修案件が定常的に発生しそうだったため。

上記のような背景から、バックエンドを共有したフロントエンドのみのQA環境を多数用意できる必要が出てきたため。

前提

もともとフロントエンドとバックエンドが同一ドメインでホストされている環境。

フロントエンドはSPAであり、初期画面のHTMLだけバックエンドが生成している。

やったこと

AWS CloudFront とS3により、 任意のサブドメインでSPAだけホスティングできるようにした。

具体的な内容

フロントエンド側にて、バックエンドのアクセス先を指定できるようにした。

フレームワークの移行中だったので、内部で新旧フレームワークがそれぞれ別のhttp Clientを利用しており、どのhttpClientに対してもバックエンドのアクセス先をうまく指定する必要があった。

具体的には axios, kyなどが使われていたので、

axios.defaults.baseURL の設定をしたり、httpClientの get , post, delete などの methodにて、 new URL(originalUrl, バックエンドドメイン) を設定したり、

クロスオリジンになるので withCredentials: truecredentials: "include" を設定したり。

CORS対応

もともと同一ドメインでホストされているのでCORSの設定は得にしていなかったが、 フロントエンドを任意サブドメインでホストさせる都合でオリジンが異なる状況となったので CORSの設定を追加した。

具体的には前段にあるnginxに設定を追加している。

このような感じのもの

set $cors "";
if ( $host ~ "\.front-staging\.example\.com$"){
  set $cors "true";
}
if ($cors = "true"){
 set_header Access-Control-Allow-Origin  $origin;
 set_header Access-Control-Allow-Method "GET, POST, PUT, DELETE, OPTIONS";
 set_header Access-Control-Allow-Headers "Content-Type, X-xxx-xxx .... Authorization";
 set_header Access-Control-Allow-Credentials "true";
}

CloudFrontとS3の用意

インフラはInfrastructure as Codeで用意している(AWS CDK (cloudformation)利用)

基本的には普通に作る。

通常と違うのは下記2点

  • CloudFrontで *.front-staging.example.comのように任意サブドメインのリクエストを受け入れるように設定
  • CloudFront Functionにて、 オリジンリクエストを //path/to/file に書き換えるよう設定

このような雰囲気のシンプルなCloudFront Functionを利用した

function handler(event) {
  var pathPrefix = event.request.headers.host.split(".")[0];
  event.request.uri = pathPrefix + event.request.uri;
  return request;
}

CloudFrontFunctionは ES5.1らしく、letやconstすら使えない世界。

S3には、1か月ファイルが消えるLifeCycle Policyが設定されている。*1

CI 環境の整備

PullRequestに対して、 SPAをビルドし、ビルドした成果物を s3の /PR-ID/path/to/file に置き、 https://PR-ID.front-staging.example.com を通知する。というCI Jobを作成した。

まとめ

上記では全く触れていないが、当初は GitLab の GitLab Pagesにある、 Job Artifactsを ブラウザで見られる機能を利用しようとしてスタートした。

断念した理由として、 GitLab PagesのJob Artifactsのブラウジングでは / で終わるURLに対して、 /index.html を呼んでくれない。 そもそも Pathにprefixがつくため、rootでホストされることが前提に作られているSPAと相性がわるい。

という話があり、途中で CloudFrontを利用する方向に舵を切りなおしている。

結果的に、それなりに使えるものが出来上がったので良かった。

そもそも最初からVercelのようなサービスを使えばいいのはそうなのだが、

現状Vercelの利用実績がないため、導入には社内でのセキュリティチェックや決済を通す必要があり、ハードルが高かった。

AWSであればプロダクション利用しており、CloudFrontとS3の値段程度は誤差なので、改めて決済する必要もなく、スムーズに利用できた。という背景がある。

*1:実際にはもっと短くてもよいが、ファイルサイズ的に保管にかかる金額は考えなくていい程度であるため、長すぎない程度の適当長さを設定している。