OmniAICreator/Qiita-1.07M huggingface dataset:
猿でもわかるAIビジネス活用シリーズ 🐵📊|[第8回] 未来の会社はどうなる？AIが変えるビジネスの最前線

## 1. はじめに - AIによって変わる"働く"のかたち

生成AIや機械学習モデルの進化によって、業務効率化だけでなく、ビジネスの在り方そのものが変わりつつあります。
今までは"人が中心"だった業務設計が、これからは"AIと人が協調"する世界へとシフトしています。

本記事では、AIがどのようにビジネスを変革しているのか、その最前線を実例を通じて解説します。
特に、以下のような疑問を持つ方におすすめです：

- AIを業務にどう組み込めばいいの？
- 実際に導入してうまくいった事例は？
- 現場でつまずかないためのノウハウは？

## 2. AIが実現する未来のビジネスとは？

AIによるビジネス変革は、以下のような3つの方向で進んでいます：

### (1) オートメーションの高度化
単なるルールベースの自動化(RPA)から、AIが文脈を理解して判断・実行する時代へ。

例：
- カスタマーサポートでのチャットボット → 自然言語理解 + セールス連携
- 自動請求処理 → 請求書の文脈判断 + ワークフロー分岐

### (2) 意思決定のインテリジェンス化
データ分析に基づくレポーティングから、予測や提案まで自動で提示できるAIの進化。

例：
- 需要予測 × 自動在庫調整
- 離職率予測 × チーム再構成シミュレーション

### (3) 創造的業務の補助
クリエイティブ領域でもAIがパートナーに。

例：
- 広告文の生成・ABテスト提案
- ソフトウェア設計のドラフト自動化

## 3. 現場導入のリアル：AIレコメンドエンジンをECサイトに組み込む

ここでは、筆者が実際に携わった「商品レコメンドAIの導入事例」をもとに、技術的・実務的なポイントを紹介します。

### 実装構成図

