0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

レガシーWebシステムを改修する技術 (1) - 環境構築とFeature Toggle編

0
Last updated at Posted at 2026-07-07

この記事は Qiita Tech Festa 2026 の投稿記事です。

【連載】レガシーWebシステムを改修する技術:Feature Toggle, シャドーイング, リファクタリング

はじめに

Qiita Tech Festa 2026 の投稿にさいして、いい機会なので少し古い手法ではあるのですが、レガシーWebシステムで ダウンタイムやデグレリスクを最小限に抑えつつ新旧ロジックを切り替える手法 をアウトプットしようと思います。割とボリュームがあるので4回に分けての記事にしようと思います。

対象はアプリケーション固有の価値となる場所で特にテストを厚くする重要性の高い、コアロジックを取り扱う層(アーキテクチャデザインパターンによって呼称が違いますが、ユースケースやサービスなどと呼ばれる層になると思います)とします。

第1回となる本記事では、リファクタリングを安全に行うための「土台」となるローカル開発環境の構築と、Feature Toggle を管理するサーバーの実装について解説します。

なぜアプリケーションで Feature Toggle を実装するのか?
モダンな開発環境であれば、LaunchDarkly などの Feature Toggle SaaSや、Istio などのサービスメッシュによるインフラ層でのトラフィックシャドーイングを利用するのが定石です。

しかし、レガシーシステム現場では

  • 「新しい外部SaaSの導入ハードルが高い」
  • 「インフラ構成を気軽に変更できない」

といった制約が多々あります。そのため本連載では、アプリケーションコードとシンプルなDocker環境という手元の技術だけ で完結させるアプローチを採用しています。

実際にはKVSサービスを利用するなどした方がよいとは思いますが、ミニマムなPoCとしても解説や環境整備のしやすさを優先して今回はアプリケーションサーバとして実装することにします。

概要・前提条件

技術スタック

  • Python 3.11以上 ※実際には執筆時点で EOL手前 の 3.10 でも可能なはずです
  • FastAPI
  • Docker Compose
  • pytest

全体アーキテクチャとディレクトリ構成

このハンズオン環境では、クライアントからのリクエストを処理する web_server と、フラグの状態を管理・配信する toggle_server の2つのコンテナを起動します。これにより、アプリケーションコードを再デプロイすることなく、リアルタイムに新旧ロジックを制御・検証できます。

├── docker-compose.yml
├── toggle_server/
│   ├── Dockerfile
│   └── main.py
└── web_server/
    ├── Dockerfile
    ├── requirements.txt
    ├── app/
    │   ├── __init__.py
    │   ├── services.py   # 既存コード・Protocol・新コード・Wrapper
    │   └── main.py       # Webサーバーのエントリポイント
    └── tests/
        ├── __init__.py
        ├── test_characterization.py # 1. 既存コードへの仕様化テスト
        └── test_new_logic.py        # 2. 新コードのRed-Green TDD

本題・実装:環境定義 (Docker Compose)

まずは2つのサーバーをオーケストレーションする docker-compose.yml と、各コンテナの Dockerfile を定義します。

docker-compose.yml
services:
  web:
    build: ./web_server
    ports:
      - "8000:8000"
    environment:
      - TOGGLE_SERVER_URL=http://toggle:8001/toggles/use-new-service
    volumes:
      - ./web_server:/app
    depends_on:
      - toggle

  toggle:
    build: ./toggle_server
    ports:
      - "8001:8001"
    volumes:
      - ./toggle_server:/app
web_server/Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
# 依存関係がインストールごとにブレるようなことがない限り、レガシーシステムに多い
# pip でのインストールのままとします
# ※ uv などへの移管は別トピックとして今回は取り扱わないものとします
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]

※ web_server/requirements.txt には fastapi, uvicorn, httpx, pytest を記述します。

軽量トグルサーバーの実装

Feature Toggleのサーバー側は、特定のフラグの有効・無効をJSONで返すシンプルなAPIです。開発中や本番運用中にここの状態を書き換えることで、動的にWebサーバーの挙動を制御します。

今回は以下の2つのトグルを管理するものとします。

  • enabled : true でユーザには新コードの実行結果を返却。 false でユーザには既存コードの実行結果を返却 (ディフォルトは既存コード参照)
  • shadow_mode : true で新と既存の結果を比較。 false で enabled で指定されたコードのみ参照

これを使って以下の段階的な切り替えを行っていく想定です。

  • 既存の挙動 ( false , false )
  • シャドーイングを導入 ( false , true )
  • 新コードで検証 ( true , true )
  • 新コードでの挙動に切り替え ( true , false )

トグルサーバのコード例は以下になります。

toggle_server/main.py
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

# 擬似的なインメモリDB(本番環境ではRedisや専用SaaS等を使用)
toggles = {
    "use-new-service": {
        "enabled": False,       # 初期値は既存コード優先 (デフォルト)
        "shadow_mode": True     # 裏側で新コードも走らせて比較するモード
    }
}

class ToggleResponse(BaseModel):
    enabled: bool
    shadow_mode: bool

# 現在のフラグの状態を返す
# 例) GET /toggles/use-new-service
#    {"enabled":false,"shadow_mode":true}
@app.get("/toggles/{name}", response_model=ToggleResponse)
def get_toggle(name: str):
    return toggles.get(name, {"enabled": False, "shadow_mode": False})

# enabled=True に変更する
# 例) POST /toggles/use-new-service/enable
@app.post("/toggles/{name}/enable")
def enable_toggle(name: str):
    if name in toggles:
        toggles[name]["enabled"] = True
    return toggles.get(name)

# 以降、enabled, shadow_mode を切り替えるエンドポイントを作るが略

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8001)

おわりに

第1回では、リファクタリングを支えるローカル開発環境として、Webサーバーとトグルサーバーの連携環境を構築しました。

次回の第2回では、この土台の上で typing.Protocol を活用した既存コードの抽象化と、シャドーイング(ダークローンチ)による安全な新旧切り替えロジックの実装方法を記載していきます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?