Twelve-Factor Appを理解する！！

# 導入

こんにちは、もんすんです。

クラウド環境やコンテナ技術と親和性の高い**Twelve-Factor App**は、開発者にとって強力な指針となります。
このガイドラインに従うことで、効率的な開発、安定した運用、そして容易なスケーリングが可能になります。

今回は、Twelve-Factor Appの基本的な考え方や12の原則をわかりやすく、日常における例と合わせて解説していきます。

# Twelve-Factor Appとは？

## 概要

**Twelve-Factor App**とは、クラウド時代に適したアプリケーションを構築するための12の基本原則をまとめたガイドラインです。

Herokuの開発者によって提唱され、アプリの**移植性**、**スケーラビリティ**、**運用の簡便性**を高めることを目的としています。

これらの原則に従うことで、以下の利点があります。

- **スムーズなデプロイ**：開発から本番環境への移行がスムーズ。Twelve-Factor Appを理解する
- **チーム開発の効率化**：他の開発者が簡単にコードを理解し、作業に参加できる。
- **スケールのしやすさ**：アプリが簡単に拡張でき、トラフィックの増減にも柔軟に対応。

クラウドやコンテナ環境に適したモダンなアプリを作る際に、Twelve-Factor Appは信頼できる「地図」のような存在です。
この原則を理解すれば、運用に強いアプリを作れるようになります。

## 1. Codebase  (コードベースの一元管理)
**一つのコードベースを一元管理し、複数環境にデプロイ**

**ポイント**
アプリのコードは1つのリポジトリで管理し、開発環境や本番環境に共有するということです。

**メリット**
コードを変更すれば、どの環境にも反映可能になります。
バグ修正や新機能の展開が簡単です。
逆に一元管理しないと、環境差異が発生する可能性が高くなってしまいます。

**イメージ例**
本を作るとしても、その元々の原稿は1つだけにします。
それをコピーして、本を印刷すれば、同じ本がたくさん作ることができます。


## 2. Dependencies  (依存関係の明示化)
**アプリが使うライブラリやツールを明確に定義する**

**ポイント**
必要なパッケージやツールを明示的に指定するということを指します。
nodeであれば、`package.json`、Pythonであれば、`requirements.txt`のことを指します。
環境ごとに依存関係を隔離します。

**メリット**
動作環境が異なるPCやサーバーでも、同じ結果を再現可能になります。

**イメージ例**
料理に必要な材料をリスト化して、買い物袋ごとに分けておくようなものです。
リスト化しておかないと、間違った食材を買ってしまい、正しく料理が作れなくなってしまいますね。

## 3. Config  (設定は環境変数で管理)
**設定情報 (APIキーやデータベース情報など)はコードから分離する**

**ポイント**
設定をコードではなく、環境変数として外部に保存します。

**メリット**
環境ごとに設定を簡単に変更が可能です。
本番環境の秘密情報も安全に管理できます。
直接ソースコードに書いてしまうと、セキュリティ的な問題が発生したり、修正するのが大変だったりします。

**イメージ例**
アプリは「手紙」で、宛先 (設定)は別紙に書いておくイメージです。
宛先を変えればどこにでも送れます。

## 4. Backing Services  (外部サービスはリソース扱い)
**データベースや外部APIを交換可能なリソースとして扱う**

**ポイント**
データベースやメール配信サービスなどの**外部サービス**はアプリに埋め込まず、接続先を柔軟に変更可能なリソースとします。

**メリット**
サービスの切り替えやアップグレードが簡単になり、柔軟性が向上します。

**イメージ例**
電源コードがなく、壁に設置されているインターホンや給湯器のリモコンより、好きなコンセントに差し替えられる家電の方が柔軟であるというイメージです。

## 5. Build, Release, Run  (ビルド・リリース・実行の分離)
**アプリの作成と公開、実行のフェーズを分ける**

**ポイント**
1. **ビルド**：コードをアプリに変換するフェーズ
2. **リリース**：アプリに設定を加えて準備するフェーズ
3. **実行**：実際にアプリを動かすフェーズ

**メリット**
それぞれを分離することでトラブル時の原因追求が容易になります。

**イメージ例**
プラモデルを作るなら、プラモデルの組み立て(ビルド)→完成品を飾る準備(リリース)→実際に展示する(実行)イメージです。