![ai-recommendation-system](https://example.com/image/ai-recommendation.png)

### 使用技術
- Google Cloud Vertex AI + BigQuery
- Python (scikit-learn, pandas)
- Cloud Functions + Firestore (リアルタイム反映)

### 主要ロジック（簡易版）
```python
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity

# 商品特徴のベクトル化
item_features = pd.read_csv("item_feature.csv")
sim_matrix = cosine_similarity(item_features.values)

# 特定ユーザーに似た商品を推薦
def recommend(user_item_id):
    sim_scores = sim_matrix[user_item_id]
    recommended = sim_scores.argsort()[::-1][1:6]
    return recommended
```

### 現場Tips
- 商品特徴ベクトルの正規化は重要（スケール差によるバイアス回避）
- オンライン反映にはバッチ＋リアルタイムのハイブリッド構成が効率的

## 4. 現場でよくある落とし穴

- **精度至上主義に陥る**：精度99%でも、UXが悪ければ意味なし
- **PoCで満足して止まる**：継続改善の仕組みがなければROIは出ない
- **部署横断での合意形成が不十分**：特にマーケ・開発・経営層の連携が重要

## 5. 応用・発展：生成AIと連携した対話型業務支援

最近では、LLM (大規模言語モデル) を使ったチャット型インターフェースも急速に進化。

### 応用例：社内ナレッジベース × LLM
- 従業員がSlackで質問すると、自動でFAQ・ドキュメントから回答
- API連携でJiraチケット作成まで可能

```python
from langchain.chains import RetrievalQA
from langchain.vectorstores import FAISS
from langchain.embeddings.openai import OpenAIEmbeddings

# ドキュメントをベクトル化して検索用に構築
vectordb = FAISS.load_local("./knowledge_faiss")
qa_chain = RetrievalQA.from_chain_type(llm=..., retriever=vectordb.as_retriever())

response = qa_chain.run("部署間連携の仕組みを教えて")
print(response)
```

## 6. まとめ：AIビジネスの現在と未来

### ✅ メリット
- 業務スピード・精度の飛躍的向上
- データに基づいた戦略判断
- 人間はより創造的な業務へシフト

### ⚠️ 課題
- データの整備コストと品質
- モデルの透明性・説明性
- 倫理的・法的リスクへの配慮

未来の企業像は「人とAIが協調する有機体」。
だからこそ、技術だけでなく"どう活かすか"の設計が肝になります。
Apache Camel x Spring Boot でsplit中にcamel:stopすると処理が途中で止まる問題

![5D7658DD-1148-4AA6-B6FF-30E282050A31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4063686/c7eeb326-0213-4216-a553-76992d410fca.png)

## はじめに

Apache Camel で Kafka などからバッチでメッセージを受け取り、`split` を使って1件ずつ処理するケースはよくあります。

このとき、**ある条件で処理を途中で終わらせたい**場合、`camel:stop`（正確には `controlbus` コンポーネントでルート停止を指示）を使いたくなるかもしれません。

しかし、**split中でcamel:stopを呼ぶとバッチ処理が途中で止まってしまう**という落とし穴があります。

本記事では、`camel:stop` の正確な動作を説明した上で、安全な代替方法をご紹介します。

---

## camel:stopとは？ルートを即時停止する強力な手段

`camel:stop` は Camel の処理を停止する手段ですが、実際には `controlbus` コンポーネントを用いて **指定したルート（routeId）を停止**します。

### 使用例：

```xml
<to uri="controlbus:route?routeId=myRoute&action=stop"/>
```

この記述は、`routeId="myRoute"` を持つルートの **すべての処理を即時に停止**します。

### 主な効果：

- `split`、`loop`、`recipientList` などの途中であっても **強制終了**
- エンドポイント（Kafka, Timer, FTPなど）も停止
- ルート単位で Camel コンテキスト内部から **明示的に処理を終わらせられる**

### 使いどころ：

- ワンショット処理やバッチ系で、**明確に「ここで処理を止めたい」**ときに便利
- 定期実行の終了制御などにも有効

### 注意点：

- **split中で使うと、それ以降のバッチ処理が行われない**
- 他の並列ルートに影響することもある（エンドポイント共有時など）
- アプリケーション全体の終了を意図せず招く場合もある

---

## 問題点：split中でcamel:stopを呼ぶと残りのメッセージが処理されない

以下のようなルートで `split` 中に `camel:stop` を呼ぶと：

```xml
<route id="dangerousSplitRoute">
  <from uri="kafka:my-topic?batch=true"/>
  <split streaming="true">
    <simple>${body}</simple>
    <choice>
      <when>
        <simple>${body} contains 'stop'</simple>
        <to uri="controlbus:route?routeId=dangerousSplitRoute&action=stop"/>
      </when>
      <otherwise>
        <to uri="bean:recordProcessor"/>
      </otherwise>
    </choice>
  </split>
</route>
```

この処理では、対象のメッセージを受信した時点でルート全体が停止されるため、**バッチで受け取った他のメッセージは処理されません。**

---

## 解決策：camel:stopの代わりに「何もしない終了ルート」を作る

Camel では、安全に処理を「スキップ」または「終了」したいだけなら、**自作の「何もしないルート」**を用意してそこに分岐させるのが安全です。

```xml
<route id="safeSplitRoute">
  <from uri="kafka:my-topic?batch=true"/>
  <split streaming="true">
    <simple>${body}</simple>
    <choice>
      <when>
        <simple>${body} contains 'stop'</simple>
        <to uri="direct:camelstop"/>
      </when>
      <otherwise>
        <to uri="bean:recordProcessor"/>
      </otherwise>
    </choice>
  </split>
</route>

<route id="camelstopRoute">
  <from uri="direct:camelstop"/>
  <log message="このメッセージは終了条件に一致しました。処理をスキップします。"/>
  <!-- 実際には何も処理しない -->
</route>
```

---

## この構成のメリット

- **split中でも他のメッセージ処理に影響を与えない**
- **「ここで終わる」ことがコード上で明示されていて分かりやすい**
- **将来的に通知やログ追加も可能で拡張性がある**
- **テストしやすい：`mock:camelstop` に差し替えて検証可能**

---

## まとめ

- `camel:stop` は Camel のルートを即座に終了させる強力な機能だが、**使いどころを誤るとバッチ処理が中途半端に終わるリスクがある**
- 特に `split` 中で使うと、**未処理のメッセージが出る可能性あり**
- **代替策として「何もしないルート」を明示的に呼び出す構成**にすると、安全かつ意図が明確な設計になる
猿でもわかるAIビジネス活用シリーズ 🐵📊|[第7回] LLMを活用したカスタマーサポート自動化の方法



こんにちは！AI活用ブロガーのマイです🌸  
今回は、今もっともホットな技術「**LLM（大規模言語モデル）**」を使って、**カスタマーサポートを自動化する方法**をご紹介します！

「問い合わせ対応に追われて本業に集中できない…」  
「スタッフの負担が大きいのに、顧客満足度は上がらない…」  
そんなお悩み、**LLMがまるっと解決**してくれるかもしれません✨

---

## 🤖 LLMってなに？ChatGPTだけじゃない！

LLM（Large Language Model）とは、ChatGPTのように自然言語を理解・生成できるAIのこと。  
最近では、企業向けに以下のような機能が注目されています：

- チャットボットとしての即時回答
- 顧客の質問に対するFAQ自動生成
- 対応履歴からナレッジを蓄積・再利用

しかも、コードが書けなくても導入できるツールが増えてきており、**中小企業でもすぐに始められるのが魅力！**

---

## 🧭 ステップ別：LLMでカスタマーサポートを自動化する方法

### ✅ ステップ①：問い合わせ内容の収集と分類
まずは、現在の問い合わせ内容を収集し、「よくある質問」「緊急対応が必要なもの」などに分類。  
LLMにとって重要なのは**学習データの質と量**です！

📌 **ツール例**：NotionやGoogle Sheetsで分類データを蓄積

---

### ✅ ステップ②：FAQの自動生成 or 強化
分類したデータをもとに、LLMにFAQの回答文を生成してもらいます。  
ChatGPTやClaudeなどに、「この質問に対して自然な返答を作って」と依頼するだけ。

📌 **ポイント**：曖昧な表現には注意し、社内用語の解説も加えると◎

---

### ✅ ステップ③：チャットボットの構築・接続
生成されたFAQをチャットボットツールに連携させ、**WebサイトやLINE、Slackなどで自動対応ができる環境**を整えます。

📌 **ノーコードツール例**：
- **KARAKURI**（日本製、カスタマー対応に強い）
- **Chatbase**（ChatGPTベースで導入が簡単）
- **Zendesk AI**（CRMとの連携◎）

---

### ✅ ステップ④：実運用・改善サイクル
運用後も、回答精度の確認、フィードバック収集が重要！  
LLMは**継続的に学習・改善**することで、より自然で正確な対応が可能になります。

📌 **チェック項目**：
- 「解決率」は上がっているか？
- 顧客の「満足度」はどう変化したか？
- オペレーターの「対応時間」は減ったか？

---

## 💡 実際に効果はあるの？

ある地方のECサイト（従業員15名）では、以下のような成果が出ました：

| 導入前 | 導入後（3ヶ月） |
|--------|------------------|
| 毎日20件の問い合わせ | 80％が自動対応で完了 |
| スタッフ2名が常時対応 | 対応時間が1/3に削減 |
| 顧客満足度 ★★☆☆☆ | 顧客満足度 ★★★★☆ |

---

## 🔍 導入前に考えるべき3つのこと

1. **どこまで自動化する？**  
　→ クレーム対応などは人間対応を残す方が◎  
2. **社内リテラシーは？**  
　→ 使う側もトレーニングを受けると精度UP  
3. **データ管理は？**  
　→ 個人情報やセンシティブな情報の扱いに注意

---

## ✅ まとめ：LLMは“接客のパートナー”になる

💬 **対応品質はキープしたまま、業務負担は軽くする**  
🤖 **LLMは顧客満足度と生産性を両立させる最強ツール**



---

📣 フォロー & いいねで最新記事をチェック！  
わからないことがあれば、コメントで気軽にどうぞ😉
【ネットワーク】CORS

# はじめに

こんにちは。アメリカに住みながら、独学でエンジニアを目指しているTairaです。

現在インターネットの知識の確認するインターネットクイズを定期的にやっているのですが、そこで出てきたCORSについて説明していきたいと思います

## CORSの説明の前に

CORS（Cross-Origin Resource Sharing）を説明する前に、オリジンについて説明します。
オリジンは一般的に以下の3つを合わせたものを指します

- **スキーム** (http/または https)
- **ドメイン名/IP** (localhost, example.com など)
- **ポート番号** (3000, 5173 など)

これらの任意の1つが異なると、別オリジンとして取り扱われ、JavaScriptからのリクエストをブロックするという機能をブラウザが標準搭載しています(**同一オリジンポリシー（SOP）の制限**)。

## なぜCORSが必要か

通常、ブラウザはセキュリティ上の理由から、異なるオリジン間での通信を制限しています（たとえば、example.com のページが api.example.net にアクセスすることは制限される）。
例えば以下のようなフロントとバックエンドを分けてAPIで接続するようなアプリを考えてみます。

- フロントエンド（Reactなど）が [http://localhost:5173](http://localhost:5173) で動作
- バックエンド（Railsなど）が [http://localhost:3000](http://localhost:3000) にある

この場合、ポートが違うのでオリジンが異なると見なされます。このとき、フロントエンドからAPIへアクセスすると、CORSエラーになります。

## そこでCORSが役に立つ

それらのような、異なるオリジン（ドメイン、ポート、プロトコルが異なる）間でのリソースの共有を可能にする仕組みをCORSといいます。
ブラウザのセキュリティ機能の一部であり、\*\*同一オリジンポリシー（SOP）\*\*の制限を一部緩和するために使われます。

### セキュリティ例:

ユーザーが [https://mybank.com](https://mybank.com) でログインしている時、別のWebサイト evil.com が JavaScriptを使って、勝手に mybank.com のAPIへ送金リクエストを投げるとします。

このような攻撃は current\_user やセッションIDを使った障害行為を実行できるため、CORSのようなブラウザ側の防衛系統が必須なのです。

## React と Rails を分離して開発する場合

React(フロントエンド): [http://localhost:5173](http://localhost:5173)
Rails(APIバックエンド): [http://localhost:3000](http://localhost:3000)

これらはポートが違うため、同じPCで動いているとしても別オリジンとして扱われます。
そのためCORSの設定をRails側で行う必要があります。

### 例: `config/initializers/cors.rb`

```ruby
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'http://localhost:5173'
    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head],
      credentials: true
  end
end
```

## 補足: CORSエラーのよくある原因と対応

### 1. フロントエンドのリクエストに `credentials: 'include'` が設定されていない

CORSでCookieやセッション情報をやり取りする場合、フロントエンド側でも以下のように `credentials: 'include'` を明示する必要があります。

```javascript
fetch('http://localhost:3000/api/example', {
  method: 'GET',
  credentials: 'include'
})
```

### 2. `credentials: true` を設定しているのに `origins '*'` にしている

Rails側で `credentials: true` を設定する場合、オリジンをワイルドカード（`'*'`）にするとエラーになります。必ず具体的なオリジン（例：`http://localhost:5173`）を指定しましょう。

### 3. `OPTIONS`メソッドへの対応が不足している

ブラウザは "事前リクエスト（preflight）" として `OPTIONS` リクエストを送る場合があります。このため、Rails側で `:options` を明示的に許可しておく必要があります。

```ruby
methods: [:get, :post, :put, :patch, :delete, :options, :head]
```

### 4. 本番環境でのドメイン指定忘れ

本番では `localhost` ではなく、本番のURL（例：`https://myapp.com`）を指定する必要があります。複数環境に対応するには、環境ごとに切り替えるように設定を工夫しましょう。
WindowsのコマンドプロンプトでAWS RDSに接続すると文字化け

Laravelでアプリを作っています。

Windows11のコマンドプロンプトで、AWS RDSに接続したらUTF-8で登録したはずのデータが文字化けしていました。
ブラウザ → Laravel → DB のどこかで SJISに変換されてしまったのかと思い、色々調べたのですが、全てUTF-8になっていて問題ありません。

試しに、Windows11のコマンドプロンプト に insert文をコピペで貼り付けたら、その瞬間に文字化けが発生しました。

原因はWindowsのコマンドプロンプトのデフォルト文字コードが Shift_JIS だからでした。

UTF-8のデータにアクセスするときは、コマンドプロンプトの文字コードをUTF-8に変えるか、WSL2のUbuntuで見るようにしたほうがいいですね。

結構ハマりました。
レンタルサーバーでNext.js（SSG）×PHP APIを運用するという、ちょっと珍しい構成の話…


# レンタルサーバーで Next.js（SSG）×PHP API を運用するという、ちょっと珍しい構成の話

こんにちは、今回は少し珍しい開発構成を紹介します。

> **Next.js（SSG）で作ったサイトを、レンタルサーバーにデプロイし、バックエンド API は `public` フォルダ内の PHP で構築する。**

そんな構成で開発・運用しています。

---

## 🧱 なぜこの構成？

- 既にレンタルサーバー（例：エックスサーバー、さくらなど）を契約していた
- Node.js や Vercel の環境が用意出来なかった
- コストを抑えたかった

つまり「**Next.js の魅力である SSG（Static Site Generation）を活かしつつ、バックエンドはレンタルサーバーの PHP で完結させる**」という狙いです。

---

## 🧪 開発環境の構成

開発時には、`concurrently`を使用して Next.js と PHP サーバーを**並行して起動**します。

### `package.json` のスクリプト例：

```json:package.json
{
  "scripts": {
    "dev": "concurrently \"npm run next\" \"npm run php\"",
    "next": "next dev",
    "php": "php -S localhost:8000 -t public"
  }
}
```

- `next dev` → `localhost:3000`
- `php -S` → `localhost:8000`

これで、フロントとバックエンドの同時起動が簡単にできます。

> ### `concurrently`とは？
>
> `concurrently` は、複数のコマンドを同時に実行できる便利なツールです。この例では、`next dev`（Next.js の開発サーバー）と `php -S`（PHP のビルトインサーバー）を並行して起動しています。
> `concurrently` を使うことで、複数のプロセスを 1 つのターミナルで管理でき、開発効率が向上します。インストールは以下のコマンドで行えます：
>
> ```bash
> npm install concurrently --save-dev
> ```
>
> これにより、複数のサーバーを簡単に起動・管理できる環境が整います。

## 🔗 Next.js から PHP API にアクセスする方法

### PHP（`public/api.php`）側：

```php:api.php
<?php
header('Access-Control-Allow-Origin: http://localhost:3000');
header('Content-Type: application/json');

echo json_encode(['message' => 'Hello from PHP']);
```

### Next.js（React 側）：

```typescript:typescript
const res = await fetch(`${process.env.NEXT_PUBLIC_API_BASE}/api.php`);
const data = await res.json();
```

開発時はポートが異なるため、CORS の許可設定が必要です。

## ⚙️ API のベースパスは環境変数で管理する

Next.js の環境変数を使用して、API のベースパスを管理します。

```typescript:next.config.js
/** @type {import('next').NextConfig} */

const isDev = process.env.NODE_ENV === "development";
const basePath = isDev ? "http://localhost:8000" : "";

const nextConfig = {
  output: "export",
  env: {
    NEXT_PUBLIC_API_BASE_PATH : basePath,
  },
};

export default nextConfig;

```

### コード例：

```typescript:typescript
const res = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_PATH}/api.php`);
```

これにより、開発と本番の切り替えが容易になります。

## 🌍 本番環境での構成

1. next build で静的ファイルを生成（SSG）
2. out フォルダをレンタルサーバーにアップロード
3. 同一ドメイン内で PHP API が動作

## 🤔 この構成のメリット・デメリット

### ✅ メリット

- レンタルサーバーで完結する
- PHP の資産や知識を活かせる
- Next.js の高速な静的出力を活かせる
- サーバーレスや Node 環境が不要

### ❌ デメリット

- 特殊な構成のため、情報が少ない
- 複数ポートでの開発がやや煩雑（npm スクリプトで対応可能）
- Next.js の API Routes は使えない

## ✍️ おわりに

この構成は少し特殊かもしれませんが、**レンタルサーバーの制約下でも Next.js と PHP を両立** させることができます。

PHP との連携が求められるプロジェクトや、Vercel などを使わずにコストを抑えたい場面では、十分に実用的なアプローチです。

> 実際にこの構成で運用していて、何か気づきがあればぜひコメントください！
Chatwork MCPサーバーを試す

## 動機
- MCPサーバーを触ってみたかった。
- Chatwork繋がりで、ChatworkにもMCPサーバーができているようなので実際に試してみる。

https://github.com/chatwork/chatwork-mcp-server

## やったこと
- github には、`ClaudeDesktop` を使う方法が記載されていますが、今回は `vscode` の `Cline` をつかってテストしてみました。

## 使用ツール
- vscode
- Cline（vscodeの拡張機能）
- deepseek（AI）

## 手順
※ インストール等の手順は省きます。

### 1. vscode を起動
### 2. 拡張機能から「Cline」をクリック
### 3. 「Remote Servers」タブをクリック

![スクリーンショット 2025-04-25 110700.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3850968/e2495d7f-d1cf-465a-a09c-62a523a20ce8.png)

### 4. 「Edit Configuration」をクリック

### 5. cline_mcp_settings.json が表示されるので以下をコピペ。

```json
{
  "mcpServers": {
    "chatwork": {
      "command": "npx",
      "args": ["@chatwork/mcp-server"],
      "env": {
        "CHATWORK_API_TOKEN": "YOUR_CHATWORK_API_TOKEN"
      }
    }
  }
}
```

### 6. 実際に指示してみる。

![スクリーンショット 2025-04-25 111341.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3850968/8d165c39-21e6-411f-99c3-1b5957337b81.png)

![スクリーンショット 2025-04-25 111052.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3850968/769715be-5e44-4280-b8e1-d1e6df66729f.png)
![スクリーンショット 2025-04-25 111137.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3850968/f5e32519-01e1-489b-ba80-583ba4b29b4a.png)


## まとめ
- AIは `deepseek-chat` を使用しました。（表記はこれであってるのかな？）
- 使用金額は、0.0067ドルでした。（円換算すると、0.9579 円？）
"invalid byte sequence in UTF-8 (ArgumentError)" が起きた場合に、具体的にどのような不正なバイト列が含まれているのか調べる

# 例

文字列がすべてひらがなで構成されているかを調べるメソッドを定義しました。

```rb
def all_hiragana?(str) = str.match?(/\A\p{Hiragana}+\z/)

all_hiragana?('もぐたろう')
#=> true

all_hiragana?('もぐタロー')
#=> false

# \x というバックスラッシュ記法で 16 進数の表現に変換しても、結果は同じ。
'もぐたろう'.b
#=> "\xE3\x82\x82\xE3\x81\x90\xE3\x81\x9F\xE3\x82\x8D\xE3\x81\x86"

all_hiragana?("\xE3\x82\x82\xE3\x81\x90\xE3\x81\x9F\xE3\x82\x8D\xE3\x81\x86")
#=> true
```

このメソッドにある文字列を渡すと `invalid byte sequence in UTF-8 (ArgumentError)` というエラーが発生します。

```rb
find_invalid_bytes("\xE3\x82\x82\x82\xAE\xE3\x81\x9F\x82\xEB\xE3\x81\x86")
# invalid byte sequence in UTF-8 (ArgumentError)
```

これは [UTF-8](https://ja.wikipedia.org/wiki/UTF-8) として不正なバイト列が含まれていることを示しています。しかし、具体的にどのバイト列が不正なのかはエラーメッセージからは分かりません。それを調べたいです。

## 方法

[String#scrub](https://docs.ruby-lang.org/ja/latest/method/String/i/scrub.html) という不正なバイト列を置き換えるためのメソッドを使用します。

```rb
def find_invalid_bytes(str)
  invalid_bytes = []

  str.scrub do |bytes|
    invalid_bytes << bytes

    # ブロックを渡す場合、
    # 不正なバイト列を置き換える文字列を戻り値で必ず指定する必要がある。
    '?'
  end

  invalid_bytes
end
```

先ほどエラーになった文字列をこの `find_invalid_bytes` に渡すと、不正なバイト列を返します。

```rb
find_invalid_bytes("\xE3\x82\x82\x82\xAE\xE3\x81\x9F\x82\xEB\xE3\x81\x86")
#=> ["\x82", "\xAE", "\x82", "\xEB"]
```

これは実は [Shift_JIS](https://ja.wikipedia.org/wiki/Shift_JIS) で「ぐ」と「ろ」を表すバイト列でした。

```rb
invalid_str = ["\x82", "\xAE", "\x82", "\xEB"].join
invalid_str.force_encoding(Encoding::Shift_JIS).encode(Encoding::UTF_8)
#=> "ぐろ"

'ぐ'.encode(Encoding::Shift_JIS)
#=> "\x{82AE}"
'ろ'.encode(Encoding::Shift_JIS)
#=> "\x{82EB}"
```

# バージョン情報

```shell-session
$ ruby -v
ruby 3.4.3 (2025-04-14 revision d0b7e5b6a0) +PRISM [arm64-darwin24]
```

# 参考

## Ruby リファレンス

- [String#b](https://docs.ruby-lang.org/ja/latest/method/String/i/b.html)
- [String#scrub](https://docs.ruby-lang.org/ja/latest/method/String/i/scrub.html)

## 過去に書いた Ruby と文字コードに関する記事

https://qiita.com/QUANON/items/09396ae9c3aab7129ac2

https://qiita.com/QUANON/items/bbc2bf0b0eb41d235ccd

https://qiita.com/QUANON/items/fdc97e2925f3855a9eb5
pythonでhsv2rgb

pythonにはcolorsysとかいう便利な機能が内蔵されているようだが、m5stackなmicro pythonにはなかった。hsv2rgbのpythonコードなんて探せばある(車輪の再発明)かもしれないが、探すのが面倒だしちゃんと動くかわからないので自作した。(自分で記事を書いたことがあるという記憶があればいつでも自分の記事を参照できて便利！)

```py
def hsv2rgb(h,s,v,Hrange=360,Srange=100,Vrange=100):
    if Hrange<=0 or Srange<=0 or Vrange<=0 or s<0 or v<0 or s>Srange or v>Vrange:
        print(f"INVALID INPUT. Your input:\n{h} {s} {v} {Hrange} {Srange} {Vrange}")
        return(0,0,0)
    if h<0:
        print(f"get H value:{h} to ",end="")
        while h<0: #-1が来たら359と解釈
            h+=Hrange
        print(f"interpreted:{h}")
    elif h>Hrange:
        print(f"get H value:{h} to ",end="")
        h%=Hrange #361という入力が来たら1と解釈
        print(f"interpreted:{h}")
    Hrange=Hrange/6 #～60°～120°～180°～240°～300°～360°の6段階でわけなきゃいけない
    MAX=v/Vrange*255 #明度はその色の最大値
    MIN=MAX-((s/Srange)*MAX) #彩度がMAXなら原色なのでRGBのいずれかが0になる
    if h<Hrange*1: #～60°(赤～黄)
        R=MAX
        G=(h           /Hrange)*(MAX-MIN)+MIN  #hが0なら原色赤(G=0)、hが60なら原色黄色(G=255)
        B=MIN
    elif h<Hrange*2: #60～120°（黄～緑）
        R=((Hrange*2-h)/Hrange)*(MAX-MIN)+MIN #hが60なら原色黄色(R=255)、hが120なら原色緑(R=0)。120から引いて60で割るとちょうど計算できる
        G=MAX
        B=MIN
    elif h<Hrange*3: #120～180°(緑～水色)
        R=MIN
        G=MAX
        B=((h-Hrange*2)/Hrange)*(MAX-MIN)+MIN #hが120なら緑(B=0)、hが180なら水色(B=255)。120を引く
    elif h<Hrange*4: #180～240°(水色～青)
        R=MIN
        G=((Hrange*4-h)/Hrange)*(MAX-MIN)+MIN #hが180なら水色(G=255)、hが240なら青(G=0)。240から引く
        B=MAX
    elif h<Hrange*5: #240～300°(青～赤紫)
        R=((h-Hrange*4)/Hrange)*(MAX-MIN)+MIN #hが240なら青(R=0)、hが300なら赤紫(R=255)
        G=MIN
        B=MAX
    else: #300～360°
        R=MAX
        G=MIN
        B=((Hrange*6-h)/Hrange)*(MAX-MIN)+MIN
    R=int(R)
    G=int(G)
    B=int(B)
    return (R,G,B)
```

無駄にエラーチェックてきなものを入れてるが不要な場合各自で削除してくれ！
Rails道場vol.1参加レポート

https://hey.connpass.com/event/349164/

参加してきました。

## 内容
`rails new`したプロジェクトに、要件をリクエストスペックにしたものが3段階のレベルで1ファイルずつある状態。それらのスペックが通るようにコーディングし、みんなでレビューする。

## タイムアタック
まっさらな状態からコーディングすると、意外とシンタックスを正確には覚えていなかったので、Railsガイドを参照しながら進めた。

https://railsguides.jp/

最新のRailsガイドを見ると、Strong Parametersの書き方が変わっていたので驚いた。
```rb
    def person_params
      params.expect(person: [:name, :age])
    end
```
以前はrequireとpermitの組み合わせだったような🤔

制限時間内に幾つのレベルまでクリアできるか...

本当に誰も喋らない。

私はレベル1を完了するあたりで制限時間ちょうどだった。

## レビュー

他の人のコードも含めて、印象に残った項目を挙げていきます。

- モデルバリデーションとDBの制約は両方とも設定しておきましょう
    - モデル側には不要、という説もあるけど、一般的な開発体制や後からDBを直接触る可能性を考慮すると、モデルとDBの両方に入れておくのがベター

https://zenn.dev/osiro/articles/4327f6978a67bb
- createやupdateの際にはロックすると安全
    - ある設定された容量に対して、溢れない必要がある要件の場合はロックしてからcreateやupdateすべし。同時リクエストで溢れてしまうのを防ぐ

https://railsguides.jp/active_record_querying.html#%E6%82%B2%E8%A6%B3%E7%9A%84%E3%83%AD%E3%83%83%E3%82%AF%EF%BC%88pessimistic%EF%BC%89
- emailの正規表現あったよね

https://techracho.bpsinc.jp/hachi8833/2024_04_05/140298

- ActionMailerから自動的にActiveJob化してメールを送ってくれる`deliver_later`の機能

https://railsguides.jp/action_mailer_basics.html#%E3%83%A1%E3%83%BC%E3%83%A9%E3%83%BC%E3%82%92%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%99

- Rigdepoleは便利な反面、大規模プロジェクトや歴史の長いシステムで既存テーブルにカラム追加したりインデックスを張り替えたりする場合にタイムアウトする可能性があり、修正内容をデプロイする前にALTER文を流しておく必要がある。Active Recordマイグレーションなら、差分ごとの適用になるのでその点が便利になる
- annotateをカスタマイズすると、必要な項目をみんなが書いてくれる話
- エラークラスなどは、1つのファイルにたくさん書きたくなるが、参照でコケることがある。本番では一度に読み込んでから実行されるのでどちらでも影響はないが、開発の手間を考えると面倒でも独立ファイルにしたほうが良い
    - Structの参照でコケて困ったことがあるので、1行だけでも面倒でも独立ファイルが良い

## おわりに
レビュー会はとても盛り上がっていて、日付を超える勢いだった。私は終電間近になったところで先に帰ったが、その後の展開は気になるところ。次回もぜひ行きたい！
Linux基本コマンド解説：初心者向けまとめ

## 1. cd（Change Directory）
用途：ディレクトリを移動するコマンドです。
例：
cd ..     1つ上のディレクトリへ
cd ~      ホームディレクトリへ
## 2. pwd（Print Working Directory）
用途：現在のディレクトリのフルパスを表示します。

例：
pwd
出力例: /home/user/Documents

## 3. ls（List）
用途：ディレクトリの内容を一覧表示します。

よく使うオプション：

-l：詳細情報がついて表示

-a：隠しファイルも表示

## 4. mkdir（Make Directory）
用途：新しいディレクトリを作成します。

例：
mkdir new_folder
mkdir -p parent/child
※-pオプションで親ディレクトリも同時に作れる

## 5. rmdir（Remove Directory）
用途：空のディレクトリを削除します。

例：

rmdir old_folder
※ 中身があるディレクトリは削除できません（その場合は rm -r を使用）。

## 6. cat（Concatenate）
用途：ファイルの中身を表示します。
例：cat file.txt

## 7. less
用途：長いテキストファイルを1ページずつスクロール表示できます。

例：

less large_file.txt
q で終了、/keyword で検索も可能。

## 8. tail
用途：ファイルの末尾(最終行)を表示します。

よく使うオプション：

-n：表示する行数（20なら最終行から20行）

-f：リアルタイム監視（ログなどに便利）

例：

tail -n 20 log.txt
tail -f /var/log/syslog
## 9. touch
用途：空のファイルを作成します。
例：

touch newfile.txt
## 10. rm（Remove）
用途：ファイルやディレクトリを削除します。

よく使うオプション：

-r：ディレクトリを再帰的に削除

-f：確認なしで強制削除

例：

rm file.txt
rm -rf old_folder


## 11. mv（Move）
用途：ファイルやディレクトリを移動または名前変更します。

例：

mv oldname.txt newname.txt     # 名前変更
mv file.txt /tmp/  # 移動

パターン	                   
mv A B（Bがファイル名）	　         A → B（名前変更）
mv A /path/（Bがディレクトリ)        A をそのディレクトリに移動
mv A /path/B（Bがファイル名付きのパス）A を移動して名前も変更

## 12. cp（Copy）
用途：ファイルやディレクトリをコピーします。

よく使うオプション：

-r：ディレクトリを再帰的にコピー

例：

cp file.txt backup.txt（backup.txtが存在しない場合、自動で作られます）
cp -r dir1/ dir2/
## 13. ln（Link）
用途：ファイルのリンクを作成します（ハードリンクまたはシンボリックリンク）。

ln original.txt link.txt            # ハードリンク

```
イメージ
[original.txt] ─┬─> 実体
[link.txt] ─────┘
```
ln -s original.txt symlink.txt     # シンボリックリンク

```
イメージ
[symlink.txt] ──> [original.txt] ──> 実体
```
## 14. find
用途：指定条件でファイルやディレクトリを検索します。

例：

find . -name "*.txt"

:::note 
意味
今いるディレクトリ（.）以下から
「.txt で終わるファイル名」のファイルを探す
:::

find /home/user -type f -size +10M

:::note 
意味
/home/user 以下にある
「サイズが10MBより大きい」
「通常ファイル（ディレクトリじゃない）」を探す
:::

-type f	通常のファイルだけ対象（ディレクトリ除外）
-size +10M	10MBより大きい（+は「より大きい」）
## 15. chmod（Change Mode）
用途：ファイルやディレクトリのパーミッションを変更します。

例：

chmod 755 script.sh
chmod u+x script.sh

## 16. chown（Change Owner）
用途：ファイルやディレクトリの所有者を変更します。

例：

chown user:group file.txt
※ sudo 権限が必要なことが多いです。

## 17. ps（Process Status）
用途：現在実行中のプロセスを表示します。

例：


ps aux　　BSD系の書き方（MacやUbuntuでよく使う）
ps -ef　　UNIX System V系の書き方

## 18. kill
用途：プロセスにシグナルを送って終了させます。

例：


kill 1234        # プロセスIDで終了
kill -9 1234     # 強制終了（SIGKILL）
※1234はプロセスID
psと組み合わせて使うことが多いです。
Gitlabにて、Let’sEncrypt SSL証明書を利用した場合の更新方法

# 実現したいこと

GitLab のSSL証明書に「Let’sEncrypt」を利用している場合の証明書更新方法を記載します。

# 前提

GitLabは稼働している状態とします。
「Let’sEncrypt」証明書は最長3カ月となります。
これを運用で更新し続ける必要があります。

# 更新方法
gitlab-ctl renew-le-certs

ただし、注意が必要です。
Gitlabサービスを停止する必要はありません。

（１）
大抵F/Wを設定されていると思います。そちらを一時的に外す必要があります。
理由は、80ポートを利用して、書き込んでもらうためです。

＞http(80)番ポートでWebサイトへ自動で生成される
＞/.well-known/acme-challenge/xxxxxx

問題がなければ、
「Gitlab」の管理ディレクトリ内「例：/xxx/gitlab/config/ssl」へ
更新された証明書が作成されております。

（２）
生成された証明書をLBなどに適切に配置します。

# 補足

参考：https://www.mubit.co.jp/pb-blog/?p=30591
組込みLinuxが突然再起動した場合確認すること

質問：「組込みLinuxが突然再起動した．
このとき確認すべきものを優先度が高い順に教えてください．」
以下はChatGPTの回答．

---

組込みLinuxシステムが**突然再起動した**場合、原因の特定は重要です。以下は、**優先度順**にチェックすべき項目です：

---

## ✅【優先度：最上】1. カーネルログ (`dmesg`, `journalctl -k`)
再起動直前に**カーネルが出力したメッセージ**は最重要。

```bash
dmesg | tail -50
journalctl -k -b -1  # 前回起動時のカーネルログ
```

チェックする内容：
- `kernel panic`, `BUG`, `Oops` などの致命的エラー
- `watchdog`, `soft lockup`, `hard lockup` のようなハング検出
- `Out of memory: Killed process ...` → OOMが原因の再起動
- ファイルシステム関連のエラー（例：`EXT4-fs error`）

---

## ✅【優先度：高】2. systemd ログ（前回起動時）
`systemd` のログで**シャットダウン/リブートの意図的な痕跡**がないか確認します：

```bash
journalctl -b -1
```

チェックする内容：
- `systemd[1]: Rebooting.`
- `session-*.scope: A process has been killed by the OOM killer.`（＝OOMで落ちた）
- 再起動直前にログがぷつっと切れてる → 電源断やカーネルクラッシュの可能性

---

## ✅【優先度：高】3. 電源関連の確認（ログ＋物理）
ログに何も出ていない場合は、**電源断（瞬断含む）**の可能性大：

- UPSを使用していない場合、外部環境要因（ケーブル抜け・電源ノイズ）
- ハードウェアウォッチドッグによる強制リブート
- 電圧低下ログ：一部ボード（例：Raspberry Pi）は `/var/log/syslog` に `under-voltage` 警告が出る

---

## ✅【優先度：中】4. `/var/log/` 下のログファイル
一般的なログファイル群からヒントを得る：

```bash
less /var/log/syslog
less /var/log/messages
less /var/log/kern.log
```

検索ワード例：
- `panic`, `fatal`, `segfault`, `watchdog`, `reboot`, `oom`
- 再起動直前にエラーが集中してないか確認

---

## ✅【優先度：中】5. ハードウェア監視（watchdog, センサー）
以下を使って、**ハードウェア監視機構が働いたか**を確認：

```bash
lsmod | grep watchdog
dmesg | grep watchdog
journalctl -b -1 | grep watchdog
```

ボードによっては `/dev/watchdog` 経由で強制リブートが走る設定もある。

---

## ✅【優先度：低〜中】6. ソフトウェア起因（自動更新、バグ）
- cronやタイマーによる自動再起動
- アプリケーションのバグ（無限ループや無制限メモリ確保）→ OOM
- 組込み独自のシェルスクリプト等による`reboot`コマンド

---

## 🚨番外：ログが全く残っていない場合
→ **電源断またはハードウェアリセット**の可能性が高いです。

チェックする：
- `last -x reboot` → reboot時刻がログに記録されているか？
- `journalctl --list-boots` でログが途中で途切れていないか？

---

必要なら、チェック用のシェルスクリプトも一緒に組みますよ。再起動の頻度や条件もわかれば、調査の方針をもっと絞れます。どうしますか？
メモリ枯渇の犯人は？

経緯
メモリ枯渇を疑うとき見るべきものについて調査中，`journalctl | grep -i "kill" | less`でOOM killerが発生していないか確認するところまでやったが，killされたプロセスがメモリ枯渇の犯人とは限らないのではないかと思ったため下記の質問をした．
質問：「oom_score_adjは多くの場合0なので，killされたプロセスのoom_score_adjが0であれば，そのプロセスのメモリ使用量が大きかったと判断して良い．
逆に，oom_score_adjが2など大きい場合には別に犯人がいる可能性があると考える．
この認識で良いですか？」
以下はChatGPTの回答．

---

はい、かなり正確な理解です！  
以下に、あなたの認識を補足しながら整理していきます。

---

## ✅ あなたの認識：ほぼ正しい！

> 🔹 `oom_score_adj == 0` のプロセスが kill された場合 →  
> ➤ **そのプロセスが相対的にメモリを多く使っていたと考えて良い。**

> 🔹 `oom_score_adj` が大きい（例：+500や+1000）  
> ➤ **そのプロセスは意図的に「殺されやすい」よう調整されている。**  
> ➤ **実際に犯人が別にいる（けどそっちは優先度が低くて見逃された）可能性がある。**

---

## 💡 詳細補足

### oom_score
- 0〜1000の値で、**実行中プロセスの kill 優先度**を示す。
- メモリ消費量（RSSなど）に基づいて自動計算されます。
- このスコアが高いほど kill されやすい。

### oom_score_adj
- -1000〜+1000 の手動調整値。
- `/proc/[pid]/oom_score_adj` に書き込んで調整できます。
- 実際のスコア計算は以下のように影響を受けます：

```
effective_score = oom_score + oom_score_adj（※簡略化して言えば）
```

### 例：

| プロセス | メモリ使用 | oom_score_adj | 備考 |
|----------|------------|----------------|------|
| A        | 2.5 GB     | 0              | 💀 kill 対象（重い＋調整なし）|
| B        | 1.0 GB     | +800           | 😱 優先的に kill される（軽いが killしやすい）|
| C        | 3.0 GB     | -1000          | 🔒 保護対象（いくら重くても kill されない）|

---

## ✅ まとめ

| 観点 | 内容 |
|------|------|
| `oom_score_adj=0` で kill | おそらくそれが「重い犯人」 |
| `oom_score_adj>0` で kill | 優先的に kill されただけ。**犯人は別にいる可能性あり** |
| `oom_score_adj<0`         | 保護対象。ほぼ kill されない |
| 実際の犯人特定には？      | `oom_score_adj` と メモリ使用量（`VmRSS`など）を両方見ると◎ |

---

必要なら、`oom_score_adj` を使って任意のプロセスに「優先度」をつける方法も紹介できます！興味あります？
外国人が基本情報技術者試験を受けた感想

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043411/6e9fa455-1ba4-48b8-a009-32b35a257c7b.png)
<font color="gray">一発合格。嬉しいね</font>

内容自体はIT関連でそこそこ勉強している人なら大体分かる話であるため難しくない。
日本語がFirst Languageではない人にとってはやはり日本語文章を読むスピードが一番の課題になってくる。
日本語を勉強して1~2年の人に科目Bの問題を時間内で読み切るのはほぼ不可能だと思う。
学生時代の研究で日本語論文や研究資料をよく読んでいた筆者でも時間がギリギリだった。

特に科目Bの後半の問題はテキストの量が多い上に、テキストに登場する加工の人物や会社の詳細を覚えながら読まないと時間内に解けない。
日本語の論文１ページを一回読んで、読み直さなくても理解できるレベルが望ましい。

基本情報はIRTと言う採点方式を用いている。
https://www.ipa.go.jp/shiken/2024/eid2eo0000004j83-att/06a_06.pdf


<details>
<summary>
<font color="gray">
あくまで噂話であるため、ご興味のある方だけ。こんな噂もあるんだ～くらいの感覚でお読みください
</font>
</summary>

> IRT
> 合計得点の問題点を解決するために，項目の難易度などの項目特性と，各受検者の能力を分離して考え，共通尺度上でのテストの構築と実施を支えるテスト理論

採点のアルゴリズムが明かされていないため、憶測でしかないが、60問中40問を当てた人より、30問を当てた人の点数の方が高くなることもあり得る...?

実際筆者も採点結果が予想の点数より高く、問題数から考えて普通の採点方式では考えにくい点数が出た。

今のところネットで噂されているのは以下
- 難易度の低い問題を多数解くより、難易度が高く OR 正解率の低い問題を解く方が点数が高い
- 今までの受験データで平均か偏差値を出して、受験者の正解率と照らし合わせて点数を決めてるかも
- 何らかの条件により追加の加算点がある気がする
- 各分野の平均正解率が点数に反映されている可能性
　→(例：
Aさん：DB系問題は全部正解+ネットワーク系問題全問外れで合計10問正解
Bさん：DB系問題半分正解+ネットワーク系問題半分正解で合計10問正解
...の場合、同じく10問正解でもAよりBの最終点数が高くなる可能性)

同じくIRT採点方式であるITパスポートについての記事
https://itpassport.gihyo.jp/archives/1435 
https://www.ap-siken.com/bbs/5195.html 

</details>

-------

市販のテキスト本では教えてくれない問題がかなり多く出題される。
そもそも基本情報は公式テキスト・教材がない＋問題も公式的に公開されるのは全80問<font color="Lightgray">(A+B)</font>の内26問だけ。
その上、受験者は問題の内容を覚えていても他の人に教えたりネットに書き込むことが禁止されている。
故に市販のテキストは公式のざっくりしたシラバスと毎年少ししか公開されない問題をベースに作成されるので、テキストにはない問題が多い。

見覚えのある問題は40%くらいで、残り60%はおそらく未公開問題であろうと思われる問題だった。

------

使った教材
・かやのき先生の基本情報技術者教室(改訂前の版、中古)
・いちばんやさしい 基本情報技術者(2024年最新版)

個人的にはいちばんやさしい～の方が分かりやすかった。

正直言うと、主な内容にそこまで違いはないため最新版に拘らなくてもいい。
紙の本じゃないと集中できないタイプではないなら、Kindleなどの電子書籍で購入することをおすすめする。
本を持ち歩かなくても出勤中や休憩時間にパソコンかスマホで勉強できるので時間が確報できる。

また、基本情報ドットコムのスマホUIもすごく見やすいので、電車の中でこまめに解いてみた方がいい。しかも無料。
https://www.fe-siken.com/ 

------

科目Bについて
アルゴリズム系のコーディングテストに慣れている人なら解きやすいと思う。
paizaやatCoderなどで遊んでる人ならわざわざ勉強する必要はあまりない。
最大公約数、素数の求め方を知っておいた方がいい。
後半にすごく長い経営/マネジメント系の問題が出るので注意。
【Reactアプリ100本ノック】03 ToDo

## はじめに
ゆかっしゅです。
2021年に事務職からデザイナー/コーダーにジョブチェンジをし、現在はフロントエンドエンジニアにスキルアップするべく、モダンフロントエンドを学習しています。

ReactやTypeScriptの基礎学習は終了したのに、なかなか0から自分だけでアプリを作れないので手を動かすべく「Reactアプリ100本ノック」 に挑戦してみようと思います。

https://qiita.com/Sicut_study/items/5dec3c42c8f3c90f0487

## Reactアプリ100本ノックルール
- 主要なライブラリやフレームワークはReactである必要がありますが、その他のツールやライブラリ（例: Redux, Next.js, Styled Componentsなど）を組み合わせて使用することは自由
- TypeScriptを利用する
- なるべくChatGPTなどのAIツールに頼らない（自分独自ルール）

## 03. TODO
![スクリーンショット 2025-04-25 102044.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4068307/fc36dde4-c032-4df3-a4a6-dc488db40941.png)

## 問題
TODOリストアプリを作成する

## 目的
TODOリストは複数のタスクを管理する必要があるため、状態管理の初歩を学ぶのに適しています。Reactを使用する場合、useStateやuseReducerなどのHooksを使って状態管理の方法を学ぶことができます。

## 達成条件
1\.入力フィールド: ユーザーがタスクを入力するためのテキストフィールドが存在する。タスク名が1文字以上でない場合はバリデーションする
2\.追加ボタン: 入力されたタスクをTODOリストに追加するためのボタン。
3\.タスクリスト表示: 追加されたタスクがリストとして表示される。
4\.削除ボタン: 各タスクの隣には削除ボタンがあり、それをクリックすることで該当のタスクをリストから削除する

## 実際に解いてみた
## 利用技術
React(19.0.0)
TypeScript(5.0)
Next.js(15.3.1)
Tailwindcss(4.0)
Vercel
解答時間:1時間

見た目25分、タスク管理の部分35分という配分でした。
Todoアプリは以前にも数回作っていたので、余裕！かと思いきや結構忘れていました..

### リンク
https://react-app-100.vercel.app/

### おわりに
次のアプリくらいから作ったことのないアプリなので苦戦しそうだと思いました。
あと、swich2の抽選外れました...。
VSCodeのExtensionをバージョンアップした話 with Clineに機能追加を依頼したら1分で実装が終わった話

# VSCodeのExtensionをバージョンアップした話

## 更新したExtensionについて

https://marketplace.visualstudio.com/items/?itemName=gengen0719.java-testingpair-opener

Javaクラスを開いた状態で Ctrl + 9 を押すとテスティングペアのJavaクラスを開く（なければ作る）という超単純なExtensionです。

作った時の記事はこちら。

https://qiita.com/gengen0719/items/c3ef391d04fe42598828

ソースコードはこちら

https://github.com/gengen0719/java-testingpair-opener

## 機能追加した内容
- 複数のテスティングペアをサポートする機能を追加しました
私が保守しているプロダクトがそうなのですが（だから作った）Hoge.javaに対してHogeTest.javaとHogeIntTest.javaが存在するようなプロジェクトでも利用できるようになりました。
Ctrl + 9 もしくは Cmd + 9 を押すと、Hoge.java、HogeTest.java、HogeIntTest.java（以降繰り返し）の順に切り替わるようになっています。

- テスティングペアの関係性をカスタマイズできる設定オプションを追加しました
テスティングペアのSuffixやフォルダ構成を任意に設定できる機能を追加しました。
こんな感じでsettings.jsonに設定できます。
ペアを増やしたり減らしたりすることもできます。
```
"java-testingpair-opener.testingPairs": [
    {
        "name": "Production",
        "pattern": "src/main/java",
        "suffix": "",
        "position": 0
    },
    {
        "name": "Unit Test",
        "pattern": "src/test/java",
        "suffix": "Test",
        "position": 1
    },
    {
        "name": "Integration Test",
        "pattern": "src/int-test/java",
        "suffix": "IntTest",
        "position": 2
    }
]
```
- 自動削除機能を追加しました
テスティングペアを切り替える際に、デフォルトの内容から変更されていないテストファイルは自動的に削除されるようになりました。（プロダクションコードのファイルは消えません）

## 機能追加時に注意が必要だったポイント
### 設定の取り扱い
今回 `package.json` にデフォルトの設定を持たせてリリースしましたが、いくつか疑問が湧いたためどういう挙動なのか調べてみました。

- 設定値の挙動
    - `package.json` の `configuration` `properties` 以下に設定した名前で設定値が判別される（今回だと [java-testingpair-opener.testingPairs](https://github.com/gengen0719/java-testingpair-opener/blob/main/package.json#L31) ）
    - settings.json に設定が存在しない場合は、package.json に記載されたデフォルトの設定値が使用される
    - ユーザーが設定を変更しない限り、`settings.json` にはデフォルトの設定値は書き込まれない
    - 一度settings.jsonに書き込まれた設定は、それ以降package.jsonのデフォルト設定を読み込むことはなく、アップデートされない
    - 設定値を強制的に更新したい場合は `activate` 関数内に更新処理を書き込む

既存ユーザーの動作を変えたくない場合は注意が必要かなと思います。

### Market Placeに表示されるファイルの更新を忘れない
色々と忘れて、何回かアップしなおしたりしたので備忘として。

- `package.json` のversionの更新
MarketPlaceにVersionとして表示される値になります（大事）
- CHANGELOG.mdの更新
MarketPlaceのVersion Historyはこの内容をもとに作成されるようです。（忘れがち）

# Clineに機能追加を依頼したら実装は1分で終わった話

## 今回の機能追加で使ったポイント
今回追加した機能のメインである `複数のテスティングペアのサポート` についてはClineに以下の依頼をして実装してもらいました。

```
任意の数のテスティングペアを設定できるように機能追加をしてください
- Hoge.java の単体テストのTestingPairとしてHogeTest.java、IntegrationテストのTestingPairとしてHogeIntTest.javaとなるような設定ができる
- Ctrl + 9 を押すたびに、プロダクションコード、単体テスト、Integrationテスト（以降繰り返し）のような切り替えとファイル生成が行われる
- TestingPairは2つだけではなく任意の数を追加できる。設定画面で設定することができる。
```

## 良かった点
以下が開発体験として良かったです。

- リポジトリに対するコンテキストはREADME.mdを読み込んで補完してくれた
- 1分程度で実装が終わった
- 一発で意図通りの動作をする実装が出てきた
- コードの修正と合わせてREADME.mdも修正してくれた（超うれしい）

## 改善ポイント

注意が必要だったポイントに記載した以下は `.clinerules` に明記するなどしてコンテキストを与えた方が良かったなと思いました。
- package.jsonのversion更新作業の明記
- CHANGELOG.mdの更新作業の明記

また実装の楽さに対してテストが面倒に感じたので

- 自動テストの整備
- 実装後テスト実行して動作確認をするインストラクション

をやっておくとよりスムーズに進められそうだなと思いました。

## 大きなリポジトリで実装してもらった際との対比
仕事で保守をしている大きなリポジトリでも、主にテストコードを書く作業をやってみてもらっているのですが、そちらでは大量のインストラクションが必要で、それでもなかなか意図したコードを書いてくれず、その体験との対比が印象的でした。
よりいっそう小さくシンプルなものを組み合わせて作っていく重要性を感じています。

おわり。
Java解説 20250425

### インスタンス化にはnewを使用する
```
データ型 変数名 = new コントラクタ名();
```
### メンバ
(a)クラス内に定義される要素。
(b)メンバ変数は、クラス内のどこからでもアクセス可能だが、ローカル変数は、宣言したブロック内でしかアクセスできない。
### コンストラクタ
インスタンスを生成する時に実行される処理。
```java
// ConstructorSampleクラス
class ConstructorSample {    
    String str = "サンプル";
 
    //　コンストラクタ
    public ConstructorSample() {        
        System.out.println(str);
    }
}

// Main.java
public class Main {
 
    public static void main(String[] args) {
        //インスタンスの生成
        //「cs」というインスタンス名で「ConstructorSample」というクラスの「ConstructorSample()」というコンストラクタ名の処理を実行。
        ConstructorSample cs = new ConstructorSample();
    }

}
```

<br>

[オラクル認定資格教科書 Javaプログラマ Bronze SE(試験番号1Z0-818)](https://www.amazon.co.jp/%E3%82%AA%E3%83%A9%E3%82%AF%E3%83%AB%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E6%95%99%E7%A7%91%E6%9B%B8-Java%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E-Bronze-SE-%E8%A9%A6%E9%A8%93%E7%95%AA%E5%8F%B71Z0-818/dp/479816206X/ref=pd_lpo_d_sccl_1/357-5313211-9846263?pd_rd_w=VQCzo&content-id=amzn1.sym.855d8f70-df76-4181-80b0-56e48ae3bb9b&pf_rd_p=855d8f70-df76-4181-80b0-56e48ae3bb9b&pf_rd_r=JRR4W9RKV32K4AXF1WRZ&pd_rd_wg=l7VoD&pd_rd_r=1d465f85-0562-4b51-b523-77f8486c1508&pd_rd_i=479816206X&psc=1 "オラクル認定資格教科書 Javaプログラマ Bronze SE(試験番号1Z0-818)")
KibanaのMLアイテム（Job, Trained Model）のスペース間共有

## ElasticsearchのMLとKibanaのSaved Object

Elasticsearchでは機械学習（ML）関連の機能をいくつか提供しています。

 * Anomaly Detection（異常検知）
 * Data Frame Analytics（データフレーム分析）
 * Trained Models (自然言語モデルのアップロードなど。ELSERやE5なども含む。)

基本的にこれらのMLの機能はElasticsearchが（Kibanaとは独立して）提供しています。

ただし、例えばKibana上からAnomaly Detectionジョブを作成すると、そのジョブは作成した時のKibana Spaceに紐づいた状態となります。複数のSpaceがある環境の場合、Spaceを切り替えると元のSpaceで作成したジョブは見えなくなるはずです。

これはKibanaがJobを作成する場合、直接ElasticsearchのML関連のデータを参照するのではなく、KibanaのSaved Objectを介して参照しているためです。このデータ構造については以下の記事でも紹介しました。

https://qiita.com/daixque/items/fa0bded5f8a08297410e#kibana%E3%81%AEsaved-object

## Saved Objectの検索

KibanaのSaved Objectは`.kibana`というシステムインデックス（エイリアス）に保存されています。私の環境では`.kibana_8.11.1_001`が実インデックスとして使われていました。これらのインデックスは、KibanaのSaved Objectを管理するためのもので、通常は直接操作することはありませんが、実際のデータ構造を理解するために、直接検索することは可能です。（現時点では。今後変わる可能性はあります。8系で試していますが、9.0でもまだアクセスできることは確認しました。）

`.kibana`インデックスではtypeフィールドにSaved Objectの種類を示す値が格納されています。これを使って、特定のSaved Objectを検索することができます。

ML関連のSaved Objectのtypeは以下のようになっています。

 * Anomaly Detection, Data Frame Analytics : `ml-job`
 * Trained Models : `ml-trained-model`

`ml-trained-model`のSaved Objectを検索してみましょう。

```
GET .kibana/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "type": {
              "value": "ml-trained-model"
            }
          }
        }
      ]
    }
  }
}
```

以下のような内容が取得できます。

```json
{
    "_index": ".kibana_8.11.1_001",
    "_id": "ml-trained-model:tohoku-nlp__bert-base-japanese-v3",
    "_score": 0,
    "_source": {
        "ml-trained-model": {
            "model_id": "tohoku-nlp__bert-base-japanese-v3",
            "job": null
        },
        "type": "ml-trained-model",
        "references": [],
        "managed": false,
        "namespaces": [
            "default"
        ],
        "coreMigrationVersion": "8.8.0",
        "typeMigrationVersion": "7.10.0",
        "updated_at": "2024-02-27T06:50:32.951Z",
        "created_at": "2024-02-27T06:50:32.951Z"
    }
}
```


## Spaceの関連付けの更新

KibanaのSaved Objectは、Spaceに関連付けられた状態で保存されます。これを更新するには、[Update saved objects in spaces API](https://www.elastic.co/docs/api/doc/kibana/operation/operation-post-spaces-update-objects-spaces) を使用します。このAPIを使用すると、特定のSaved Objectを指定したSpaceに追加（あるいは削除）することができます。

よくある操作として、アップロードしたモデルを複数のスペースで使いたいというものがあります。KibanaのTrained Modelsの画面上からはできないので、Dev Toolsを利用して以下のようにKibana APIを利用して変更します。

```
POST kbn:/api/spaces/_update_objects_spaces
{
  "objects": [
    {
      "id": ".elser_model_2_linux-x86_64",
      "type": "ml-trained-model"
    }
  ],
  "spacesToAdd": [
    "default",
    "test"
  ],
  "spacesToRemove": []
}
```

`id`にはドキュメントのIDではなく、モデルのid（ml-jobの場合は`job_id`）を直接指定します。

このようにKibanaのAPIを利用することで、Saved ObjectのSpaceの関連付けを変更することができます。これにより、特定のSpaceに関連付けられたSaved Objectを他のSpaceでも利用できるようになります。

## まとめ

ElasticsearchのML関連の機能は、KibanaのSaved Objectを介してSpaceに関連付けられています。これを変更するためには、Kibanaの[Update saved objects in spaces API](https://www.elastic.co/docs/api/doc/kibana/operation/operation-post-spaces-update-objects-spaces) を利用します。

特定のスペースで作成したML関連のオブジェクトを他のスペースで利用したい場合には、この記事を参考にしてください。
広告タグを球面に貼って動かしてみた

![Dev Log-720-short1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4070870/2a9c54d4-8460-4dfc-b861-c82b33f4abaf.gif)

GIFのようなページを作ってみました。
詳細は下に書きました。

[広告タグを球面に貼って動かしてみた](https://dev-tools-log.pages.dev/blogs/3d-ad)
フェデレーションとOAuth2.0　認証の流れ


AndroidでgoogleSign-Inを実装する時にまとめたもの。
OAuth2.0は多くのサービスで登場し当然モバイル開発でも利用するので自分用にまとめました。


> Credential Manager は、ユーザー名とパスワード、パスキー、フェデレーション サインイン ソリューション (Google でのサインインなど) などの複数のサインイン方法を単一の API でサポートする Jetpack API であり、開発者の統合を簡素化します(翻訳)
引用元：
https://developer.android.com/identity/sign-in/credential-manager?hl=en

フェデレーション認証とは、Googleアカウントなどの外部のIdP(Identity Provider)を利用して、別のサービス(RP)にログインする仕組み。Googleサインインはその一例。
:::
この場合の利用サービスをRP呼ぶ
本人確認を行なった後ユーザーに対してサービス提供を行う主体
:::

:::
認証情報の管理や認証を行う主体のことをIdP(アイデンティプロパイダー)という。
例。Google,MicroSoft等
CredentialManagerはGoogleIdPのフェデレーションに対応している
:::

CredentialManagerでは
フェデレーションのセキュリティ強化のために
フェデレーション+パスキー、フェデレーション+パスワードが用意されている


パスキーは顔スキャン、指紋、PINでログインできる
Googleから推奨されている方法。

## Oauth2.0
OAuth2.0
IdPと認可サーバーのやり取りの1と3をプロトコルにしたものがOAuth2.0

1.ユーザーがIdP(Googleなど)で認証し、RPにログインする
2.RPはIdPの認可サーバーにアクセストークンを要求する
3.「ユーザー情報をRPに渡していいですか？」とIdPの認可サーバーがユーザーに確認する
4.OKならIdPの認可サーバーがアクセストークンをRPに発行
5.RPは発行されたアクセストークンをリソースサーバーに渡す
6.リソースサーバーはその検証を行い、権限があるユーザーデータをRPに渡す
個人的備忘録：Uvicornの起動ログを読み解きながら記事としてまとめてみた

## はじめに

本記事では、Python製のASGIサーバー「Uvicorn（ユビコーン）」に関して、基本的な役割やログ出力の読み方を整理します。  

:::note info
**FastAPIやStarletteといったASGIアプリケーションと組み合わせて使われることが多く、現代的なPython Webアプリケーションの土台として広く利用されています。**
:::

「ログに何かエラーが出ているのでは？」と思ったときに冷静に確認できるよう、実際の起動ログをもとに解説していきます。

## Uvicornとは？

**Uvicorn**は、ASGI（Asynchronous Server Gateway Interface）仕様に基づいて動作する軽量・高速なWebサーバーです。  

https://www.uvicorn.org/

WSGI（FlaskやDjangoの従来の仕組み）と比較して**非同期処理に強く、リアルタイムなアプリケーション（チャット、WebSocketなど）に適しています**。

### 主な特徴

- 非同期対応（async/await を活かした処理が可能）
- 軽量かつ高速なサーバー
- HTTP/1.1, WebSocket サポート
- FastAPI や Starlette と相性が良い

Uvicorn は、`uvicorn main:app --host 0.0.0.0 --port 8000` のようなコマンドで起動し、Pythonコード内の ASGI アプリケーションを Webサーバーとして立ち上げます。

## 起動ログの読み解き

以下は、ある FastAPI アプリケーションを Uvicorn で起動したときのログです。

```
2025-04-24T22:50:36.648+09:00
INFO: Started server process [1]
2025-04-24T22:50:36.648+09:00
INFO: Waiting for application startup.
2025-04-24T22:50:36.649+09:00
INFO: Application startup complete.
2025-04-24T22:50:36.652+09:00
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
```

### 各行の意味

- `Started server process [1]`  
  → PID（プロセスID）1番でUvicornサーバープロセスが起動したことを示します。

- `Waiting for application startup.`  
  → FastAPIなどのアプリケーションの初期化を待っている状態です。

- `Application startup complete.`  
  → アプリケーションが無事に起動したことを意味します。

- `Uvicorn running on http://0.0.0.0:8000`  
  → サーバーがポート8000番でリッスンしており、外部からのアクセスを受け付ける準備ができた状態です。

