hosochinの技術ブログ

【Spring Boot】機能フラグ(Feature Flags)を実装する

はじめに

お世話になります、hosochinです。 今回はJava/Spring Bootで機能フラグ(Feature Flags)を導入する方法についてです。 機能フラグを使うことで、コードを変更せずに機能のON/OFFを切り替えることができます。

目次

機能フラグとは

機能フラグ(Feature Flags / Feature Toggles)は、実行時に機能のON/OFFを切り替えるための仕組みです。 環境変数や設定ファイルを使って、コードを変更せずに新機能の有効化/無効化を制御できます。

機能フラグのメリット・デメリット

メリット

  • 段階的なリリースが可能: 新機能を特定のユーザーやステージング環境でのみ有効化できる
  • リスクの低減: 問題が発生した場合、コードを戻さずに機能を無効化できる
  • 並行開発の支援: 複数の機能を同時に開発しながら、本番環境では無効にできる
  • A/Bテストの実施: 異なる実装を切り替えて比較検証できる

デメリット

  • コードの複雑化: 分岐処理が増えるため、コードが読みにくくなる可能性がある
  • 技術的負債: 古い機能フラグが残り続けると、メンテナンス性が低下する
  • テストケースの増加: ON/OFF両方のパターンをテストする必要がある

Spring Bootでの実装方法

今回は、@ConfigurationPropertiesを使った実装方法を紹介します。 重要なポイントは以下の通りです:

  1. 環境変数で制御: application.ymlで設定し、環境変数で上書き可能にする
  2. Beanごとの差し替えをしない: 複数案件が同時並行で進んでいる場合、同じクラスに修正を加えたいケースを考慮
  3. Staticメソッドでも利用可能: @PostConstructを使って静的インスタンスを保持する

実装例

1. 機能フラグ設定クラス

@ConfigurationPropertiesrecordを使ってシンプルに実装します。 @PostConstructで静的インスタンスを保持することで、staticメソッドからも参照可能にします。

機能フラグを1つのクラスで一元管理することで、どの機能フラグが現在使われているかが一目でわかります。 これにより、不要になった機能フラグの削除忘れを防ぎ、コードベース全体への汚染を最小限に抑えることができます。

package com.example.demo.config;

import jakarta.annotation.PostConstruct;
import org.springframework.boot.context.properties.ConfigurationProperties;

/** 機能フラグを一元管理するクラス */
@ConfigurationProperties(prefix = "feature")
public record FeatureFlags(boolean newUiEnabled) {
  private static FeatureFlags staticFeatureFlags;

  @PostConstruct
  private void init() {
    staticFeatureFlags = new FeatureFlags(newUiEnabled);
  }

  public static FeatureFlags getInstance() {
    return staticFeatureFlags;
  }
}

2. application.yml

環境変数で上書き可能な設定として定義します。

# 機能フラグ設定
feature:
  # 新しいUI機能
  new-ui-enabled: ${FEATURE_NEW_UI_ENABLED:false}

3. サービスクラスでの利用

DIでも静的参照でも両方使えます。

package com.example.demo.service;

import com.example.demo.config.FeatureFlags;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class SampleService {

  private final FeatureFlags featureFlags;

  public String execute() {
    // パターン1: DIして使う場合
    if (featureFlags.newUiEnabled()) return "機能フラグON";
    return "機能フラグOFF";

    // パターン2: static参照(staticメソッド内でも利用可能)
    // if (FeatureFlags.getInstance().newUiEnabled()) return "機能フラグON";
    // return "機能フラグOFF";
  }
}

環境変数での上書き

本番環境では環境変数で機能フラグを制御できます:

# 環境変数で機能を有効
export FEATURE_NEW_UI_ENABLED=true

# またはアプリケーション起動時に指定
java -jar app.jar --feature.new-ui-enabled=true

まとめ

Spring Bootで機能フラグを実装する方法を紹介しました。

ポイント:

  • @ConfigurationPropertiesを使ってシンプルに実装
  • 環境変数で簡単にON/OFF切り替え可能
  • @PostConstructを使うことでstaticメソッドからも参照可能

機能フラグは便利な仕組みですが、使い終わった機能フラグは定期的に削除し、コードをクリーンに保つことが重要です。