OmniAICreator/Qiita-1.07M huggingface dataset:
Salesforceに大容量ファイルをアップロードする

## Salesforce Filesを利用して大容量ファイルをアップロードできるが、APIを利用するときは制約がある。

ContentVersion Object
https://developer.salesforce.com/docs/atlas.ja-jp.object_reference.meta/object_reference/sforce_api_objects_contentversion.htm

>SOAP API を使用してアップロードできるファイルの最大サイズは 50 MB です。ドキュメントが API を使用してアップロードまたはダウンロードされると、base64 に変換され、VersionData に格納されます。この変換により、ドキュメントサイズは約 37% 増加します。アップロードする予定のファイルが変換後に 50 MB 未満になるように base64 変換による増加を考慮します。

Blob データを挿入または更新する
https://developer.salesforce.com/docs/atlas.ja-jp.api_rest.meta/api_rest/dome_sobject_insert_update_blob.htm

>You can insert or update blob data using a non-multipart message, but if you do, you are limited to 50 MB of text data or 37.5 MB of base64–encoded data.

要するに、50MB制限を突破するためには以下の条件が必要
 - REST APIを利用する
 - Requestをmultipart/form-data形式で送信する

この記事ではSimple-Salesforceを利用して、ファイルをアップロードしてみる。

試験環境
 - Python 3.10
 - simple-salesforce 1.12.5
 - Salesforce API Version V57以上 (Winter'23)

## アプロードするコード
現在ディレクトリに50MB以上の`largefile.zip`が存在していると仮定する。

```python
import os
import pprint
from simple_salesforce import Salesforce
from simple_salesforce import format_soql
import datetime
import base64
import json

def create_version_large_file(sf, filename, title=None):
    """Salesforceに50MB以上のファイルをアップロードする

        Args:
        sf (Salesforce): simple_salesforceインスタンス
        filename (string): アップロードするファイル名
        title (string, optional): Salesforceにアップロードする際のファイル名
    """
    if title is None:
        title = filename

    url = '{}sobjects/ContentVersion'.format(sf.base_url)

    metadata = json.dumps({
        'Title': title,
        'PathOnClient': filename,
    })

    with open(filename, 'rb') as f:
        content = f.read()

    files = [
        ('entity_content', ('', metadata, 'application/json')),
        ('VersionData', (filename, content, 'application/octet-stream'))
    ]

    headers = {
        'Authorization': sf.headers['Authorization'],
    }

    response = sf.session.post(url=url, headers=headers, files=files)
    json_response = response.json()

    version_id = json_response['id']
    return version_id

# Salesforce接続情報
username = '<ユーザ名>'
password = '<パスワード>'
security_token = '<セキュリティトークン>'

# Simple-Salesforceインスタンスを作成
sf = Salesforce(username=username, password=password, security_token=security_token)

# アップロードするファイル名
filename = 'largefile.zip'
result = create_version_large_file(sf, filename)
print('アップロード結果：', result)
```

これでうまくアップロードできたことが確認できた。:relaxed:
Firebase Cloud Messaging API（V1）でのPushテストの方法

# 概要

以前から利用していたFirebaseのCloud MessagingAPI(レガシー)の期限が迫ってきました。

![fcm-expire.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/6b0dbc15-f7c8-5936-ede9-29e97d99de74.png)


で、Firebase Cloud Messaging API（V1）に移行が必要なのですが、これをすると困ることがあります。

それは、いままでDebug用のアプリメニューから、Push通知テストを試すコマンドをSlackに送る仕組みを作っていたのですが、その仕組みがそのままでは使えなくなりますし、面倒になります。

ので、その対応の記事です。

# 何が面倒になる？

レガシーの場合は、Pushのテストをするときに、Httpヘッダーの`Authorization` に固定のキーを入れておけばよかったのですが、これからは、アクセストークンに変わります。（セキュリティが強化されました）
アクセストークンは、秘密鍵を使って生成できますが、それをアプリに入れることはできません。
レガシーの頃の固定値のようにDebugアプリにそのまま仕込むことはできません。

詳しくは、以下の移行の方法を確認しましょう。
https://firebase.google.com/docs/cloud-messaging/migrate-v1?hl=ja

# 今後はどうする？

OAuth 2.0 Playgroundを使えば良いです。
https://developers.google.com/oauthplayground/

# こうする

1. OAuth 2.0 Playgroundで「Cloud Messaging API v1」 を選択し、「Authorize APIs」ボタンを押下します

    ![スクリーンショット 2024-02-05 17.20.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/78d0df37-2a2e-2064-a5cf-e92ae7fff287.png)

    ここで、開発で利用しているアカウントで認可しときます。

2. 次に 「Exchange authorization code for tokens」 ボタンを押下します。押下するとAccess Tokenが設定されます

    ![スクリーンショット 2024-02-05 17.23.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/b4f440e8-3e89-1229-5fd5-44a80018cc89.png)

3. Request URIに入力します

    Request URI : `https://fcm.googleapis.com/v1/projects/プロジェクトID/messages:send`
    HTTP Method : `POST`

    ![スクリーンショット 2024-02-05 17.31.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/eb6d482f-72a0-7baa-b0c9-6c525314bd35.png)

    Request URIのプロジェクトIDは、Firebaseコンソールの「全般」にあるプロジェクトIDのことです。

    「Enter Request Body」をタップして、PushテストするためのJSONを入力します。

    たとえば、以下です。
    ここでの\<FCM_TOKEN\> は、端末のトークンを指定します。そうすれば自分の端末だけにしかPushが届きません。

    ```json
    {
        "message": {
            "token": "<FCM_TOKEN>",
            "data": {
                "body": "You Got A Notification",
                "title": "You Got A Notification",
            }
        }
    }
    ```

    つまり、Androidの実装の `FirebaseMessaging.getInstance().token` で取得成功した時の結果のことです。
    レガシーでは `"to"` で指定していた値です。ヘッダーで指定するアクセストークンではないので注意です。

    で、最後に 「Send the Request」 ボタンを押下するとPushが送られます。
    (ちなみにレガシーでもこの方法でテストできます)

# おまけ

2で取得したアクセストークンを使えば、`curl`コマンドでも当然、Push通知を送ることができます。
これをデバッグメニューでslackに送り、アクセストークンを入力してcurlで送る運用にすれば、少しステップは増えるけど、今までとそんなに変わらずにテストができそうです。（アクセストークンを取得できるアカウントがないとできませんが...）

```shell
$ curl -X POST \
--header "Authorization: Bearer <アクセストークン>" \
--header "Content-Type: application/json" \
https://fcm.googleapis.com/v1/projects/<プロジェクトID>/messages:send -d " \
{ \"message\": {\"token\":\"<FCM_TOKEN>\",
\"data\":{\"body\": \"You Got A Notification\", \"title\": \"You Got A Notification\"}}}"
```
Zodで始める型安全な世界: TypeScriptの強力な味方

# Zodとは
TypeScriptで使用するためのバリデーションライブラリです。型安全な方法でデータの検証を行うことができ、特にAPIのリクエストやレスポンスのバリデーション、アプリケーション内でのデータ構造の検証に役立ちます。Zodを使うと、開発者はスキーマを定義して、そのスキーマに基づいてデータの形状や型をチェックできます。このプロセスは完全に型安全であり、TypeScriptの型推論の恩恵を受けることができます。

# Zodの主な特徴
### 型安全なバリデーション
ZodはTypeScriptの型システムを活用し、コンパイル時に型安全を保証します。これにより、ランタイムエラーのリスクを減らしつつ、開発の生産性を高めることができます。

### 簡単なスキーマ定義
Zodを使用すると、オブジェクト、配列、文字列、数値、日付など、さまざまなデータ型のスキーマを簡単に定義できます。これにより、データの構造と期待される型が明確になります。

### カスタムバリデーション
ユーザーはカスタムバリデーション関数を定義して、特定の検証ロジックを実装することができます。これにより、アプリケーション固有のバリデーション要件に柔軟に対応できます。

### エラーハンドリング
Zodはバリデーションエラーを詳細に報告し、どのフィールドがどのような理由でバリデーションに失敗したかを簡単に特定できるようにします。

# 使用例
Zodは、APIのリクエストボディやクエリパラメータの検証、設定ファイルや外部サービスからのデータの構造検証など、さまざまなシナリオで役立ちます。たとえば、外部APIからのレスポンスの形状をチェックするためにスキーマを定義し、そのスキーマに基づいてデータを検証することができます。

Zodは、型安全性を重視するTypeScriptの開発者にとって、強力で便利なツールです。開発プロセスをより効率的かつエラーの少ないものにし、アプリケーションの品質を向上させることが期待できます。

# 基本的な型
### 文字列
```
import { z } from 'zod';
const stringSchema = z.string();
```
### 数値
```
const numberSchema = z.number();
```
### ブール値
```
const booleanSchema = z.boolean();
```
### オブジェクト
```
const userSchema = z.object({
  name: z.string(),
  age: z.number(),
  email: z.string().email(),
});
```
### 配列
```
const userSchema = z.object({
  name: z.string(),
  age: z.number(),
  email: z.string().email(),
});
```
### タプル
```
const tupleSchema = z.tuple([z.string(), z.number(), z.boolean()]);
```
### 列列挙型
```
const tupleSchema = z.tuple([z.string(), z.number(), z.boolean()]);
```
### カスタムバリデーション
```
const passwordSchema = z.string().min(8).max(20).refine((val) => /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/.test(val), {
  message: "Password must contain at least one letter and one number",
});
```
Railsでログインを押すとログアウトに表示を変更する方法

## Railsでログインを押すとログアウトに表示を変更する方法

今回はRuby on Railsでログイン機能を実装します！
ログイン機能を実装しようとすると、ログイン・ログアウト・新規登録のボタンが3つできるかもしれません。今回は3つできるボタンを2つで実装し、ログインボタンを押したらログアウトと表示できるようにしていきたいと思います！(イメージは以下の動画です)
![ログイン.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3687617/30d26900-51b4-51bb-0646-223227b9db92.gif)


:::note warn
注意
この記事は、すでにログイン・ログアウト・新規登録の実装ができていることを前提に書いています。
:::

### 目次
1.View周り
2.コントローラー設計
3.ルート周り


## View周り
まず、ビューページのどこかに以下のようにログイン・ログアウト・新規登録のボタンを実装しているかもしれません。

```ruby:tweets/index.html.erb
  <%= link_to "ログイン", tweets_path %>
  <%= link_to "新規登録", new_user_registration_path %>
  <%= button_to 'ログアウト', destroy_user_session_path, method: :delete %>
```

しかしWebサイトでは、ログイン機能はほとんどヘッダーに実装されることが多いボタンになります。そこで、今回はヘッダーに書いてみましょう！
また、今回はif文を使用していくので以下のようにビューページを編集します。
```ruby:layouts/application.html.erb
<% if user_signed_in? %>
    <a href="/users/sign_out" data-method="delete" class="button1">
        <span class="button1__text">Log out</span>
    </a>
<% else %>
    <a href=" /users/sign_in.html" class="button1">
        <span class="button1__text">Log in</span>
    </a>
<% end %>
    <a href=" /users/sign_up.html" class="button1">
        <span class="button1__text">Sign up</span>
    </a>
```

## コントローラー設計
次にコントローラーを作成します。
```ruby:コマンド
rails g controller users
```

作成したコントローラーに以下を書きます。

```ruby:users_controller.rb
class UsersController < ApplicationController
    def test_destroy
        delete destroy_user_session_path
        @request.env["devise.mapping"] = Devise.mappings[:user] 
        assert_response :success
    end
end
```

## ルート周り
最後にルートを書きます。
devise_for :usersの下に書くといいと思います！

```ruby:routes.rb
  devise_scope :user do
    get '/users/sign_out', to: 'devise/sessions#destroy'
    delete '/users/sign_out', to: 'devise/sessions#destroy'
  end
```

以上です！
TiDBにDeep Diveするためのリンク集

TiDB Docs
https://docs.pingcap.com/tidb/stable/overview

TiDB Cloud Docs
https://docs.pingcap.com/tidbcloud/tidb-cloud-intro

TiKV Deep Dive
https://tikv.org/deep-dive/introduction/

TiDB Introduction Blog Part 1, Part 2, Part 3
https://www.pingcap.com/blog/tidb-internal-data-storage/
https://www.pingcap.com/blog/tidb-internal-computing/
https://www.pingcap.com/blog/tidb-internal-scheduling/

Introduction to TiDB
https://eng.edu.pingcap.com/learner/courseinfo/id:203

TiDB Essentials
https://eng.edu.pingcap.com/learner/courseinfo/id:190

TiDB: A Raft-based HTAP Database
https://www.vldb.org/pvldb/vol13/p3072-huang.pdf

Building a Large-scale Distributed Storage System Based on Raft
https://tikv.org/blog/building-distributed-storage-system-on-raft

Large-scale Incremental Processing Using Distributed Transactions and Notifications
https://research.google/pubs/large-scale-incremental-processing-using-distributed-transactions-and-notifications/

F1: A Distributed SQL Database That Scales
https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/41344.pdf

Building a Database from Scratch: the Evolution of TiDB
https://www.youtube.com/watch?v=BPnv21E0W1w

TiDB: On the Long Journey of HTAP
https://www.youtube.com/watch?v=mmzoSkEhYrA

How TiDB Keeps Performance Predictable under a High Load
https://www.youtube.com/watch?v=tzA4yHeSzZQ

The Design of TiDB's Columnar Storage Engine, TiFlash
https://www.youtube.com/watch?v=KXN6XsQx2b0

TiDB Customer Story of Square
https://www.youtube.com/watch?v=TjqL50qzy3A

Scaling SQL at Flipkart with TiDB
https://www.youtube.com/watch?v=wUrNVYRUCSk

A Critique of ANSI SQL Isolation Levels
https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-95-51.pdf
【Swift】割り算の商と余りが欲しい！！

# はじめに
私の今までの知識を使って実装します。

```swift
let q = 10 / 3
let r = 10 % 3

print("商: \(q), 余り: \(r)") // 商: 3, 余り: 1
```

まぁ悪くないですが、もっといい方法がありました。

# 実装
```swift
import Foundation

let (q, r) = 10.quotientAndRemainder(dividingBy: 3)

print("商: \(q), 余り: \(r)") // 商: 3, 余り: 1
```

# おわり
Swift知識が増えました

# 公式ドキュメント
https://developer.apple.com/documentation/swift/int/quotientandremainder(dividingby:)
アプリケーション自動作成系AIの LTを聞いてのメモ

先日行われた [AI駆動開発(AI-Driven Development) 勉強会（第1回）](https://aid.connpass.com/event/306406/) にて 1KK0 さん ( @eltociear さん) が
「🧑‍🤝‍🧑→🤖と移りゆくアプリ開発」
というタイトルでLT登壇されていました。大変ありがたかったです。

とても興味深く面白かったので自分用のメモとして記録とさせてください。

https://speakerdeck.com/eltociear/toyi-riyukuapurikai-fa?slide=12


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47327/4b8c3138-f646-84da-4232-b733a7e72a92.png)

生成AIをソフトウェアの開発チーム（ソフトウェア会社）のメンバーとしてそのロールを与えつつ、ソフトウェアを生成させるというものだそうです。
アプリ開発完全未経美少女エンジニアが最強のToDoアプリを怒りに任せて自作するまでの話#2(1/23~2/5)

### 自己紹介
🌻著者プロフィール🌻
名前：おじょち(25歳)
技術領域：ねっとわーく(よわ)、さーば(よわよわ)、ことりん(げきよわ)
趣味：おさんぽ、くりーむそーだ
# 前回までのあらすじ
- ToDoアプリを自作してやると意気込む
- 挫折
    - 以上

# 最近のおじょち


お久しぶりです、おじょちです🤗

（最近Xも始めたのでフォローしてね🤗）

（@ojochi_510510）

先週に更新するといいましたが！！それは嘘になりました！！(ﾔｹｸｿ)

だってKotlinが難しすぎてかけることなかったので😡😡😡😡😡😡

と、いうわけで、この期間私がやっていたことを紹介していきます！

---

- Kotlin公式チュートリアル
    - 時間かかり過ぎで挫折✖
- UdemyのKotlinコース
    - 自己紹介アプリの開だーん！🤗
    初めてアプリつくれたから！あとで！みせるね！！
- TODOアプリの作成
    - Android Studioのバージョン違いでうまくつくれず1挫折、、、
    - バージョンを合わせてリトライ！完成！

---

、、、、こんなかんじです😢😢😢

Kotlinってなんなんこれ、、、というか開発って全然簡単じゃないじゃん、、、😢
TODОアプリが可愛くないなんて言ってゴメンだったよ、、、

もう愛くるしく見えてくるよ、、、
そもそも自分で書いたコードのはずなのに意味がわからないよ😢😢😢😢😢😢

# 成果物お披露目
### 自己紹介アプリ
[詳細を表示]ボタンを押すと、趣味とか居住地が隠れます！！！
すごいね！！！
![Screenshot_2024-02-05-22-14-27-14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1566153/c72c031e-d402-64d7-2fe6-158707d16d7e.jpeg)

### ToDoアプリ

タスクの追加、編集、削除ができます！！！

![Screenshot_2024-02-05-22-14-49-01_73df57d78f2763bb71de0b540a75136d.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1566153/2ff3627a-6d00-ad04-88db-c05917d1b521.jpeg)


![Screenshot_2024-02-05-22-15-00-11_73df57d78f2763bb71de0b540a75136d.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1566153/1a373ec3-6219-7875-0c04-5093b903ba53.jpeg)

# 初めての開発を終えて

正直わたし自身がなんのコードを書いているか全くわからなくなってしまいました。。。😢
(ハンズオンって楽しいけど、脳みそ使わないでできちゃうからね。。。)

というわけで、これからどうしていくかといいますと、、、

！！！毎日コードを紐解いていって何とかわかるところまで行こう！！！

ということです🤗
地道に努力しますってことですね🤗

と、その前に、そもそも、クラスだのインスタンスだのメタデータだの、、、
わからないことでいっぱいだったので、わたしなりにまとめたものを見てください。。。😭

---

🚀 クラス（設計図） 
🛠️: クラスってのは、これから生まれるインスタンスちゃんたちのためのスーパーかわいい設計図なの！
🌟 部品のカタログみたいなもので、どんな見た目🎨や動き🏃‍♂️があるか、全部ここで決めちゃうの！
実行すると、カタログからぴょんっとインスタンスちゃんが飛び出してくるの！ワクワクだね！😍

🌟 データ（プロパティ） 
🎨: プロパティさんたちはね、インスタンスちゃんたちのキュートな見た目の要素を決めるの！🌈
 例えば、Carクラスだったら、「color（色）🚗」「model（モデル）🏎」「year（年式）📅」などなど！
ここで指定した通りに、インスタンスちゃんたちはキラキラ輝くの！✨

🎶 メソッド（手続き）
 🕺: メソッド君たちは、インスタンスちゃんたちがどんな素敵な動きをするかを教えてくれるの！🎵
 Carクラスのインスタンスだったら、
「start()でエンジン始動💨」
「stop()でエンジン停止🛑」
「accelerateで加速🚀」などがあるよ！
これでインスタンスちゃんたちはアクティブに動き回れるね！

🌟 インスタンス（オブジェクト） 
🎉: ここで登場するのが、クラスの設計図から生まれたインスタンスちゃんたち！💕
 それぞれがプロパティさんたちが決めた素敵な見た目と、メソッド君たちが指示するステキな動きを持ってるの！🌟

🔍 メタデータ
 📊: メタデータってのは、データについての情報なの！
写真データの場合だと、
「位置情報🌍」
「撮影日📆」
「ファイル形式📁」などがあるよ！
これでデータを整理したり検索したりするのがラクラクになるの！👍

---

いかがでしょうか？
こんな感じで、来週からはわからない奴らに立ちむあって行こうと思います！！

今回はここまで！！！

# さいごに
めちゃむずいんですけど😡😡😡😡😡😡

ここまでお付き合いいただきありがとうございました！
ではまた！🤗

次回：🌻02/13更新🌻
→　2/6~2/12までの進捗を書きます！
Pythonの確認とインストール(Mac)

## 前提
MacPCでPythonを使えるように準備します
筆者が利用しているM2のチップを搭載したMacPCでのメモになります

Pythonをは主にAWSのLambdaで利用したいので、処理の動作テストなどをローカル環境で動かせるよう準備します

筆者のMacPCのバージョンは下記内容になります
```zsh
ProductName:		macOS
ProductVersion:		14.3
BuildVersion:		23D56
```

## まずは確認
Macには標準でPythonがインストールされています
ターミナルからPythonのバージョンの確認をしてみましょう

```zsh
% python --version
```
```zsh
zsh: command not found: python
```
実行結果です
Macには標準でPythonがインストールされているはずですがこのようにエラーが出ました

あれ、Python入って無いじゃんって思うかもしれません
今度はこちらを試してみてください
```zsh
% python3 --version
```
```zsh
Python 3.11.6
```
実行結果です、Pythonのバージョンが確認できました！

現在は最新がPython3系なのでM2チップのMacにはPython3系がインストールされていたみたいです
MacPCの購入時期やOSのバージョンによってはPythonのバージョンも変わっているかもしれません

この確認でpythonのインストールが確認できた方はここまでも大丈夫です

Pythonのインストールが確認できなかった、または標準でインストールされているPythonが古い、バージョン指定してインストールしたい場合は次のインストールに進んで下さい

## インストール
インストール方法は色々ありますが今回は公式サイトからインストールする方法とHomebrewでインストール方法の2種類を記載します

### 公式サイト
https://www.python.org/downloads/macos/

上記公式サイトからインストールしたいバージョンのPythonのパッケージをDLしてください
ダウンロードした「.pkg」ファイルを開いてインストールするできます

### Homebrew
Homebrewがインストール済みの方はbrewでのインストールができます

```zsh
% brew install python
```
バージョン指定しない場合は最新のPythonがインストールされます

### Homebrewでバージョン指定する場合

バージョンを指定する場合は先にインストール可能なPythonのバージョンを検索してみましょう
```zsh
% brew search python | grep "python@"
python@3.10
python@3.11
python@3.12
python@3.7
python@3.8
python@3.9
```
検索結果から利用したいバージョンを指定してインストールします
```zsh
% brew install python@3.1２
```

## おわり
特に問題がなければMac標準のPythonでそのまま利用で良さそうです
次はPythonのプログラムとして基本的な使い方を書こうと思います
Docker desktopをインストールしたが、command not found

業務で、簡易的なnginxサーバーをDocker環境で構築することになったのですが、dockerコマンドのパスが通らないことがあったので、対処法を備忘録として残しておきます。

## 構築環境
- mac OS
    - Sonoma 14.3
    - Apple chip(M2)
- Docker　Desktop 
    - version　4.9.1

## 起きた事象

下記より、`Apple チップの Mac`用をダウンロード、インストールし、
https://matsuand.github.io/docs.docker.jp.onthefly/desktop/mac/install/
下記コマンドを叩いたところ、
```
$ docker  --version
zsh: command not found: docker

```

## 原因、対象
docker desktopをインストールすると、以下のシンボリックリンクへのパスが追加されるはずが、なんらかの理由により失敗した可能性がある。
PATHに`~/.docker/bin`に追加することで、パスが通った。
```
$ docker --versioni
Docker version 20.10.16, build aa7e414
```

## 参考にしたページ
- https://teratail.com/questions/rcple66ofn8g76
【AWS】buildspec.yamlで使う「aws ecr get-login」と「aws ecr get-login-password」の違い

# 概要

`buildspec.yaml`を利用してAWS CodeBuildでビルドする際の、
DockerイメージをAWSのECRにプッシュするために使用するコマンドについて。

以下のようにyamlに記載していましたが、これは古い認証方法とのこと。
（CLIコマンドとして使うときも同様）

```yaml
  - $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
```

以下のように書き換えることが推奨されています。

```yaml
  - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
```

なぜか？今回調べてみました。

## `aws ecr get-login`と`aws ecr get-login-password`の違い

1つ目のコマンドでは、`aws ecr get-login`を使用してDockerログインコマンドを生成し、そのコマンドを実行しています。この方法は、AWS CLI v1では使われていたようですが、AWS CLI v2では非推奨とのこと。パスワードがシェルのhistoryやログファイルに残ってしまうリスクがあったためです。

2つ目のコマンドでは、`aws ecr get-login-password`を使用してECRからDocker認証トークンを取得し、そのトークンを使用してDockerにログインします。パスワードを標準入力（`--password-stdin`）を通じてDockerに渡すため、コマンドラインやシェルの履歴にパスワードが残らないようになりました。こちらはAWS CLI v2で推奨されていますし、セキュリティの観点からも好ましいでしょう。

どちらも一時的な認証トークンではありますが、パスワードをパイプラインを通じて`docker login`コマンドに渡せる2番目の方が良い、ということになります。

公式ドキュメントから引用

> get-login-password を使用して Amazon ECR レジストリに対して Docker を認証するには、aws ecr get-login-password コマンドを実行します。認証トークンを docker login コマンドに渡すとき、ユーザー名に AWS 値を使用し、認証先の Amazon ECR レジストリの URI を指定します。

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/registry_auth.html

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/getting-started-cli.html

## 補足

ちなみに、一つ目の方法の際、`aws ecr get-login-password --region ap-northeast-1`というように`$()`がない場合だと`no basic auth credentials`というログが出ます。これは以前記事にしたのでご参考までに。

https://qiita.com/Ryo-0131/items/766f0986e2e24dd0377f


## そのほか参考：

https://zenn.dev/mn87/articles/9d87931fc1a24b

https://qiita.com/hayao_k/items/3e4c822425b7b72e7fd0

https://dev.classmethod.jp/articles/aws-cli-v2-ecr-get-login-password/
[翻訳自動化]イメージファイルからテキストを抽出し、翻訳する

# 背景
仕様書や論文を読んでいくとき、わからない英文をコピペしては、翻訳、コピペしては、翻訳、、、大変面倒です。さらにイメージファイルではコピペができない！そんなわけで、翻訳の自動化を試みました。
# 使用技術
<dl>
<dt>MATLAB</dt>
<dD>基本的な実装のために使用しました</dd>

<dt>Computer Vision toolbox</dt>
<dd>MATLABでOCRを使用するために使用しました</dd>
<dt>Google Apps Script</dt>
<dd>Google翻訳のAPIを実装するために使用しました</dd>
</dl>

# 実装方法
下記を実装することで実現しました。
1\. OCRによるイメージファイルからのテキスト抽出実装
2\. GASによるGoogle翻訳APIを実装
3\. MATLABからGASの実行
## 1.OCRによるイメージファイルからのテキスト抽出実装
Computer Vision toolboxの関数である「ocr」を使用してイメージファイルを読み込みテキストを取得します。

今回読み込むサンプル(example.comのスクショ)
![example.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662936/84131809-2a31-0750-b07c-93d8a7ebbf3e.png "読み込むイメージファイル")

下記MATLABコードでイメージファイルを読み込みます
```matlab:ocr.m
    % イメージファイルの読み込み(pngFileName：イメージファイルのパスを入力)
    pngFileInfo = imread(pngFileName);
    
    % 読み込んだイメージファイルを使用しOCRでテキストを抽出
    pngObj = ocr(pngFileInfo);
    
    % テキスト取得
    targetText = pngObj.Text;
```
## 2.GASによるGoogle翻訳APIを実装
取得したテキスト情報(targetText)をGoogle翻訳にかけるためのAPIをGASで実装します。
こちらの素晴らしい記事を ~~パクらせて~~ 参考にさせていただきました。
https://qiita.com/tanabee/items/c79c5c28ba0537112922

```javascript:googleTransAPI.gs
function doGet(e) {
  var p = e.parameter;
  var translatedText = LanguageApp.translate(p.text, p.source, p.target);
  return ContentService.createTextOutput(translatedText);
}
```
このコードをデプロイし、Google翻訳APIのURLを作成しました。

## 3.MATLABからGASの実行
MATLABによって今回抽出したテキストデータをURLに設定し、
GETメソッドによるHTTPリクエストを実施します。

```matlab:request.m
    % google翻訳のGAS APIにアクセスする
    % HTTPリクエストを送るurlを作成する
    base = ['https://script.google.com/macros/s' ...
            '/AKfycbw57UQkAv2Yhqzr-0n2USD2STnS_yGn8SYkABTLxCZemKxbE' ...
            'z8YIbMjdFhTyjkPEaw73A/exec'];

    % English →　Japanese
    sourceLang = 'en';
    targetLang = 'ja';
    url = strcat(base, '?text=', targetText ,'&source=', sourceLang, '&target=', targetLang);

    %GASにてリクエスト→結果表示
    web(url);
```

# 結果表示
上記のmスクリプトを関数化しました。引数にはpngファイルのパスを指定します。
![スクリーンショット 2024-02-05 220043.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662936/4201f26b-bd0e-5ca2-45fa-b267ffd3ebb0.png)

自動で翻訳が完了しました。
![ret.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662936/2a69c6ce-149c-9203-029c-64b2227a4457.png)

# あとがき
仕様書や論文のファイル形式はPDF形式が多く、PDFに対応したかったですが、、、、
もうちょっと掘り下げてPDFにも対応して再度投稿しようと思います。

㎰.GASを初めて触りましたが、便利ですね、、、Googleアカウントがあればほぼ100％使えますし、興味が出てきました。業務効率化のためキャッチアップしようと思います！



以上です！
ライブラリとフレームワークの違いについて


## はじめに
ReactやNext.jsを学習している時、ライブラリとフレームワークという文言が出てきたが、
違いがいまいちわからなかったため調査してみました。

## ライブラリ(Library)
ライブラリとは、開発者が必要に応じて選択し、利用するさまざまなツールや関数を集めたものです。
自分でプロジェクトの構造を設計しながら、必要な機能だけを取り入れて開発を進めることが可能です。

### ライブラリに該当するもの
React, jQuery

## フレームワーク(framework)
フレームワークには、開発を進めるための特定のルールや構造が設けられています。
開発者はこれらの枠組みの中でプロジェクトを構築することになります。
フレームワークを使用することで、開発プロセスの一貫性や効率が高まりますが、
逆に言えば、フレームワークが定めるルールに従って開発を進めなければならないという制約もあります。

### フレームワークに該当するもの
Next.js, Laravel
Clould Functionsを用いたFirestoreのサブコレクション削除にバッチ処理を用いる

## 背景
この記事の続きっぽい感じ。

https://qiita.com/TIshow/items/d3898f201233c4e53491

## 背景
Firestoreのデータ操作には、一括で多くのドキュメントを扱うことが問われることが多い。
バッチ処理は、複数の操作を一つのトランザクションとして処理し、データ整合性を保ちながら効率的にタスクを完了させることができるため、特にサブコレクションを含む大量のドキュメントを扱う際に使えそうと考えた。

## この記事の対象者
この記事は、Firestoreを使用しているが、サブコレクションの削除処理に頭を悩ませている開発者、またはFirebaseを学習中の方々に少しでも参考になればと思いメモを残しておく。

## 問題点
あるドキュメントが削除された際に、そのドキュメントに紐づくサブコレクションが自動的に削除されない。

例えば、あるデータに関連する多数のコレクションやサブコレクションがある場合、そのデータのドキュメントを削除しても、これらのコレクションやサブコレクションは残り続け、不要なデータが蓄積される可能性がある。

このような状況は、データベースのパフォーマンスを低下させるだけでなく、データ管理の複雑化を招き、最終的にはアプリケーションのメンテナンス性にも悪影響を及ぼす。

## やること
Firebase Functionsを活用して、特定のドキュメントが削除された際に、それに紐づくサブコレクションも自動的に削除する処理を実装する。
その際、バッチ処理などを使ってメモリリミットを回避できるように気を配る。

## 解決案
Firebase Admin SDKを使用して、ドキュメントとそのサブコレクションを一括で削除する方法を採用。
Admin SDKにはrecursiveDeleteメソッドがあり、これを使用することで指定したドキュメントとそのサブコレクションを再帰的に削除することができる。


## 完成したコード

```typescript:typescript
import * as functions from "firebase-functions/v1";
import * as FirebaseAdmin from "firebase-admin";
import * as logger from "firebase-functions/logger";
import { QueryDocumentSnapshot } from "@google-cloud/firestore";

FirebaseAdmin.initializeApp();
const db = FirebaseAdmin.firestore();

// バッチ処理の関数
async function processBatch(
  collectionId: string,
  subcollectionId: string,
  lastDoc?: QueryDocumentSnapshot | null,
) {
  const BATCH_SIZE = 10;
  let query = db.collection(`collections/{collectionId}/subcollections`)
    .where("subcollectionId", "==", subcollectionId)
    .limit(BATCH_SIZE);

  if (lastDoc) {
    query = query.startAfter(lastDoc);
  }

  const snapshot = await query.get();

  if (snapshot.empty) {
    return null; // タスクがなければ処理終了
  }

  const batch = db.batch();

  for (const doc of snapshot.docs) {
    batch.delete(doc.ref);
  }

  // バッチ処理を実行
  await batch.commit();

  // 次のバッチのために最後のドキュメントを返す
  return snapshot.docs[snapshot.docs.length - 1];
}

export const deleteDocuments = functions
  .region("asia-northeast1")
  .firestore.document("collections/{collectionId}/subcollections/{subcollectionId}")
  .onDelete(async (snapshot, context) => {
    const collectionId = context.params.collectionId;
    const subcollectionId = context.params.subcollectionId;

    let lastDoc = null;
    do {
      lastDoc = await processBatch(collectionId, subcollectionId, lastDoc);
    } while (lastDoc);

    logger.log(`Successfully deleted all subcollection: ${subcollectionId}`);
  });

```

`deleteDocument`は、Firestoreドキュメントが削除されると自動的にトリガーされるCloud Functionである。
この関数は`processBatch`を繰り返し呼び出し、関連するすべてのサブコレクションが削除されるまで処理を続ける。

`processBatch`は、指定されたサブコレクションを持つドキュメントをバッチサイズの制限内で検索し、見つかったドキュメントとそれに関連するサブコレクションを削除する。バッチ処理により、これらの削除操作が一つのトランザクションとして扱われ、処理の効率が大幅に向上する。







## お疲れ様でした。
この方法により、Firestoreのデータ構造における親子関係を持つデータの整合性を維持しつつ、不要になったデータを効率的に削除できると思う。
また、この処理はサーバーサイドで実行されるため、クライアント側の負荷を軽減できる利点もある。

わからないところ、間違っているところ、もっといい方法がある場合は、コメントでもDMでも教えてください。
cat -v について

---
cat -v について
---

**天体観測**

_見えないものを見ようとして_
_望遠鏡を覗き込んだ_

>
> BUMP OF CHICKEN 『天体観測』

　いい歌ですよね。
望遠鏡の先の景色は、何が広がっていたんでしょうね。

 大人になると、見たくないものも見えてしまうものです。

 まあでも、たまには、見えないものを見ようとしたっていいじゃないですか。

　見えるうちにね。

**目次**
[1. cat -vとは](#1-cat--vとは)
[2. テスト例](#2-テスト例)
[3. おわりに](#3-おわりに)

# 1. cat -vとは

 　`cat`（concatenateの略）コマンドは、テキストファイルの内容を標準出力（通常は画面）に表示するためによく使用されます。
 
　`-v` オプションを付けることで、通常は見えない制御文字も特定の表現で表示します。

　`cat -v` コマンドは、特にデバッグやファイルの内容確認において非常に有用です。

 <font color="low blue">**非表示文字とは**</font>
 
　非表示文字には、タブ文字、改行文字、そしてASCII制御文字が含まれます。
 
 　これらは通常、テキストエディタでは直接表示されませんが、cat -v を使用すると、これらの文字を視覚化して確認することができます。

 <font color="low blue">**cat -v の動作**</font>
ASCII制御文字（0x00 から 0x1F）は、^ に続けて特定の文字で表示されます（例：0x01 は ^A と表示）。
DEL文字（0x7F）は ^? と表示されます。
拡張ASCII文字（0x80 から 0xFF）は、M- に続けて特定の文字で表示されます。

　詳しくは下記のサイトに
>[参考]
[IBM man](https://www.ibm.com/docs/ja/aix/7.2?topic=c-cat-command#cat__row-d3e66480)

# 2. テスト例
　このコマンドを使って、実際にどういう挙動になるのかテストしてみます。
 
まずは、ASCII文字全て（0x00 から 0x7F）と非ASCII文字（0x80 から 0xFF）を準備します。

　本当はファイルをそのまま張りたかったのですが、やり方がわからず、ここでは紹介のみとさせていただきます。

 本来は
 ```sh
 echo -e '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' > test.txt

 ```

 のコマンドでうまくいくはずですが、私は無理でした。後日、そのファイルを含んだファイルを共有させて頂きます。

　できたファイルの中身はこんな感じです。

 ```txt
   	


 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~≠ヤ・㊧炎旧克署葬灯楓利劒屆撼泛｡｢｣､･ｦｧｨｩｪｫｬｭｮｯｰｱｲｳｴｵｶｷｸｹｺｻｼｽｾｿﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎﾏﾐﾑﾒﾓﾔﾕﾖﾗﾘﾙﾚﾛﾜﾝﾞﾟ珮粤蒟跚韜・・ⅰ涇・
 ```

  文字化けしまくってますね(;^_^A

このファイルを`cat -v`してみると

```
^@^A^B^C^D^E^F^G^H
^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^]^_`abcdefghijklmnopqrstuvwxyz{|}PM-^QM-^RM-^SM-^TM-^UM-^VM-^WM-^XM-.M-/M-0M-1M-2M-3M-4M-5M-6M-7M-8-PM-QM-RM-SM-TM-UM-VM-WM-XM-YM-ZM
```

のように出力されます。

　これで、ファイルの中に非アスキー文字の、なにがどこに配置されているかがわかるようになります。

# 3. おわりに

　ファイルのバイト数をはかったところ

```sh
wc -c test.txt 
> 256 test.txt (出力)
```

となりました。

　あたりまえなのかもですが、256バイトなんだよなーとASCIIを実感した時間でした。
【JavaScript】配列と繰り返し(for文)

今日は配列と繰り返しで初心者がこのあたりからつまずきそう...
という部分を解説してみました！
最近Railsの投稿ばかりだったので、少し気分転換で！

## 配列とfor文
まずはこれを見てください。
```javascript:script.js
const fruit = ["apple", "banana", "orange"];
for(let i = 0; i<3, i++){
    console.log(fruit[i]);
};
```
ぱっと見でどういう意味か分かるでしょうか。
これは配列とfor文を組み合わせたものです。
少し分解してみていきましょう。
```javascript:
const fruit = ["apple", "banana", "orange"];
```
まず左辺でconstを用いてfruitという定数の定義を行っています。
右辺では定数fruitの中身を配列の形で並べています。(左からインデックス番号は0,1,2)

```javascript
for(let i = 0; i<3, i++){
    console.log(fruit[i]);
};
```
ここではfor文を用いて、for(変数の定義; 条件式; 変数の更新)
という順番で記述されています。
ここでいうと、変数iに0を代入、iが3より小さいとき、i+1(変数++で変数に+1するという意味です。条件がfalseとならない限り更新を繰り返します。)を実行するという意味になっています。
そしてconsole.log(fruit[i]);とすることで、fruitの中の配列のインデックス番号0~2までを出力します。
出力は
```javascript
apple
banana
orange
```
となります。
iの部分は定義しなくてもconsole.log(fruit[0]);...と力技で出力することはできますが、
今回と違ってインデックス番号100まで出力したいときや、ただでさえ条件式が長いときは記述の重複している部分をなくすため、変数を定義して条件などを付ける方が可読性が増します。
値を順番に繰り出したいな～と思ったらfor文を是非思い出して使ってみてください！
資格受験・受験予定レポート

## ここ最近

11月に転職したことをきっかけに、最近いろんな資格の勉強中です。

通勤時間が３倍くらいになったのですが、スマホアプリとかSNSとか頑張っても１０分くらいしか時間つぶせないので、暇つぶしがてらにはちょうどいいですね。

## 受験レポート（ざっくり）

### ITパスポート

大学生の時に授業内で練習問題を解いてから名前すら聞かなかった資格。
勉強しなくてもいけるだろと余裕をぶっこいていたら、合格点ギリギリでした。

IT企業で働くうえでというか、このご時世ではITパスポートレベルの知識がない人は、特に若い人はどうするんだろうと思うレベルで基礎がまとめられていると感じました。

## 日経テスト

このテストに関しては、試験当日まで２択選択式だと思ってた。
まさかの４択で驚愕しました。

でも勉強してもしょうがい内容だったので記念受験としては面白かったです。

## MOS EXCELLエキスパート

現在勉強中です。
圧倒的に一番勉強してて面白い。

エクセルって本当に神アプリなんだなと改めて感じました。


## TOEIC

４年前の自分はどこえやら。
当時はバイリンガル並みに話せる・聞けると思っていたのに・・


## WEB〇〇検定３級

再来週受験予定ですが、試験名がわからないくらいなにもしていません。
WEB系のテストということでこちらは大丈夫でしょう。
TerraformCloudでEC2インスタンスを起動して接続するまで

## 結論
1.キーペアを作成する
2.key_nameで指定する
3.githubにpushしてTerraformCloudでapplyしてインスタンス起動
4.sshで接続する

4ステップで終わりか！余裕だね！

## 経緯
今までEC2インスタンス起動する時ってキーペアを新規作成していて、都度秘密鍵をダウンロードしていた。
TerraformCloudで実行しているからローカルに出力とかできないしどうすんだ？と思ったのがきっかけ。そういえばキーペアって一回も使ったことがなかった。

## 1.キーペアを作成する
EC2 > キーペア　からキーペアの作成
今回はwindowsでteratermから接続する予定なので**RSA**の.pem形式を選択
名前は「tfc_key」、秘密鍵はローカルで保管。

## 2.key_nameで指定する
key_nameのところにキーペアの名前を入れてあげる
```.tf
provider "aws" {
  region = "us-east-1"
}

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  key_name      = "tfc_key"

  tags = {
    Name = "ExampleInstance"
  }
}
```



## 3.githubにpushしてTerraformCloudでapplyしてインスタンス起動
ここはまた別の記事で詳細まとめようと思います。
とりあえずTerraform Cloud上でapplyしたらインスタンスが起動された。

## 4.sshで接続する
teratermからパブリックIPv4アドレスを入力してsshで接続。余裕でした。
今回AMIはAmazonLinux2023で起動した。デフォルトユーザー名はec2-userらしいので、それを入力して秘密鍵選択して接続***できない！！！なんで！？？***

## 5.なんか色々設定を見直す
もちろんTerraformではEC2以外（VPCとか）も作成しているのでその設定を確認したり、起動したEC2インスタンスのキーペアを確認してちゃんと紐付けられているかなどなど、、、

## 6.「teraterm」「AmazonLinux2023」「繋がらない」
全然Terraform関係ないところで問題がありました
参考にさせていただきました↓

https://qiita.com/sugimount-a/items/78b5c02d4c286b7c266b

https://www.geekfeed.co.jp/geekblog/amazonlinux2023-al2023/

teratermのバージョンによってはAmazonLinux2023に接続できない（ssh-rsaシグネチャ無効化に引っかかる）らしい。使っているteratermのバージョンは**4.106**、***アウト！***

## Terraformに関する記事じゃないんですか？
新しいことを始めて上手くいかない時、まず疑うのは全く自信がない新しく学び始めた範囲になるのは仕方ない。灯台下暗しを教訓とした備忘録。
CMSで作るモダンECサイト

## こんなもの作りました。

義理の母がお花屋さんをしていて、たまに個人でお店をだしていたりしてるのですが、かなりセンスが良くリピーターも多いので「ECサイトで販売したら売れるのでは？！」と思い実際に作ってみました。

https://smallforest.online/
（レスポンシブ対応していないため、PC表示だとかなり崩れて表示されます・・）

宣伝もかねて紹介させてもらいます。

## 使用技術

- WordPress
- PHP
- Bootstrap
- その他もろもろの無料サーバ、DBなどなど

## 各パーツとこだわり

ロゴも自作です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3480394/e17e00c6-590f-790b-ae9d-6af729f10b47.png)


TOPバナーのくすみ加工とカラーがお気に入りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3480394/8a043bb5-a35a-06f2-224a-dd0a8a6c5bc3.png)


各ページのタイトルも実は画像ではなくほとんどCSSで作ってます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3480394/8f0a12aa-bc1e-64df-2bbb-f3453bc82797.png)


ECサイト部分の価格絞り込みもかなりスムーズに動きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3480394/72299065-2b34-a60a-a74f-d36a068ea510.png)

ログイン認証機能も付けてます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3480394/077b69c4-b902-d3a0-6fe4-682a326a0cb9.png)


##　展望

デザイン、機能面含めても花屋にしてはかなりのスペックがあるかなと。

コンテンツとしてはまだまだなのでこれから充実させていこう。
【実践編】データベース設計書｜ログイン機能

> ログインの機能について
「設計フェーズ：データベース設計書」を作成してください。
開発者のチームに対してどのような指導を行いますか？
重要なポイントを教えてください。
どのようなステップがありますか？

ログイン機能に関する「設計フェーズ：データベース設計書」を作成し、開発者チームへの指導を行う際の重要なポイントとステップは以下の通りです。

# データベース設計書の内容

### 概要

ログイン機能に関連するデータベース設計の目的と概要を説明します。

### エンティティと属性の定義

ユーザーエンティティを中心とした、必要なエンティティ（テーブル）とその属性（フィールド）をリストアップします。例：ユーザーID、ユーザー名、パスワード（暗号化済み）、メールアドレス、登録日時など。

### リレーショナルモデル

エンティティ間の関係を定義し、リレーショナルモデル（ER図など）で図示します。

### 正規化

データの冗長性を避け、更新の異常を防ぐために、データベースを適切な正規形に正規化するプロセスを説明します。

### インデックス設計

クエリのパフォーマンス向上のために、インデックスを設定するカラム（例：ユーザー名、メールアドレス）を指定します。

### セキュリティ対策

パスワードの暗号化、SQLインジェクション対策など、データベースのセキュリティを確保するための対策を記述します。

### バックアップとリカバリ

データの安全性を確保するためのバックアップ戦略とリカバリプロセスを記述します。

# 開発者チームへの指導ポイント

### 正規化の理解

データベースの正規化の重要性を理解し、データの冗長性と一貫性のないデータを避けるように指導します。

### セキュリティの徹底

パスワードの暗号化やSQLインジェクション対策など、データベースセキュリティに関するベストプラクティスを徹底するよう指導します。

### パフォーマンスへの配慮

インデックスの適切な使用やクエリの最適化など、データベースのパフォーマンスを考慮した設計を行うよう指導します。

### ドキュメントの活用

データベース設計書を開発の基盤として活用し、設計書に沿った実装を行うことの重要性を強調します。

# データベース設計のステップ

### 要件分析

ログイン機能に必要なデータ要件を明確にします。

### エンティティの特定

必要なエンティティ（テーブル）とその属性（カラム）を特定します。

### 関係の定義

エンティティ間の関係を定義し、ER図などで図示します。

### 正規化

データベースを適切な正規形に正規化して、データの冗長性を排除します。

### インデックスの設計

クエリのパフォーマンスを向上させるために必要なインデックスを設計します。

### セキュリティ対策の検討

データの保護とセキュリティを確保するための対策を検討します。

### ドキュメントの作成

上記の情報をもとに、データベース設計書を作成します。

### レビューと調整

設計書を関係者と共有し、レビューを受けて必要に応じて調整します。

データベース設計はシステムの性能と信頼性に大きく影響するため、正確さとセキュリティへの配慮が求められます。開発者チームは設計書を正しく理解し、その指針に従って実装を進める必要があります。
【実践編】システム設計書｜ログイン機能

> ログインの機能について
設計フェーズ：システム設計書を作成してください。
開発者のチームに対してどのような指導を行いますか？
重要なポイントを教えてください。
どのようなステップがありますか？

ログイン機能に関するシステム設計書（基本設計書）を作成し、開発者チームへの指導を行う際の重要なポイントとステップは以下の通りです。

# システム設計書の内容

### 概要

ログイン機能の目的と全体の概要を記述します。

### アーキテクチャ設計

ログイン機能を実現するためのシステムアーキテクチャ、主要なコンポーネント、それらの関係を図式化します。

### データモデル

ユーザー情報、認証データなど、ログイン機能に関連するデータの構造を定義します。

### インターフェース設計

ユーザーインターフェース（UI）のレイアウト、画面遷移図、UI要素の詳細を記述します。

### 認証フロー

ユーザーの認証プロセスを図示し、各ステップの動作を詳細に記述します。

### セキュリティ要件

パスワード管理、セッション管理、データ暗号化など、セキュリティに関連する要件と対策を記述します。

### エラーハンドリング

認証失敗、セッションタイムアウトなど、想定されるエラーのリストとそれに対するハンドリング方法を記述します。

### テスト計画

ログイン機能のテストに関する概要、テストケース、テスト環境の要件を記述します。

# 開発者チームへの指導ポイント

### 設計の重要性の理解

開発者が設計書の内容を正確に理解し、設計に基づいて開発を行うことの重要性を強調します。

### セキュリティへの配慮

セキュリティ要件を遵守し、安全なコードを書くことの重要性を指導します。

### 品質保証

設計書に沿った開発だけでなく、品質保証の観点からも適切なテストが行われるよう指導します。

### ドキュメントの活用

開発プロセス中に設計書を参照し、必要に応じてフィードバックを提供することの重要性を指導します。

# 設計フェーズのステップ

### 要件の確認

要件定義書を基に、ログイン機能に関する要件を再確認します。

### アーキテクチャの設計

システム全体の構造と、ログイン機能を実現するための主要なコンポーネントを設計します。

### データモデルの定義

必要なデータ構造を定義し、データベーススキーマを設計します。

### インターフェースとユーザー体験の設計

ユーザーインターフェースの設計を行い、ユーザーが直感的に操作できるUIを考慮します。

### セキュリティ要件の詳細化

ログイン機能のセキュリティを保証するための具体的な要件を定義します。

### 設計書の作成

上記の内容をもとに、詳細なシステム設計書を作成します。

### レビューと調整

設計書を関係者と共有し、レビューを受けて必要に応じて調整します。

システム設計書は開発の指針となる重要なドキュメントです。開発者チームには設計書の内容を正確に理解し、設計に基づいた開発と適切なセキュリティ対策の実施を徹底するよう指導することが重要です。
【実践編】ビジネスケース定義書｜ログイン機能

> ログインの機能について
ビジネスケース定義書を作成してください。
開発者のチームに対してどのような指導を行いますか？
重要なポイントを教えてください。
どのようなステップがありますか？

ログイン機能に関するビジネスケース定義書を作成し、開発者チームへの指導を行う際の重要なポイントとステップは以下の通りです。

# ビジネスケース定義書の内容

### プロジェクトの背景

ログイン機能の導入または改善が必要とされる背景、現状の課題や問題点を説明します。

### ビジネス目標

ログイン機能によって達成したいビジネス上の目標や成果を明確にします。例えば、ユーザーエクスペリエンスの向上、セキュリティ強化、新規ユーザーの獲得など。

### ソリューションの提案

ログイン機能の具体的な提案内容を記述します。これには、技術的アプローチ、利用する技術やツール、予定される主要機能などが含まれます。

### 利益とコストの分析

プロジェクトの実施による利益（効果、収益の増加、コスト削減など）と、開発・運用にかかるコスト（開発費用、人件費、維持管理費など）を分析します。

### リスクと対策

プロジェクト実施に伴う潜在的なリスクを特定し、それらに対する対策を提案します。

### 実施計画

プロジェクトのタイムライン、フェーズごとの主要な活動、マイルストーン、納期などを記載します。

# 開発者チームへの指導ポイント

### ビジネス目標の理解

開発者がビジネスケースの背景とビジネス目標を理解し、それに沿った開発を行うように指導します。

### コスト意識の醸成

開発プロセスにおけるコスト効率の良い選択を行うよう、コスト意識を持って開発に取り組むことを指導します。

### リスクへの対応

プロジェクトのリスクを認識し、リスクが現実のものとなった際に適切に対応できるよう指導します。

### 成果物の品質

ビジネス目標達成に必要な品質の成果物を提供することの重要性を強調し、品質管理に対する意識を高めます。

# ビジネスケース作成のステップ

### 情報収集

プロジェクトの背景、目標、関連するデータや情報を収集します。

### 分析

収集した情報を基に、プロジェクトの利益とコスト、リスクと対策を分析します。

### ドキュメントの作成

分析結果を基にビジネスケース定義書を作成します。

### レビューと承認

関係者にドキュメントをレビューしてもらい、必要に応じて修正を行った後、承認を得ます。

### 開発者チームへの共有

ビジネスケース定義書を開発者チームに共有し、プロジェクトの目標と期待を明確にします。

ビジネスケース定義書は、プロジェクトの経済的正当性を評価し、関係者にプロジェクトの価値を伝えるための重要なドキュメントです。開発者チームには、ビジネスケースの内容を深く理解し、ビジネス目標の達成に向けて貢献するよう指導することが重要です。
【実践編】ステークホルダー分析書｜ログイン機能

> ログインの機能について
ステークホルダー分析書を作成してください。
開発者のチームに対してどのような指導を行いますか？
重要なポイントを教えてください。
どのようなステップがありますか？

ログイン機能に関するステークホルダー分析書を作成し、開発者チームへの指導を行う際の重要なポイントとステップは以下の通りです。

# ステークホルダー分析書の内容
### ステークホルダーの識別

ログイン機能に関わる、または影響を受ける全てのステークホルダーをリストアップします。例えば、エンドユーザー、開発チーム、プロジェクトマネージャー、セキュリティチーム、マーケティングチームなど。

### ステークホルダーの要求

各ステークホルダーのログイン機能に関する具体的な要求や期待を記述します。例えば、エンドユーザーは使いやすさを重視するかもしれませんが、セキュリティチームはセキュリティ要件を最優先するでしょう。

### ステークホルダーの影響度

ログイン機能に対する各ステークホルダーの影響度を評価し、記述します。影響度が高いステークホルダーの要求は、開発プロセスにおいて特に重視されるべきです。

### コミュニケーション計画

各ステークホルダーとのコミュニケーション方法、頻度、情報共有のプロトコルを定義します。適切なコミュニケーションを通じて、ステークホルダーの期待を管理し、プロジェクトの進行に彼らを巻き込む方法を検討します。

# 開発者チームへの指導ポイント

### ステークホルダーの理解

開発者がステークホルダー分析書を通じて、プロジェクトに関わる全てのステークホルダーとその要求を理解することが重要です。

### 要求の優先順位付け

ステークホルダーの影響度と要求を考慮し、要求の優先順位を適切に設定し、それに基づいて開発を進めます。

### フィードバックの積極的な取り入れ

ステークホルダーからのフィードバックを積極的に取り入れ、プロジェクトの改善に役立てます。

### コミュニケーションの重要性

ステークホルダーとの適切なコミュニケーションを維持することの重要性を理解し、コミュニケーション計画に従って行動します。

# ステークホルダー分析のステップ

### ステークホルダーの特定

プロジェクトに影響を与える、または影響を受ける個人やグループを特定します。

### 要求の収集

インタビュー、アンケート、ワークショップなどを通じて、各ステークホルダーの要求や期待を収集します。

### 分析と評価

収集した情報を分析し、各ステークホルダーの影響度と要求の優先順位を評価します。

### ドキュメントの作成

分析結果をもとにステークホルダー分析書を作成します。

### レビューと調整

ステークホルダー分析書を関係者と共有し、フィードバックを受けて必要に応じて調整します。

ステークホルダー分析はプロジェクトの成功に不可欠なプロセスであり、全てのステークホルダーの要求をバランスよく満たすソリューションを開発するための基盤を提供します。開発チームには、この分析を理解し、それに基づいて効率的で効果的な開発を行うよう指導することが重要です。
【実践編】要件定義書｜ログイン機能

> ログインの機能を例にして
要件定義書を作成してください。
開発者のチームに対してどのような指導を行いますか？
重要なポイントを教えてください。
どのようなステップがありますか？

ログイン機能に関する要件定義書を作成し、開発者チームへの指導を行う際の重要なポイントとステップを以下に示します。

# 要件定義書の内容

### 概要

ログイン機能の目的と、その機能が果たすべき役割についての説明。

### 機能要件

ユーザー認証：正しいユーザー名とパスワードを入力したユーザーのみがシステムにアクセスできること。
エラーハンドリング：不正な入力や認証失敗時に適切なエラーメッセージを表示すること。
セッション管理：ログイン後はユーザー情報をセッションで管理し、ログアウトまたはセッションタイムアウトでセッションを終了すること。

### 非機能要件

セキュリティ：パスワードは暗号化して保存し、SQLインジェクションやクロスサイトスクリプティング（XSS）などの脆弱性に対策を講じること。
パフォーマンス：認証プロセスはユーザーにとって快適なレスポンス時間内に完了すること。
ユーザビリティ：ログインフォームは直感的に操作できること。

### 制約事項

技術的制約、法的制約、運用上の制約など、開発や運用における制約条件を記載。

### 用語集

要件定義書内で使用される専門用語の定義。

# 開発者チームへの指導ポイント

### 要件の理解

開発者が要件定義書の内容を正確に理解し、要件通りの機能を実装できるようにします。

### セキュリティ意識の強化

ログイン機能はセキュリティが非常に重要な部分なので、セキュリティ対策を徹底するよう指導します。

### テストケースの作成

要件を満たすための詳細なテストケースを作成し、開発中および開発後に十分なテストを行うよう指導します。

### ドキュメントの更新

開発プロセス中に要件に変更が生じた場合は、要件定義書を更新し、常に最新の状態に保つよう指導します。

# 要件定義からリリースまでのステップ

### 要件収集

ステークホルダーから要件を収集し、ログイン機能に必要な要件を明確にします。

### 要件定義書の作成

収集した要件を基に、上述の内容を含む要件定義書を作成します。

### 設計

要件定義書に基づいて、ログイン機能の詳細設計を行います。

### 実装

設計書に従って、ログイン機能のコーディングを行います。

### テスト

単体テスト、結合テスト、システムテストを行い、要件を満たしているか確認します。

### リリース前準備

リリースノートの作成、最終的な確認作業を行います。

### リリース

製品をリリースし、エンドユーザーに提供します。

要件定義書は、開発の出発点となる重要なドキュメントであり、開発者が要件を正確に理解し実装するための基盤となります。そのため、要件定義書の作成には十分な注意を払い、開発チームが要件を適切に理解し実装できるようにサポートすることが重要です。
Next.jsのESLint+Prettier+ Huskyテンプレート

## はじめに

Next.jsは、Reactアプリケーションの開発を簡素化するフレームワークです。ESLintとPrettierは、コードのエラーを識別し、フォーマットを整えるのに役立ちます。Huskyを使用すると、Gitのコミットフックを利用してコードの品質を自動的に管理できます。[サンプルコード](https://github.com/toshiki-git/Template_Nextjs-with-ESLint-Prettier-Husky)はこちらです。

## 手順

### 1. Next.jsとTypeScriptの環境構築

まず、新しいNext.jsプロジェクトを作成します。

```bash
$ npx create-next-app my-next-app
$ cd my-next-app
```

### 2. Visual Studio Codeの設定

#### .vscodeディレクトリの作成

プロジェクトルートに`.vscode`ディレクトリを作成し、以下のファイルを追加します。

- `extensions.json`

  ```json
  {
    "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
  }
  ```

- `settings.json`

  ```json
  {
    "editor.codeActionsOnSave": {
      "source.fixAll.eslint": true
    },
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
  ```

### 3. ESLintとPrettierの設定

TypeScript用のESLintプラグインとPrettier関連のパッケージをインストールします。

```bash
npm install @typescript-eslint/eslint-plugin --save-dev
npm install prettier eslint-config-prettier eslint-plugin-prettier --save-dev
```

#### .eslintrc.jsonの設定

プロジェクトのルートに`.eslintrc.json`ファイルを作成し、ESLintの設定を記述します。

  ```json
{
      "plugins": ["@typescript-eslint"],
      "extends": [
        "next/core-web-vitals",
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended",
        "prettier"
      ],
      "rules": {
        "no-console": "warn"
      }
}
  ```
#### .prettierrc.jsonの設定

Prettierの設定ファイル`.prettierrc.json`をプロジェクトルートに作成します。
  ```json
 {
      "semi": true,
      "trailingComma": "es5",
      "singleQuote": false,
      "jsxSingleQuote": false,
      "tabWidth": 2,
      "useTabs": false
}
  ```

設定ファイルはチームや個人ごとに適切なものを設定してください。
### 4. Huskyの設定

Huskyとlint-stagedをインストールして、コミット前に自動的にリントとフォーマットを実行できるようにします。

```bash
npm install husky lint-staged --save-dev
```

#### package.jsonの設定

`package.json`に以下のスクリプトと設定を追加します。

- `scripts`に`prepare`を追加：

  ```json
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "prepare": "husky install"
  }
  ```

- `lint-staged`の設定を追加：

  ```json
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": [
      "eslint --fix",
      "prettier --write"
    ]
  }
  ```

#### .husky/pre-commitの設定

Huskyを初期化するために、次のコマンドを実行します。

```bash
npm run prepare
or
npx husky install
```

```bash
npx husky add .husky/pre-commit "npx lint-staged"
```

`.husky/pre-commit`フックを作成し、以下のコマンドを追加します。

npx lint-staged→node_modules/.bin/lint-stagedに変更する
```bash
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

node_modules/.bin/lint-staged
```

これで、Next.jsプロジェクトにESLint、Prettier、およびHuskyの統合が完了しました。これにより、コードの整合性が保たれ、開発プロセスがスムーズになります。
クラステンプレート引数は部分省略できない

テンプレート引数の省略について、関数とクラスとで異なる動きを発見したのでメモしておきます。

# 実行環境
以下の環境で確認しました。
- cl.exe : 14.29.30136.0
- g++ : 11.4.0


# 関数テンプレートの場合

c++では、テンプレート関数のテンプレート引数を推測することができる場合、テンプレート引数を省略することができます。

```c++
template<class A, class B>
void func( A, B ) {}

int main() {
  func<int,int>(1,2);
  func<int>(1,2);
  func(1,2);
}
```

この3つの例の通り、関数のテンプレート引数は省略することができます。

# クラステンプレートの場合
c++17から、クラステンプレートの場合でもコンストラクタから型が推測できる場合、テンプレートパラメータが省略できます。

```c++
template<class A, class B>
struct C {
  C(A, B) {}
};

int main() {
  C<int,int> c1(1, 2);
  // C<int> c2(1, 2); // error
  C c3(1, 2);
}
```

関数の時と同じように推測することができるのですが、 ~~何故か~~ 一部だけ推測することができません。

一応、デフォルト引数を与えると同じことができますが、これでは引数を省略できているとはいえないでしょう...
```c++
template<class A, class B=int>
struct C {
  C(A, B) {}
};

int main() {
  C<int,int> c1(1, 2);
  C<int> c2(1, 2); // ok!
  C c3(1, 2);
}
```

なぜこのような挙動になるのか、もしくは仕様なのか、知っている人がいたら教えていただけると幸いです。

# 参考文献
- [クラステンプレートのテンプレート引数推論 (cpprefjp)](https://cpprefjp.github.io/lang/cpp17/type_deduction_for_class_templates.html)
- [テンプレート引数は部分的に省略できる (Qiita)](https://qiita.com/rennone/items/ec643539821d4731a9bd)
【保存必須】Dockerが全然わからなかった僕が出会った神書籍とそのまとめ

![Docker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2957298/c08beb5f-c778-f8c3-b72d-2f06b04954e3.png)

# はじめに
現在の仕事で、Dockerに関する業務がありました。

開始当初はDockerというものが全くわからず大変苦戦していましたが、本屋で出会った神書籍によってDockerについての理解がかなり深まり、自分でDocker環境を構築することができるレベルまでになりました。

その書籍の紹介とその本で学んだDockerについての知識をまとめたいと思います。

# 書籍紹介
本屋でDockerについての本をいくつか手に取って読んでみて、イラストが多く1番わかりやすそうだったので購入しました。大当たりでした。
色んな記事でもランクインしている書籍なのでぜひおすすめです。

![8150qINEUjL._SL1500_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2957298/c099b92d-9cc9-fef9-b90c-a18879db4809.jpeg)

下記Amazonリンクです。
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
[仕組みと使い方がわかる Docker&Kubernetesのきほんのきほん](https://www.amazon.co.jp/%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%A8%E4%BD%BF%E3%81%84%E6%96%B9%E3%81%8C%E3%82%8F%E3%81%8B%E3%82%8B-Docker-Kubernetes%E3%81%AE%E3%81%8D%E3%81%BB%E3%82%93%E3%81%AE%E3%81%8D%E3%81%BB%E3%82%93-%E5%B0%8F%E7%AC%A0%E5%8E%9F%E7%A8%AE%E9%AB%98/dp/4839972745)

# 概要
### Dockerとは
一言で表すと、「データやプログラムを隔離できる仕組み」

コンテナという箱を用いて、その中に環境を構築して使う感じです。
本来であれば1つのPCで1つの環境しか構築できません。（Pythonのバージョンは1個しか入れられないのと同じ）

Dockerを用いてコンテナごとに環境を管理することで、同じPythonでも違うバージョンの実効環境を共存させることができます。

### Dockerを使うメリット・デメリット
メリットとしては
・複数の環境を1つのPCで扱うことができる。
・仮想環境と比べて軽量（原理は後回しで良い）
・コンテナ技術を用いて、別のPCでも開発環境をすぐに構築できる

デメリットは
・Dockerを使いこなすためには学習コストがかかること
・複数環境を使わない場合はあまりメリットを感じられない

### イメージとコンテナ
##### イメージ
コンテナを作る元のようなもの
イメージだけでは何もできない。コンテナになって初めて環境が構築できる。
レシピのようなDockerFileからイメージを作成する。

##### コンテナ
環境を構築する箱のようなもの
イメージからコンテナを作成することで環境が構築できる

### イメージの作成方法
めちゃくちゃ簡単。
DokerFile作成→Docker buildコマンド
DockerFileの内容は、作りたい環境に合わせてChatGPTを使うと一瞬で書いてくれる。
それか「作りたい環境　DockerFile」で検索したら大抵出てくる
```
# ベースイメージの指定
FROM python:3.9

# 環境変数の設定
ENV PYTHONUNBUFFERED 1

# 作業ディレクトリの設定
WORKDIR /app

# ホストのrequirements.txtをコンテナにコピー
COPY requirements.txt /app/

# Pythonパッケージのインストール
RUN pip install --no-cache-dir -r requirements.txt

# コンテナ内にコピーしたファイルをすべてコピー
COPY . /app/
```

### コンテナの作成方法
##### Docker run
イメージからコンテナを作るためのコマンド
コンテナは作成した瞬間から稼働する。（稼働させたくない場合はdocker create）

##### Docker compose
DockerFileからイメージを作るのと似ている。
環境に関する設定が書かれたYAMLファイルを作る→Docker compose
YAMLもChatGPTに聞いたら作ってくれる。下記がPython環境をお願いした場合。
YAMLファイルの書き方を調べるとお作法が学べる。
```
version: '3.8'

services:
  python_app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./app:/app
    ports:
      - "8000:8000"
    environment:
      - PYTHONUNBUFFERED=1

```
### DockerHub
Dockerイメージを保存しておく場所。（Githubみたいな感じ！）
公式のイメージを持ってきてコンテナ作成したりもできる。
これのおかげで、Dockerイメージをチームで共有してすぐに環境構築したりできる。

### Dockerの使い方
実際に実行したいファイルが格納されているフォルダとリンクさせることができるので、リンクさせた後にそのファイルを実行すると構築した環境で実行ができる。
使い方としてはリンクさせたサーバー上に実行したいファイルを置く→DockerHubからイメージを持ってくる→サーバー上に環境構築→サーバー上のファイルを実行

### Kubernetesについて
こちらについては、応用なので今回は省略します。


# まとめ
この本のおかげで、Dockerについての理解が大変深まった。
まだ自分のローカルでDockerを使った自動化実行は行っていないので、DockerHubを用いて自動実行を行ってみようと思う。
AWS ENI を触ってみる

ENI(Elastic Network Interface) は単体で触る機会があまりなかったので、どんなことができるのか触ってみました。

## ENI

EC2 インスタンスはそれ自体に IP アドレスが付与されているわけではない。
EC2　にネットワーク情報を付与するには ENI が必要。
ENI は EC2 とは独立して存在しているため、EC2 にアタッチしたり、デタッチすることが可能。

インスタンスがネットワークに接続するためのいろんな情報を持たせることができる。
ENI には次の情報を持たせることができる。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-eni.html


> VPC の IPv4 アドレス範囲からのプライマリプライベート IPv4 アドレス
VPC の IPv4 アドレス範囲からの 1 つ以上のセカンダリプライベート IPv4 アドレス
プライベート IPv4 アドレスごとに 1 つの Elastic IP アドレス (IPv4)
1 つのパブリック IPv4 アドレス
1 つ以上の IPv6 アドレス
1 つ以上のセキュリティグループ
MAC アドレス
送信元/送信先チェックフラグ

EC2 を作成すると ENI も自動で作成されている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/c3f3d987-890c-267f-8816-7136629736a8.png)


ENI は単体で作成することができて、セキュリティーグループも ENI に紐づいていることがわかる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/49bbd9ce-1591-ebc7-dfcb-ad8b0010635c.png)


## １つの EC2 インスタンスに IP アドレスを2つ設定する


上で作成した ENI を EC2 に紐づける
1つの EC2 にネットワークインターフェースが複数紐づいていることがわかり、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/dfec76eb-1d89-af4e-d905-80d8c33165da.png)

private ip も2つになっていることがわかる

![貼り付けた画像_2024_01_07_21_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/54fb5606-7a93-4961-a019-914fb328ea73.png)



ENI 単体に public ip アドレレスを割り当てるには Elastic IP アドレスを作成する必要などがありそう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/95b29e97-6c72-a769-0cda-d89599718104.png)


## IP アドレスなどを引き継いで、 EC2 インスタンスを新規作成

IP アドレスは　ENI に紐づいているという話だったので、今ある EC2 を削除して別の EC2 を新規作成した際に、 IP アドレスを引き継ぐこともできる。

ENI の設定で、紐づいている EC2 を削除した際に、一緒に削除されないように設定しておく。

![貼り付けた画像_2024_01_08_16_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/019661f2-ebde-bf13-846d-9c75f0c30f3f.png)

「インスタンスの削除時に削除」の有効化のチェックを外しておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/e68433ee-38fd-93f6-0e7c-d01fa9dd1394.png)

今あるインスタンスを削除して、

![貼り付けた画像_2024_01_08_16_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/76c34819-d440-c704-4d4f-98d087eeab89.png)

別のインスタンを新規で作成。その際にネットワークインターフェイスに既存のものを設定。

![貼り付けた画像_2024_01_08_17_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/c2875ae6-e525-f5c1-bd9a-d428496ff28b.png)


新規作成した EC2 の IP アドレスを確認すると、 public ip アドレスは変わっていたが、private ip アドレスは削除した EC2 から引き継ぐことができている。

今回 public ip アドレスは固定にしていなかったため、変わってしまったが、固定にしてたら public ip アドレスも引き継ぐことができそう。

![貼り付けた画像_2024_01_08_17_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/762678be-58e6-5049-330c-3b1bb43d3a0a.png)



## IP フローティング

EC2 と ENI が独立していることで、障害発生時に ENI を別の EC2 　に自動でアタッチすることで、アクセス先の EC2 を切り替えるなどすることが可能。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/4d032ba6-7656-0815-68a2-186dfb6ff346.png)

## 複数のVPCにEC2インスタンスを接続する

複数の VPC に EC2 インスタンスを接続することもできるらしい。
同一 AZ でないと無理らしい。

https://dev.classmethod.jp/articles/attatch-ec2-to-multiple-vpc/

## 参考

https://dev.classmethod.jp/articles/ec2_takeover_privateipaddr_macaddr/
https://dev.classmethod.jp/tags/eni/
https://aws.amazon.com/jp/about-aws/whats-new/2023/10/multi-vpc-eni-attachments/