### 補足：0.0.0.0 とは？
`0.0.0.0` は「全てのネットワークインターフェースからの接続を許可する」ことを意味します。  
たとえば、FargateやDockerなどでホストされる場合、この設定がないと ALB や他の外部リクエストを受けられないことがあります。

## 結論：このログにエラーはない

冒頭のログはすべて `INFO` レベルであり、**エラーや警告は一切含まれていません**。  
そのため、このログが表示されている限りは、アプリケーションとUvicornサーバーは正常に起動していると判断できます。

## まとめ

**個人の備忘録程度の走り書きとなっておりますが、温かい目で見守っていただければ幸いです...！**

以下、簡単なメモとなります。

- Uvicorn は FastAPI などの ASGI アプリケーションを起動する軽量サーバー。
- ログに含まれる `INFO` メッセージは通常動作を示しており、エラーではない。
- `http://0.0.0.0:8000` の表記は「すべてのインターフェースで待ち受け中」であり、クラウド環境でも重要な設定。
AtCoderは競技じゃない、実践教材だ。

Pythonを勉強していて「文法は一通りわかったけど、次に何をすればいいのか分からない」と感じたことはありませんか？

そんなときにおすすめしたいのが、**AtCoder**という競技プログラミングサイトです。

「え、競技プログラミング？ハードル高そう…」と思うかもしれませんが、実はAtCoderは、Pythonの練習教材としても非常に優れています。

