UdemyのコースでAWSを使っていくメモ
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
今回やっていくのはコレ。
フロントエンドからAPIサーバを経由してDBにデータを格納する方法やデータを取得する方法はわかったが、ストレージにデータを保存する方法や、取得する方法はいまいちなのでs3に写真を格納できる本コースを選択。
ついでにReact * TypeScriptも学んでいく。
※授業の内容の中で自分で調べた内容や雑感を書いていくイメージ。
備忘録的な。
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
昨日の段階で、
- アカウント作成
- IAMユーザの作成
- 予算/アラートの作成
- aws cli のインストール/ configの設定
が終わっている。
aws cliは下記からダウンロード
$ aws configure
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: ap-northeast-1
Default output format [None]: json
※登録したアクセスキーなどは上記とは違います。
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
余談
アカウント作成は本登録までやっていなくて、3/5くらいまでで昨年6月から放置していたが、昨日スタートして無償枠の範囲内だった。
Billingまでは見られたから無償枠はとっくに過ぎたと思っていたのでびっくりした。
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
AWS CDKを理解する。
設定済みのアプリケーションコンポーネントを使用
パッケージマネージャやアーティファクトリポジトリから構成済みのコンポーネントをダウンロードする。
↓
アプリケーションのモデル化
アプリケーションのロジックやインフラをプログラミング言語でモデル化します。
↓
AWS CloudFormationを使用してアプリケーションをモデル化する
AWS CloudFormationを使用して、アプリケーションコードとサポートするインフラストラクチャをプロビジョニングします。
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
AWS CloudFormationを使うと、AWS(200くらいあるらしい)にたくさんあるサービスを組み合わせて一気に作成することができるらしい。
解説によると、CloudFormationの設定は膨大で、AWS CDKは膨大なその設定を出力することができる機能を持っているらしい。
参考
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
AWS CloudFormationを試す。
AWS CloudFormationを作成していく。
- CloudFormationサービスを検索
- JSONでS3を設定(本来はS3を設定してからいくのか?
- タスク名を設定
- スタックオプション/詳細オプション未設定
- レビュー未設定
上記の手順で実施すると、作成される。
testStack
2021-07-27 11:48:00 UTC+0900
CREATE_IN_PROGRESS
↓リロード後 Ctrl + R
testStack
2021-07-27 11:48:00 UTC+0900
CREATE_COMPLETE
イベント (5)
2021-07-27 11:48:28 UTC+0900 testStack CREATE_COMPLETE -
2021-07-27 11:48:26 UTC+0900 HelloBucket CREATE_COMPLETE -
2021-07-27 11:48:06 UTC+0900 HelloBucket CREATE_IN_PROGRESS Resource creation Initiated
2021-07-27 11:48:04 UTC+0900 HelloBucket CREATE_IN_PROGRESS -
2021-07-27 11:48:00 UTC+0900 testStack CREATE_IN_PROGRESS User Initiated
リソースタブから作成したS3の設定にリンクがある。
アクセス権限をPublicReadで設定したため、オブジェクトタブからファイルの保存ができることを確認した。
S3の権限設定が未着手なのでしょうがないけど、S3が全公開設定なのにファイルを参照しようとするとアクセスできない。
と思っていたら、オブジェクトURLにアクセスできないだけで、公開してあるファイルにはアクセスできた。
公開されているURLを見るとSecurityTokenがあるので、これの設定によるものっぽい。
オブジェクトアクションから公開設定にしたらオブジェクトURLからアクセスできた。
アクセス権限のパブリック・アクセスの意味が自分の認識と差異がありそう。
ここまでの作業でスタック情報を削除する。
削除した場合、S3がどうなるのか気になる。
-> リソースにDeletionPolicy属性がない場合、AWSCloudFormationはデフォルトでリソースを削除します。
スタックを削除しようとしたら、ステータス DELETE_FAILED
となった。
理由はバケットが空でないかららしい。
なのでバケットに追加したファイルを削除して再度実行する。
チェックせずに削除を押下すると今度はDELETE_COMPLETEとなる。
Stacksの数が1から0になった。
Stackで作成したバケットはおそらく消えたが、別のStackで使用した情報が格納されたバケットが自動作成されていた。一応消しておく。
感想①
下記のようにステップがあるのは親切だと思った。
ステップ 1 テンプレートの指定
ステップ 2 スタックの詳細を指定
ステップ 3 スタックオプションの設定
ステップ 4 レビュー
感想②
イベントタブを見ると、stack情報とbucket情報の2種類あったおそらく作成するサービスが増えると、その度に増えるのだと思う。
感想③
AWS内でのs3の立ち位置はマジでストレージ、オブジェクト置き場なんだなぁという感想。
Billingの設定の際にもレポートをs3に置く。みたいな設定があったので、オブジェクトは全部ここに配置できるのかな、と思いました。
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
IAM の見直し
ここまでの作業でIAMの設定に不安があったので、調べる。
下記記事の通りに作業する。
IAMユーザの見直し
このコースではaws cliを使った関係から、アクセスキーの発行にIAMでユーザを作成した。
しかし、コンソールでの作業ではIAMを特に作成しなかったため、先の作業はrootユーザで行った。
それに違和感があり、調査した。
rootユーザは基本使わない。
当面、どんな作業があるかわからないため、コンソール用のIAMをAdmin権限で使用する。
本登録になっていない状態ではMFAは作成できなかったため、改めて調べて実施した。
パスワードはもともと12桁だったけど、24桁にした。
あまり使わないなら構わないでしょう。
IAMはとりあえず2つ
aws cliなどのアクセスキー発行のIAMと、コンソール操作用のIAM
グループとロールについてはまだどの程度の権限で作成したら良いかよくわかっていないため、
今後サービスを複数使う際に追々設定していく。
MFAの設定
仮想MFAの1と2については初めての作業だったのでわからなかった。
1回目と2回目なんだね。
cloudtrailは有効化(クイックで作成)
ログの設定
GuardDutyも有効化
侵入者検知かな?
上記2つは有料だけど、どんな攻撃がくるのか知っておくためにも有効化しておくのが良いと思う。
というか、無料の期間中になるべく試して、必要な情報だけを保存するように努力したい。
と、とりあえず、これでいく。
その他読んだ記事
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
AWS CDKの使う
install
❯ npm i -g aws-cdk
added 181 packages, and audited 182 packages in 17s
found 0 vulnerabilities
❯ cdk --version
1.115.0 (build f0ca40f)
folder
❯ mkdir first-aws-cdk
❯ cd first-aws-cdk
❯ aws s3 ls
2021-07-27 13:22:22 aws-cloudtrail-logs-494841387284-a9d7dd47
cdk init app --language typescript
cdk command: cdk init app --language typescript
これを作るとcdkによる開発環境のセットアップが可能になる。
テスト環境や初期設定なども入っていて、わかりやすい。
❯ aws s3 ls
2021-07-27 13:22:22 aws-cloudtrail-logs-494841387284-a9d7dd47
❯ cdk init app --language typescript
Applying project template app for typescript
# Welcome to your CDK TypeScript project!
This is a blank project for TypeScript development with CDK.
The `cdk.json` file tells the CDK Toolkit how to execute your app.
## Useful commands
* `npm run build` compile typescript to js
* `npm run watch` watch for changes and compile
* `npm run test` perform the jest unit tests
* `cdk deploy` deploy this stack to your default AWS account/region
* `cdk diff` compare deployed stack with current state
* `cdk synth` emits the synthesized CloudFormation template
Initializing a new git repository...
Executing npm install...
npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated
npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated
npm WARN deprecated sane@4.1.0: some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added
✅ All done!
bin/first-aws-cdk.ts -> cdkのinitialize設定
lib/first-aws-cdk-stack.ts -> stack情報の設定
cdk synth
cdk command: cdk synth
これをするとcdkを用いて作成したcodeを元にCloudFormationのテンプレートJSONファイルが出力される。
cdk synth
コマンドを実行すると、次のCloudFormationテンプレートを出力しcdk.outディレクトリが作成される。
出力されるのはjsonファイルで、このjsonファイルの記述量を見るに、cdkの便利さがよくわかる。
cdk bootstrap
cdk command: cdk bootstrap
プロビジョニングをしてくれるらしい。
AWS CDKアプリをAWS環境(AWSアカウントとリージョンの組み合わせ)にデプロイするには、AWSCDKがデプロイを実行するために必要なリソースをプロビジョニングする必要がある場合があります。これらのリソースには、ファイルを保存するためのAmazon S3バケットと、デプロイの実行に必要なアクセス許可を付与するIAMロールが含まれます。これらの初期リソースをプロビジョニングするプロセスは、ブートストラップと呼ばれます。
実行するとCloudFormationのstacksに下記ができている。
CDKToolkit CREATE_COMPLETE
2021-07-27 15:00:29 UTC+0900
The CDK Toolkit Stack. It was created by cdk bootstrap
and manages resources necessary for managing your Cloud Applications with AWS CDK.
cdk deploy
❯ cdk deploy
FirstAwsCdkStack
2021-07-27 15:18:54 UTC+0900
CREATE_COMPLETE
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
AWS CDKを使ったディレクトリ構造を見ていく。
cdk.jsonがcdkToolkitに対し、実行方法を伝える。
その際に、ts-node
からbin/first-aws-cdk.ts
が伝えられる。
bin/first-aws-cdk.ts
ではlib/first-aws-cdk-stack.ts
を使ってstack情報をnewしようとしている。
……だと思う。
npm i @aws-cdk/aws-s3
import * as cdk from '@aws-cdk/core'
import { Bucket } from '@aws-cdk/aws-s3'
export class FirstAwsCdkStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props)
new Bucket(this, 'MyFirstBucket')
}
}
その後、
cdk deploy
❯ cdk deploy
FirstAwsCdkStack: deploying...
FirstAwsCdkStack: creating CloudFormation changeset...
✅ FirstAwsCdkStack
作成されたことがわかる。
ブラウザ上のコンソールからも下記のように作成されたことがわかる。
Stack
2021-07-27 16:52:18 UTC+0900 FirstAwsCdkStack UPDATE_COMPLETE -
2021-07-27 16:52:17 UTC+0900 FirstAwsCdkStack UPDATE_COMPLETE_CLEANUP_IN_PROGRESS -
2021-07-27 16:52:15 UTC+0900 MyFirstBucketB8884501 CREATE_COMPLETE -
2021-07-27 16:51:53 UTC+0900 CDKMetadata UPDATE_COMPLETE -
一方で、このやり方で作成されたバケットにはポリシーなどは設定されていないため、しっかりと記述してやる必要があることがわかった。指定するにはBucketPropsに設定するみたい。
AWS CDK Document
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
AWS s3 LifeCycle
これを使うと、設定された時間によって動作を変更できるらしい。
例えば、より低速で安価なストレージにデータを移したり、保管期限の切れたデータを消したりできるんだと思う。
new Bucket(this, 'MyFirstBucket')
上記Bucketにどんなpropsが入るかは下記に書いてある。
new Bucket(scope: Construct, id: string, props?: BucketProps)
でprops?となっていることからpropsはなくても大丈夫。だが、無いと権限設定などのoptionがない状態になる。(当たり前
BucketPropsはオブジェクトなので、下記のようになる。
new Bucket(this, 'MyFirstBucket', {})
オブジェクトの中には、例えばlifecycleRulesが入る。
lifecycleRulesはTypeがLifecycleRule[]なので
new Bucket(this, 'MyFirstBucket', {
lifecycleRules: [
{}
]
})
のようになる。
lifecycleRulesは、LifecycleRuleから情報を取得できる。
expirationのTypeはDurationで、Durationは下記情報から TypeScript (source) @aws-cdk/core » Duration
として使える。
new Bucket(this, 'MyFirstBucket', {
lifecycleRules: [
{
expiration:Duration.days(5),
}
]
})
※import { Duration } from '@aws-cdk/core'
その後、cdk deploy
でstack情報がupdateできる。
2021-07-27 18:04:15 UTC+0900 FirstAwsCdkStack UPDATE_COMPLETE
作成したs3のライフサイクル設定が5日になっていることがわかった。
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
AWS CLI と AWS CDKのCredentials関係
Credentials関係において、AWS CLIのconfigから設定した内容をAWS CDKで読み取ることができるみたい。
推奨事項として、Credentialsはアプリケーション内やブラウザスクリプトにハードコーティングしないことと書かれている。
なるほどねぇ。
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
CDK Commandを学習する
cdk list
app内に設定されているstackをlsする。
json -> first-aws-cdk.tsからstackの数を読み取ってるんじゃないかな。
cdk deploy
オプションで--allですべてのstackをdeployできる。
複数のstackがある状態でcdk deploy
をすると--allを使うようにエラーがでる。
new FirstAwsCdkStack(app, 'FirstAwsCdkStack', {})
new FirstAwsCdkStack(app, 'FirstAwsCdkStack2', {})
❯ cdk deploy
Since this app includes more than a single stack, specify which stacks to use (wildcards are supported) or specify `--all`
Stacks: FirstAwsCdkStack · FirstAwsCdkStack2
❯ cdk deploy --all
FirstAwsCdkStack
FirstAwsCdkStack: deploying...
✅ FirstAwsCdkStack (no changes)
FirstAwsCdkStack2
FirstAwsCdkStack2: deploying...
FirstAwsCdkStack2: creating CloudFormation changeset...
✅ FirstAwsCdkStack2
deployしても変更がない部分に関してno changesと出るのが賢い。
cdk diff
指定されたスタックを、デプロイされたスタック
またはローカルのテンプレートファイルと比較し
スタック、またはローカルのテンプレート・ファイルと比較する。
-> cdk diffをするとcdk.outディレクトリのtemplateファイルが自動生成される。
設定を変更した後でdiffすると現行とどう違うかが確認できる、んだと思う。
❯ cdk diff
Stack FirstAwsCdkStack
Resources
[~] AWS::S3::Bucket MyFirstBucket MyFirstBucketB8884501
└─ [~] LifecycleConfiguration
└─ [~] .Rules:
└─ @@ -1,6 +1,6 @@
[ ] [
[ ] {
[-] "ExpirationInDays": 5,
[+] "ExpirationInDays": 3,
[ ] "Status": "Enabled"
[ ] }
[ ] ]
コードのこの部分が変わっているというより、コンフィグのこの部分に差異があるよ!という指摘に見える。
cdk synthesize
[aliases: synth]
templateファイルの合成はこっちが主。
しかし、一度生成されたtemplateはcdk.outディレクトリから消えないみたい。
cdk destroy
❯ cdk destroy FirstAwsCdkStack2
Are you sure you want to delete: FirstAwsCdkStack2 (y/n)? y
FirstAwsCdkStack2: destroying...
✅ FirstAwsCdkStack2: destroyed
stackをまるごと削除できるが、s3bucketにリソースがあると厄介なエラーが発生するらしい。
ブラウザで削除しようとした際もエラーが発生したので、その類だと思う。
cdk doctor
setupに問題がないか確認してくれる。
❯ cdk doctor
ℹ️ CDK Version: 1.115.0 (build f0ca40f)
ℹ️ AWS environment variables:
- AWS_STS_REGIONAL_ENDPOINTS = regional
- AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1
- AWS_SDK_LOAD_CONFIG = 1
ℹ️ No CDK environment variables
余談メモ
一度deployして作成したbucketに名前をつけようとしてもエラーが出るみたい。
もう既にあるよ!みたいなエラーが出た。
名前変更とかできるのかな?
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
AWS CDK の出力
const myBucket = new Bucket(this, 'MyFirstBucket', {
lifecycleRules: [
{
expiration: Duration.days(3),
},
],
})
new CfnOutput(this, 'myBucket', {
value: myBucket.bucketName,
})
CfnOutputを使うと、stackの出力タブにkeyとしてmyBucketを登録し、
myBucket firstawscdkstack-myfirstbucket(bucketName)にすることができる。
なんとなくだが、今回の作業を通じて、初回ビルド時にbucketNameというのは確定してしまうというのがわかった。
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
outputでParametersを指定する。
const duration = new CfnParameter(this, 'duration', {
type: 'Number',
default: 6,
minValue: 1,
maxValue: 10,
})
const myBucket = new Bucket(this, 'MyFirstBucket', {
lifecycleRules: [
{
expiration: Duration.days(duration.valueAsNumber),
},
],
})
new CfnOutput(this, 'myBucket', {
value: myBucket.bucketName,
})
上記のようにdurationを設定するとcdk deploy --parameters duration=10
のように設定ができる。
なお、この設定でdurationを11などにすると、FirstAwsCdkStack failed: Error [ValidationError]: Parameter 'duration' must be a number not greater than 10
のようになる。
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
ここまでやって思ったのは、コンソールGUIでポチポチやるのはあまり好きじゃないので、すごく使いやすいなという感想。
ポリシーの設定などやってみたい。
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
Serverless Stackとしてバックエンドを作成する。
ApiGateway -> Lambda -> DynamoDBのように接続する。
学習前に読んだ記事
ApiGateway
Lambda
DynamoDB
RDBMSとの相性問題(過去の話
DynamoDBを今後活用するなら読もうと思う記事
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
AWS CDK v2を使う
開発者プレビュー版とのことで、本番環境作成には適さないようだが、今後メジャー化するだろうと予想しv2でのコース作成となったみたい。
現状もまだ開発者プレビュー版(RC)だけど、機能を見てみるとバージョン管理が楽そうだったり、機能が整理されていたりと便利そうなのでこっちを学習してみる。
コースではnpmでの作業になっているが、yarnを使ってみる。
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
backendを構築する。
Errorに遭遇した。Udemyに投稿したものから抜粋
普通にインストールすると、下記の内容が足りなかった。
というか、constructsが3系のインストールになり依存関係が合わないと言われる。
warning " > aws-cdk-lib@2.0.0-rc.14" has incorrect peer dependency "constructs@^10.0.0".
warning " > ts-node@10.1.0" has unmet peer dependency "@types/node@*".
下記がエラー
エラーにあったバージョン
"devDependencies": {
"aws-cdk": "^1.115.0",
"aws-cdk-lib": "^2.0.0-rc.14",
"constructs": "^3.3.107",
"ts-node": "^10.1.0",
"typescript": "^4.3.5"
}
正常系
"devDependencies": {
"@types/node": "^15.0.1",
"aws-cdk": "^1.115.0",
"aws-cdk-lib": "^2.0.0-rc.14",
"constructs": "^10.0.5",
"ts-node": "^10.1.0",
"typescript": "^4.3.5"
}
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
cdk.jsonに対し、ts-nodeを活用しているため、tsconfig.jsonでbaseurlを使おうとすると認識されない。
これは普通にtsconfig-pathsで対応できる。
{
"app": "npx ts-node -r tsconfig-paths/register infra/Launcher.ts"
}
![Yutaka Fujii](https://res.cloudinary.com/zenn/image/fetch/s--x4R-Oj_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ec9b05d548.jpeg)
少し手がつけられないので一旦クローズ