## 6. Processes  (ステートレスプロセス)

**アプリは「状態を持たない」設計にする**

**ポイント**
アプリはデータを保存せず、必要な情報、特に状態情報をデータベースや外部ストレージに任せます。

**メリット**
アプリサーバの台数を増減しても影響がなく、スケーラビリティが高まります。

**イメージ例**
店員が注文をすぐにメモに書いて注文台に置くことで、それ以降は別の店員が対応できる仕組みと似ています。
もし、注文した店員がメモをポケットにしまってしまうと、別の店員は対応できなくなりますね。

## 7. Port Binding (ポートバインディング)
**アプリ自身がポートをバインドし、外部から直接アクセス可能にする**

**ポイント**
アプリはWebサーバーに依存せず、自分でポートを公開し、外部からアクセスできるようにします。

**メリット**
設定がシンプルで、どこにでも簡単にデプロイ可能になります。

**イメージ例**
アプリが「お店」だとしたら、特定の「住所(ポート番号)」を使って訪問者を迎えるイメージです。 

## 8 Concurrency (プロセスモデルでのスケール)
**複数のプロセスを活用してアプリの負荷に対応する**

**ポイント**
アプリを複数のプロセスに分けて動かし、負荷を分散します。
例えば、Webリクエスト処理用のプロセスとバックグラウンド作業用のプロセスを分けます。 

**メリット**
負荷が増えたらプロセスを増やすだけでスケールアウトが可能になります。
プロセスを分けないとサーバ自体をスケールアウトする必要が出てくるため、必要のないプロセス分までスケールアウトすることになってしまいます。

**イメージ例**
レストランで料理を作る人と配膳する人を分けて仕事を効率化するようなものです。  

## 9. Disposability (素早い起動と終了)
**プロセスはすぐに起動・終了できるよう設計する**

**ポイント**
プロセスが短時間で起動し、終了時には未処理を残さないようにします。
これにより障害発生時のリカバリが迅速に行えます。

**メリット**
障害発生時の影響を最小限に抑え、柔軟な運用が可能になります。

**イメージ例**
仕事中でも片付けが簡単な机を用意しておくと、すぐ次の作業に取り掛かれるようなものです。 

## 10. Dev/Prod Parity (開発・本番の一致)
**開発環境と本番環境を可能な限り一致させる**

**ポイント**
開発、ステージング、本番環境のギャップを減らすことで、本番環境で発生した問題を開発環境でも同じように再現できます。

**メリット**
環境差によるバグを防ぎ、本番運用時のトラブルが減少するというメリットがあります。

**イメージ例**
演劇や舞台などで、リハーサルと本番が同じステージや衣装を使って行われるのと同じです。
そのような業界でも、いかにリハーサルを本番さながらに実施できるかによって、本番前にトラブルに気づけるかが決まります。

## 11. Logs (ログをイベントストリームとして扱う)
**ログはアプリの動作記録としてストリーム出力する**

**ポイント**
ログはファイルに保存するのではなく、リアルタイムで外部のログ管理サービス(AWSのCloudWatchなど)に送信します。

**メリット**
ログの分析や監視が簡単になり、トラブルシューティングが迅速になります。
また、サーバがダウンしてもそのサーバログは外部にあるわけですから、その保全にもなります。

**イメージ例**
パソコンのローカルPCに作業内容を残すのではなく、クラウド上で作業することで、リアルタイムで情報が保存されていく動きに似ています。

## 12. Admin Processes (管理タスクのワンオフ実行)
**管理作業は一時的なプロセスとして実行する**

**ポイント**
データ移行やバッチ処理などの管理タスクは、通常のアプリのプロセスとは独立した一時的なプロセスとして実行します。

**メリット**
管理タスクがアプリに影響を与えず、運用の安定性が向上します。

**イメージ例**
普段は動かない特別な装置を一時的に使うようなものです。

# 終わりに

Twelve-Factor Appは、クラウド時代のアプリケーション開発の「基本設計図」として、多くの利点を提供します。
この原則を理解し、実践することで、柔軟でスケーラブルなアプリケーションを構築できるようになります。

本記事を参考に、まずは小さなステップから取り組み、開発プロジェクトやチームに適応させてみてください！