理由はシンプルです：
- 小さな問題単位で練習できる
- 自動で答え合わせしてくれる
- 実行時間やメモリ制限があるので、効率的な書き方を意識できる
- 入力・出力、条件分岐、ループ、配列など、基本構文の実践的な使い方が自然と身につく

何より、「動くコードを書く → 実行する → 結果が返る → うまくいった！」というフィードバックループが楽しく、自然と継続できます。

# AtCoderとは
AtCoder（アットコーダー)は、プログラミング問題を解くためのオンラインジャッジサイトです。日本発のサービスで、競技プログラミングの大会も定期的に開催されています。

特徴は以下の通りです：

- 毎週末に定期コンテスト（ABCなど）が開催されている  
- 過去問が豊富で、いつでも挑戦できる  
- Pythonを含む複数のプログラミング言語に対応  
- 問題を提出すると、その場で自動採点される（AC/WAなど）

AtCoderは“競技プログラミング”の場として知られていますが、実は**プログラミング初心者にとっても非常に良い練習環境**です。

# どのようにAtCoderを教材として使うか
### ステップ①：APG4b Pythonで一通りの文法を実践的に学ぶ

AtCoderには「APG4b（Aizu Programming Guide for Beginners）」という、Pythonを使って基本文法を実践的に学べる教材が用意されています。

👉 [APG4b Python版](https://atcoder.jp/contests/APG4bpython)

この教材の特徴：

- 実際にコードを入力して、実行・提出ができる
- 1問ごとにテーマが分かれていて、文法の理解を深めやすい
- `print()`、リスト、条件分岐、ループなど、AtCoderでよく使う構文に特化している

AtCoderの問題に取り組む前に、このAPG4bで手を動かしておくと、**「読むだけの学習」から「書ける学習」への橋渡し**がスムーズにできます。

特に以下のようなセクションは、初心者にとって非常に役立ちます：

- EX3: 整数と文字列
- EX6: if文と条件分岐
- EX7: for文
- EX11: リストの操作

このあたりを一通りやってからABCの過去問に進むのがオススメです。

---
### ステップ②：AtCoderに登録し、過去問にチャレンジする

まずは [AtCoder](https://atcoder.jp/) に登録しましょう。登録は無料で、すぐに問題を解き始めることができます。

初心者におすすめなのは、**ABC（AtCoder Beginner Contest）の過去問**です。

特に次のような問題から始めると、無理なく実力を伸ばせます：

- ABC081A – Placing Marbles
- ABC086A – Product
- ABC083B – Some Sums

これらは入力と出力の練習にちょうど良く、短いコードで解けるので達成感も得やすいです。

---

### ステップ③：提出して、即時フィードバックをもらう

コードが書けたら「提出」ボタンを押すと、即座に「AC（正解）」や「WA（不正解）」などの判定が返ってきます。

これは、普通の学習教材にはない大きなメリットです。

- 成功すれば自信になる
- 失敗してもテストケースのおかげで改善点が分かる

学習効率が非常に高く、モチベーションも維持しやすいです。

# おわりに

Pythonの文法を一通り学んだあと、「次は何をすればいいんだろう？」という壁にぶつかる人は少なくありません。そんなとき、**AtCoderはまさに“実践の場”としてぴったりの教材**になります。

- 文法の復習になる  
- 自動採点でフィードバックが得られる  
- シンプルな問題から段階的にレベルアップできる  

特に「APG4b」から始めて、ABCの過去問を少しずつ解いていけば、自然とPythonの書き方や考え方が身についていきます。

「競プロだから難しそう」と思わずに、まずは1問だけでもチャレンジしてみてください。**“コードを書いて動かす楽しさ”**を実感できるはずです。

ここまで読んでいただきありがとうございました！
HTML・CSS入門　classとidの違いとは？divを例に使い分けと実務での活用方法

# はじめに
HTMLとCSSでレイアウトを組む際、必ず使用するのが`<div>`要素。

どちらもスタイルやJavaScriptでの操作に使われますが、**役割や使いどころには明確な違い**があります。
この記事では、`class`と`id`の違い・使い分け・実務での使用例を、備忘録として整理します。

# ①classとidの違いをざっくり比較
属性 | 用途 | 特徴 |
|------|------|------|
| `class` | 複数の要素に**共通のスタイル**を当てる | **何回でも使える** |
| `id` | 1つの要素だけを**一意に識別**する | **1ページに1つだけ**が原則 |

---

# ②使用例：classとidの基本構文

### classの例（複数の要素に同じスタイル）

```html
<div class="box">Box A</div>
<div class="box">Box B</div>
```
```css
.box {
    background-color: lightblue;
    padding: 10px;
}
```

### idの例(1つの要素だけに適用)
```html
<div id="main-header">ヘッダー</div>
```
```css
#main-header {
    font-size: 24px;
}
```

# ③CSSでの書き方の違い
![IMG_7855.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246240/4517bb69-e596-41cd-8c0c-a1e5249f19c1.jpeg)

# ④実務での使い分け
![IMG_7856.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246240/e8462076-1b8d-492c-a8ec-b360e4c74e42.jpeg)

# ⑤classとidのメリット・デメリット
![IMG_7857.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246240/bca65814-eb2b-44d7-b00f-faa977ade0aa.jpeg)

# ⑥実務での注意ポイント
- CSSの**優先度** (specificity) では id の方が class より強い（上書きしやすい）
- 同じIDを複数要素に使うと、JavaScriptやアンカーリンクが**意図通りに動かない**

# ⑦まとめ

![IMG_7858.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246240/2ce66924-9771-40ae-8166-2ca295e3bcb7.jpeg)

- **classは「グループ名」、idは「個別の名前（背番号）」と覚えておくと◎**
watsonx.governanceのmetricsで閾値を設定する方法

このgithubのサンプルコード。各種metricを設定して可視化できる・・が、閾値の設定方法が書かれていなかったので、メモ。
https://github.com/IBM/ibm-watsonx-gov/blob/samples/notebooks/python_sdk/model_insights/Model%20Insights.ipynb


各種メトリックススは以下で設定されているが、
```
metrics = [
    AveragePrecisionMetric(),
    ContextRelevanceMetric(),
    FaithfulnessMetric(),
    HitRateMetric(),
    NDCGMetric(),
    ReciprocalRankMetric(),
    RetrievalPrecisionMetric(),
    UnsuccessfulRequestsMetric(),
]
```

閾値は以下のように設定できる。
他のメトリックも同様に設定できる模様。

```
metrics = [
    ContextRelevanceMetric(method="sentence_bert_mini_lm",thresholds=[MetricThreshold(type="lower_limit", value=0.1)]),
]
```
なお、初期値はtype=lower_limit, value=0.8になっている。
upper_limitも設定できる。
【SAS対策】Route53 まとめ

## はじめに
ソリューションアーキテクトアソシエイト対策の学習メモ

## Route53とは？
 - マネージドDNS(ドメインネームサービス)
 - 所有しているドメインを管理(Route53サービス内でドメイン購入もできる)
 - ドメインはホストゾーンとして管理され、1ドメインあたり月額0.5ドル発生
 - ロードバランシングもできる
 - ヘルスチェック(限定的)
## レコードの種類
 - Aレコード：ホスト名をIPアドレスに(IPv4方式)
 - AAAAレコード：ホスト名をIPアドレスに(IPv6方式)
 - CNAMEレコード：ホスト名を別のホスト名へ
 - Aliasレコード：ホスト名をAWSリソースへ
※レコード：ドメイン名を IP アドレスに紐づけるためのデータベース上の情報のこと
```
ホストゾーン
└hogehoge.com(ルートドメイン)
　└test.hogehoge.com(Aレコード)
　└test2.hogehoge.com(AAAAレコード)
└hugahuga.com(ルートドメイン)
　└test.hugahuga.com(Aレコード)
 ```
## CNAMEレコードとAliasレコード
 - ALBのエンドポイントではなく、自分で決めたドメインを使いたいときなどに使用
 - CNAMEレコード：非ルートドメインに限る、有料
 - Aliasレコード：IPアドレスやドメイン名の代わりにCloudFront、Elastic Beanstalk環境、ELBなどを設定できる、ルートドメインも設定可、無料
## レコードのTTL(Time to Live)
 - 毎回DNSに問い合わせをすると時間がかかるので、キャッシュを利用している
その有効期間のこと
 - IPアドレスが変わってもTTLが切れないとDNSへの再問合せは発生しない
## ヘルスチェック
 - デフォルトでヘルスチェックに3回失敗したらunhealthy
 - デフォルトでヘルスチェックに3回合格したらhealthy
## ルーティングポリシー
 - **シンプル**
   - 単一リソースにリダイレクト
   - 1レコードに複数のIPアドレスを設定できる
   - ヘルスチェックを判定に使用不可(Aがhealthy、Bがunhelthyだった場合もA,Bが返る)
   - 複数の値が返却される(レコードのIPアドレスを複数設定)場合、クライアントがランダムに一つ選択
 - **複数値回答(マルチバリュー)**
   - ヘルスチェックを判定に使用可(Aがhealthy、Bがunhelthyだった場合もAのみ返る)
   - 同じドメインで複数レコード登録
 - **加重**
   - Aサーバに30%,Bサーバに20%,Cサーバに50%といった具合にリクエストを分散できる
   - 同じドメインで複数レコード登録
   - ヘルスチェックと併用可能
 - **レイテンシー**
   - クライアントの近くの最もレイテンシー(遅延)の少ないサーバにリダイレクト
   - レイテンシーはクライアントと設定したAWSリージョン間の遅延で評価
   - 同じドメインで複数レコード登録
 - **フェイルオーバー**
   - プライマリーサーバへのヘルスチェックがunhealthyになった場合、セカンダリのIPアドレスを返すようになる
   - プライマリサーバへのヘルスチェック設定が必須
   - 同じドメインで複数レコード登録(プライマリ、セカンダリ)
 - **位置情報**
   - ユーザの位置情報に基づいたルーティング(イギリスからのトラフィックは特定のIPに送られるよう指定)
   - デフォルトのポリシー作成が必要(ロケーションにマッチするものがない場合用)
   - 同じドメインで複数レコード登録(デフォルトを1レコード、各国や地域単位のレコード)
 - **地理的近接性**
   - ユーザとリソースの地理的な位置関係に基づいてルーティング
   - バイアスと呼ばれる値を指定する
   - AWSリソース(リージョンを指定)、AWS以外のリソース(緯度と経度を指定)を指定可能
   - トラフィックフロー(高度)を使う必要があり、Aレコードでは対応不可
   - 同じドメインで複数レコード登録
![route53_baias.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586050/3e995211-7c59-4855-b20b-3a49d4a896a1.png)
個人的備忘録：ALB + Fargate + FastAPI 環境における「502 Bad Gateway」エラーの切り分け手順

## はじめに

本記事では、AWS ALB（Application Load Balancer）と Fargate 上で稼働する FastAPI アプリケーションの構成において「502 Bad Gateway」エラーが発生した際の、原因特定と対処方法について整理します。

**個人の備忘録程度の走り書きとなっておりますが、温かい目で見守っていただければ幸いです。**

---

## よくある原因と対処法

### ① FastAPIアプリが `0.0.0.0` で起動していない
- **NG例**: `uvicorn main:app`（デフォルトでは `127.0.0.1:8000`）
- **OK例**: `uvicorn main:app --host 0.0.0.0 --port 8000`

> Fargate 環境では、`0.0.0.0` でバインドしないと外部（ALB）からアクセスできません。

---

### ② ALBのターゲットグループのヘルスチェックが FastAPI に存在しない（これから調査）
- 例：ターゲットグループのヘルスチェックパス `/health` を設定していて、FastAPI 側にそのエンドポイントが存在しない場合、ターゲットが常に `unhealthy` となり、結果として `502` エラーになる可能性が高い。

```python
# FastAPI 側でのヘルスチェックエンドポイントの追加例
@app.get("/health")
def health_check():
    return {"status": "ok"}
```

---

### ③ ターゲットグループと FastAPI のポート不一致
- FastAPI の起動ポートと、ALB のターゲットグループが指定しているポートが一致していない場合も `502` が発生します。
- 例：FastAPI を `--port 8000` で起動している場合 → ターゲットグループのポートも 8000 に設定する必要があります。

---

### ④ セキュリティグループの設定ミス
- ALB のセキュリティグループから、Fargate のセキュリティグループに対して TCP 8000 ポートのインバウンド通信が許可されていない場合、通信できずに `502` となります。

---

### ⑤ FastAPI コンテナが内部エラーで応答していない
- 表面的には Uvicorn が起動していても、FastAPI のアプリ内部で例外が発生していたり、起動処理が失敗していることがあります。
- `aws logs` コマンドや CloudWatch Logs を確認して、エラーの有無をチェックします。

---

## チェックリスト（簡易版）

| チェック項目 | 確認結果 |
|---------------|----------|
| FastAPI が `0.0.0.0` で待ち受けているか | ✅ |
| ポート8000で起動しているか | ✅ |
| ターゲットグループがポート8000に向いているか | ✅ |
| ターゲットグループのヘルスチェックパスが FastAPI 側にあるか | ✅ |
| セキュリティグループで ALB→Fargate 通信が許可されているか | ✅ |
| FastAPI のログにエラーがないか | ✅ |

---

## 補足：ログに「エラーがない」ように見えても
`INFO` ログしか出ていない場合でも、コンテナ内のアプリが正しく処理を返せていないケースがあります。

リクエストに対して `500` を返していたり、タイムアウトしている可能性も含めて、アプリケーションログと ALB のターゲットステータス（unhealthy）などを合わせて確認してみてください...！

---

## まとめ
本記事で紹介したように、ALB との組み合わせでよく発生する `502 Bad Gateway` の多くは、「アプリが適切に公開されていない」「ヘルスチェック失敗」が原因です。

:::note alert
***現時点では問題はまだ解消していませんが、これらの観点をもとに、引き続き原因を切り分けながら確認を進めていく予定です。***
:::

1つずつ設定を丁寧に見直すことで、安定したデプロイ環境を構築できるはずです。ALB との組み合わせでよく発生する `502 Bad Gateway` の多くは、「アプリが適切に公開されていない」「ヘルスチェック失敗」が原因です...！