木曜日, 7月 17, 2025
木曜日, 7月 17, 2025
- Advertisment -
ホームニューステックニュース新規プロダクト開発チームが Claude Code を活用するために取り組んでいること

新規プロダクト開発チームが Claude Code を活用するために取り組んでいること


こんにちは、株式会社カナリーでソフトウェアエンジニアをやっている matsu です。本記事はチームメイトの さかす と共同で執筆しています。

私たちは現在、エンジニア6人のチームで新規プロダクトを開発しています。

さて、今年の6月頭、AIコーディング支援ツール「Claude Code」が一気に話題となりました。そのタイミングで社内でも導入が検討され始め、一部のメンバーがいち早く活用を始めていました。「開発速度が爆速になった」「もう戻れない」といった声が聞こえてくる一方で、一部のメンバーしか使っていないが故に、知見が個人に閉じてしまっていたりチームでの開発フローを大きく変えることが難しかったりと、少しもったいない状況になっていました。

そこで私たちのチームでは、1週間集中の検証プロジェクト「Dive into Claude Code」を実施。チーム全員で Claude Code を使い倒し、各々が得た知見を共有する機会を作りました (プロジェクトの詳細については、別の記事で追ってご紹介する予定です)。

このプロジェクトによって、AI エージェントをチームに組み込むには環境や開発フローをどのように変えていけば良いのか、活発な議論が生まれるようになり、実際に様々な変化が生じました (プロジェクト終了後もチーム全員が継続して利用しています)。

本記事では、Claude Code の導入によって私たちのチームにどのような変化が起きたのか利用する上でどのような工夫をしているのか、といった点をご紹介します。

まず前提として、私たちのチームは新規の機能開発がメインのフェーズです。したがって、トイルや既存機能の改修は少なく、Claude Code の活用場面も新規機能の開発が中心となっています。

1つの機能開発は、ざっくりですがおおよそ以下のようなステップで進んでいることが多いです。

  1. 🙎‍♂️ 開発担当者が機能要件を Claude Code に提供
  2. 🤖 Claude Code が作業計画を作成
  3. 🙎‍♂️ 開発担当者が作業計画をレビュー (場合によってはチームでレビューします、後述)
  4. 🤖 Claude Code が作業計画を基にコーディングし、Pull Request の作成までを実施
  5. 👥 チームでコードレビュー

もちろん、Claude Code が担当するステップも、人間のサポートを必要とする場面はままあります。それでも、コミットのおおよそ 2/3 は Claude Code が生み出していたりPull Request の発行はほぼ全て Claude Code が行なっていたりと、かなりの活躍を見せてくれています。

以降では、Claude Code に最大限活躍してもらうために、私たちが実践している具体的な取り組みや工夫を紹介していきます。

開発フローの改善

Plan mode から始める

Claude Code には Plan mode と呼ばれる、調査計画立案を専門とするモードが存在します。

何らかの作業を Claude Code にお願いする際には、まずは Plan mode で作業計画を立案してもらい、その作業計画を人間がレビューした上で実作業に進んでもらう、という流れを基本としています。例えば、次のようなアプローチで作業計画を立ててもらっています。

  • 要求をまとめた指示書 (.md) を人間が作成し、それをベースに作業計画を立ててもらう
  • チャットベースで要件や実装方針をディスカッションし、最後に会話内容をベースに作業計画を立ててもらう

以下、入力する指示書と出力される作業計画のイメージです (業務で実際に利用したものを、Claude Code に依頼して架空のノートアプリのものに変換してもらいました)。

指示書の例

ユーザーは、ノートのステータスを共有モードに変更することができるようになる

概要

  • note_app に Note の Status を変更できる ChangeNoteStatus API を生やす
  • gateway_note_app_user で note_app の ChangeNoteStatus を shared で呼び出す ShareNote APIを生やす
作業計画の例

ユーザーは、ノートのステータスを共有モードに変更することができるようになる

概要

  • note_app に Note の Status を変更できる ChangeNoteStatus API を生やす
  • gateway_note_app_user で note_appの ChangeNoteStatus を shared で呼び出す ShareNote API を生やす

1. note_app サービスの ChangeNoteStatus API 実装

Protocol Buffers定義

  • proto/src/note_app/v1/service.protoChangeNoteStatus RPCメソッドを追加
  • proto/src/note_app/v1/service.protoChangeNoteStatusRequestChangeNoteStatusResponse メッセージを追加

実装差分

// proto/src/note_app/v1/service.proto
service NoteService {
    // 既存のメソッド...
    rpc ChangeNoteStatus(ChangeNoteStatusRequest) returns (ChangeNoteStatusResponse) {}
}

// Note のステータス変更リクエスト
message ChangeNoteStatusRequest {
    // ワークスペースID
    string workspace_id = 1;
    // ノートID
    string note_id = 2;
    // ステータス
    Status status = 3;
}

// Note のステータス変更レスポンス
message ChangeNoteStatusResponse {
    // ノート(Embedで関連データを含む)
    NoteEmbed note = 1;
}

ドメイン層

  • pkg/note_app/content/domain/note/repository.go にアップデートメソッドを追加
  • pkg/note_app/content/domain/note/note.go にビジネスロジックメソッドを追加

インフラ層

  • pkg/note_app/content/infra/spanner/note_repository.goUpdateNote 実装を追加

ユースケース層

  • pkg/note_app/content/usecase/usecase.go にインターフェースを追加
  • pkg/note_app/content/usecase/change_note_status.go にビジネスロジック実装を追加
  • レスポンス用にNoteEmbedを構築(NoteとNoteAttachmentを含む)

アダプター層

  • pkg/note_app/adapter/note.go にgRPCハンドラーを追加

2. gateway_note_app_user サービスの ShareNote API 実装

Protocol Buffers定義

  • proto/src/gateway_note_app_user/v1/note_service.protoShareNote RPCメソッドを追加
  • proto/src/gateway_note_app_user/v1/note_service.protoShareNoteRequestShareNoteResponse メッセージを追加

実装差分

// proto/src/gateway_note_app_user/v1/note_service.proto
service NoteService {
    // 既存のメソッド...
    rpc ShareNote(ShareNoteRequest) returns (ShareNoteResponse) {
        option (google.api.http) = {
            post: "/v1/notes/{note_id}/share"
            body: "*"
        };
    }
}

// 共有実行リクエスト
message ShareNoteRequest {
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
        json_schema: {
            title: "ShareNoteRequest"
            description: "ノート共有実行リクエスト"
            required: ["note_id"]
        }
    };

    // ノートID
    string note_id = 1;
}

// 共有実行レスポンス
message ShareNoteResponse {
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
        json_schema: {
            title: "ShareNoteResponse"
            description: "ノート共有実行レスポンス"
            required: ["note"]
        }
    };

    // ノート(Embedで関連データを含む)
    NoteEmbed note = 1;
}

ゲートウェイ層実装

  • pkg/gateway_note_app_user/note.go にgRPCハンドラーを追加
  • note_appの ChangeNoteStatusSTATUS_SHARED で呼び出す実装
  • note_appのレスポンス(NoteEmbed)をそのまま返す

Phase 1: Protocol Buffers定義の追加とコード生成

1.1 note_app サービスのProtocol Buffers定義

  • proto/src/note_app/v1/service.protoChangeNoteStatus RPCメソッドを追加
  • proto/src/note_app/v1/service.protoChangeNoteStatusRequestChangeNoteStatusResponse メッセージを追加
  • レスポンスは NoteEmbed を使用

1.2 gateway_note_app_user サービスのProtocol Buffers定義

  • proto/src/gateway_note_app_user/v1/note_service.protoShareNote RPCメソッドを追加
  • proto/src/gateway_note_app_user/v1/note_service.protoShareNoteRequestShareNoteResponse メッセージを追加
  • レスポンスは NoteEmbed を使用

1.3 コード生成

  • make proto-generate を実行

Phase 2: note_app サービス – ドメイン層の実装

2.1 リポジトリインターフェースの追加

  • pkg/note_app/content/domain/note/repository.goUpdateNote(ctx context.Context, note *Note, fillInFields []NoteColumnStr) (*Note, error) メソッドを追加

2.2 ドメインロジックの実装

  • pkg/note_app/content/domain/note/note.goChangeStatus メソッドを追加(バリデーションロジック含む)

Phase 3: note_app サービス – インフラ層の実装

3.1 Spannerリポジトリの実装

  • pkg/note_app/content/infra/spanner/note_repository.goUpdateNote の実装を追加
  • fillInFieldsパラメータ([]NoteColumnStr型)を使用して、指定されたフィールドのみを更新

Phase 4: note_app サービス – ユースケース層の実装

4.1 ユースケースインターフェースの追加

  • pkg/note_app/content/usecase/usecase.goChangeNoteStatus メソッドを追加

4.2 ユースケース実装

  • pkg/note_app/content/usecase/change_note_status.go に実装を追加
  • レスポンス用にNoteEmbedを構築(NoteとNoteAttachmentを含む)

Phase 5: note_app サービス – アダプター層の実装

5.1 gRPCハンドラーの実装

  • pkg/note_app/adapter/note.goChangeNoteStatus gRPCハンドラーを追加

5.2 Wire設定の更新

  • 必要に応じてDI設定を更新
  • make generate を実行

Phase 6: note_app サービス – テストの実装

6.1 各層のユニットテスト

  • ドメイン層のテスト
  • インフラ層のテスト
  • ユースケース層のテスト
  • アダプター層のテスト

6.2 統合テスト

  • エンドツーエンドテストの追加

Phase 7: gateway_note_app_user サービスの ShareNote API 実装

7.1 ゲートウェイ層の実装

  • pkg/gateway_note_app_user/note.goShareNote gRPCハンドラーを追加
  • note_appの ChangeNoteStatusSTATUS_SHARED で呼び出す実装
  • note_appのレスポンス(NoteEmbed)をそのまま返す

7.2 テストの実装

  • ゲートウェイ層のユニットテストを追加
  • エンドツーエンドテストを追加

重要なポイント

  • note_app、gateway_note_app_user 両方のレスポンスで NoteEmbed を使用
  • NoteEmbed には Note と関連する NoteAttachment を含む
  • gateway_note_app_user は note_app のレスポンスをそのまま返すため、実装が簡潔
  • usecaseのファイル名は change_note_status.go を使用
  • adapterのファイル名は note.go を使用
  • 既存のアーキテクチャとAPIパターンに従った実装を行う

Plan mode を起点としたプロセスには、以下のようなメリットがあります。

  • Claude Code が根本的な方針の間違いや想定外の挙動を起こしにくくなる。これにより、追加の指示や作業のやり直しといった余計な手間が激減する。
  • 整理された作業計画をドキュメントとして残すことができる。これにより、チーム内でのコードレビューに活用する実装時の方針や意図を後世に残す、などが可能になる (詳細は次の項にて)。
  • Claude Code がプランニングの壁打ちに徹してくれることで、開発者自身が仕様や設計を改めて整理するきっかけになる。

新規の機能開発では、こうした恩恵を特に受けやすいと感じています。一方的な指示出しのみでいきなりコーディングに入ってしまうと、複雑なビジネスロジックを伝えきれず、人間の意図とは全く異なる方向に進んでいくことがほとんどです。そのため、新規の機能開発では必ず、Plan mode で会話しながら丁寧に仕様や設計、計画を擦り合わせ、その後にコーディングに移ってもらうようにしています。

Claude Code とのやり取りを文書化して Git で管理する

Claude Code に作業を進めてもらう過程では、文章のやり取りが多く発生します。例えば、

  • Plan mode への入力に使った指示書
  • Plan mode にて出力された作業計画
  • 実作業の途中で発生した方針転換ディスカッション

こうしたやり取りをその場限りで捨ててしまうのはもったいないと考え、ドキュメントとして Git で管理する試みを行っています。ドキュメント化も Claude Code に任せれば良いので、人間に追加の手間はほとんど発生していません。

この試みには、以下のようなメリットを感じています。

  • 他のメンバーがどのように Claude Code を利用しているのか把握しやすい
  • 新たな作業計画を立てる際に、過去の入力に使った指示書を転用できる
  • なぜそのような方針・実装になったのか、という情報が第三者 (コードレビューのレビュワーや、将来そのコードを読む人など) に伝わりやすい

一方で、どこまでをコミット対象とするかの線引きが難しい、単純にドキュメントの量が膨大になる、といった運用面の課題が将来的に発生する可能性は感じており、引き続き良い形を探っていきたいです。

実作業の前にチーム内で作業計画書をレビューする

実装の高速化により、人間によるコードレビューが追いつかない場面がちらほら見られるようになりました。これにより、レビューが返ってくる頃には既にその先の実装が進んでいることが多く、レビューで根本的な指摘が入った際の手戻りが大きくなる問題が発生していました。

この問題を軽減するために、開発タスクが複雑な場合は作業計画書をチーム内でレビューしてから実装に進む、という試みを実施しています。「根本的な指摘が入らないように事前に方針を擦り合わせる」というアプローチですね。

前述の通り、作業計画書はいずれにせよ最初に Claude Code に生成してもらうため、開発担当者に追加の手間は発生しません。その上で具体的な方針や設計を事前にディスカッションできるため、非常に効果的に働いています。

また、類似の試みとして、業務委託の方にタスクを依頼する際に、併せて作業計画書をお渡しするようにしてみています。業務委託の方とは非同期のコミュニケーションが中心となる場面も多く、依頼するタスクの内容を具体的に伝達することが重要です。作業計画書であれば、ドキュメント準備のコストを下げつつ方針や意図を具体的に伝えられるため、こちらの試みも効果的に働いていると感じています。

Claude Code に渡すコンテキストを整備する

プロジェクトの規約や暗黙知を言語化して整備する

Claude Code との開発でコードベースの秩序を保つためには、プロジェクト特有の規約から、これまで暗黙のうちに守ってきたルールとも呼べないものたちに至るまで、正しく言語化して Claude Code に伝えてあげる必要があります。

そのための一般的な手段が メモリファイル です。Claude Code を使い始めたらまずはこのメモリファイルを作成し、その後もプロジェクトの変化に応じて継続的にメンテナンスし続けなくてはなりません。

私たちのチームでは、以下のようなドキュメント (多いので一部のみ掲載) を .claude ディレクトリ配下に配置し、CLAUDE.md から インポート しています。

  • 共通ドキュメント
    • 開発ワークフロー
    • ディレクトリ構成
    • 技術スタック・外部ライブラリ
    • 利用可能なコマンドの一覧
    • Pull Request 作成のガイドライン
  • バックエンド関連
    • マイクロサービスの構成
    • インフラのアーキテクチャ
    • Protocol Buffers の設計指針・書き方
    • テストの指針・書き方
  • フロントエンド関連
    • コンポーネントの設計指針・書き方
    • コンポーネントテストの指針・書き方

書き方を指示するようなドキュメントでは、必ず手本となるような具体例を併せて記載するようにしています (テストの書き方を指示するドキュメントであれば、コードブロックでサンプルのテストコードを記載する、等)

情報を1つのリポジトリに集約する

Claude Code に参照してほしい情報は、1箇所に集約されている方が断然扱いやすいです。

MCP Server による外部ツールとの連携なども手段としては存在しますが、速度や柔軟性の面でボトルネックになりがちで、集約できるのであればそれに越したことはないと感じています。

そこで、Claude Code の利用開始を機に

  • ADR 等のドキュメントを Notion での管理から Git での管理に移行
  • 別々だったフロントエンドとバックエンドの GitHub リポジトリを1つに統合

の2つを実施しました。

余計なコンテキストが増えてノイズになるのでは?という点については、CLAUDE.md の複数配置 + VSCode の Multi-root Workspace 機能によっておおよそ解消できています。

以下はディレクトリ構成とワークスペース設定の一例です。必要に応じてご参照ください。

VS Code Multi-root Workspace 設定
project-root/
├── .claude/
├── CLAUDE.md
├── frontend/
│   ├── .claude/
│   ├── CLAUDE.md
│   └── src/
├── backend/
│   ├── .claude/
│   ├── CLAUDE.md
│   └── src/
├── docs/
│   ├── adr/
│   └── ...
└── .vscode/
    └── project.code-workspace

{
  "folders": [
    { "name": "root", "path": "." },
    { "name": "frontend", "path": "frontend" },
    { "name": "backend", "path": "backend" }
  ],
}

主に作業するディレクトリをワークスペースに追加しておくことで、ターミナルのルートパスを簡単に切り替えることが可能です。

Claude Code は起動したディレクトリを起点に CLAUDE.md やその他ファイルを読み込むため、作業するディレクトリごとに CLAUDE.md や .claude を配置しておくことで、手軽にコンテキストの切り分け・切り替えができるというわけです。

ルールベースの仕組みで不確実性を低減する

いくら Claude Code が優秀であるとはいえ、生成してもらうコード量が増えるほど不確実性が高くなり、品質のブレや人間によるコードレビューの負担が増加します。

そこで、ルールベースの仕組みを強化し、Claude Code に書いてもらうコード量を減らしたり、書いてもらったコードを高速にチェックしたりできるよう工夫をしています。

コードの自動生成

Claude Code に書いてもらうコード量を減らすアプローチです。

バックエンド (Go) では、パターン化可能な処理 (クリーンアーキテクチャの infrastructure 層や、各層への伝搬の際に必要となる型変換など) は積極的に go generate で生成するようにしました。

これにより、Claude Code とのやり取りを減らしたり、生成されたコードのレビュー範囲を狭めたりすることができています。

また、go generate で使用する generator 自体の作成も Claude Code にお願いしています。以前は、特に AST を用いて generator を組もうとするとそれなりの工数がかかり、対応が後回しになっていました。しかし、 Claude Code が、既存のコードベースの共通部分をうまいこと抽出して高精度な generator を作成してくれるようになったため、敷居がグッと下がっています。

フロントエンドでは、以前から Orval を使用して OpenAPI スキーマから API クライアント・TanStack Query 周りのコードを自動生成していましたが、Claude Code 導入後はバックエンド同様のメリットを享受できています。

pre-commit や Claude Code Hook で修正サイクルを加速する

リントやフォーマット、テストは、以前はエディタの機能や GitHub Actions の CI workflow にて実行していました。しかし、Claude Code を用いたコーディングでは現状これらの仕組みを活用するのは難しく、人間が CI workflow の結果を見て修正する、というような対応が発生してしまっていました。

そこで、 pre-commitClaude Code Hook にてこれらを実行することで、Claude Code が素早く検知・修正できるようにしました。pre-commit については、コミットまで Claude Code にお願いしておくことによって、コミット時にエラーを検知して修正までやってくれるようになります。

pre-commit 導入の際は、人間がコミットする際の体験が悪化する懸念はありましたが、そもそも人間がコミットする機会がかなり減っていたため、Claude Code の開発サイクルが遅くなる方が致命的だと考え、導入に至りました (導入後の体感としても、変更差分のみを対象とした局所的なチェックに留めることで、さしてストレスは感じていません)。

待ち時間の有効活用

Claude Code 実行中の待ち時間の有効活用、難しくないですか?私たちも絶賛試行錯誤中です。

現状、機能開発を何並列も同時にブン回すようなことは行えていません。タスク間の依存関係やコードレビューの兼ね合い、作業者のコンテキストスイッチの限界、などがボトルネックになっているためです。

一方で、改善活動のようなタスクであれば、機能開発と並列で作業しやすいのではないかと考えました。具体的には、リファクタや軽微なバグ修正、開発フローの整備 (前述した go generate の作成など) といったタスクがこれにあたります。

  • 機能開発と違って複雑なビジネスロジックが絡むことが少ないため、1回の指示出しだけでもタスクを正しく完遂できる場合が多々ある
  • タスク間の依存が無い場合が多く、ふとした隙間時間にいつでも作業できる

といった点が理由です。

(関連して、近いアプローチでとても共感した記事 -> AIによる開発高速化で作り出した時間は新機能開発でなくユーザー理解に使おう)。

そこで、これをさらに効率的に回すための仕組み作りとして、以下の取り組みを試しています。

  • 改善したい点を見つけたら、即座に Claude Code に調査・タスクチケットの発行をやってもらう
  • いつ誰が取り組んでも良いタスク、という意味合いで、Good First Issue ラベルをつけておく (本来の意味とはちょっと違うけど)

これにより、従来は塩漬けになっていたような細かいタスクが拾われる機会がかなり増えてきています。

本記事では、Claude Code の導入によって生じたチームの変化や、利用する上で工夫している点についてご紹介しました。

利用する中で改めて感じているのは、AI エージェントに活躍してもらうには、人間側で適切なレールを敷いてあげることが不可欠だということです。正直なところ、導入当初は「自分で開発したほうが早いな」と思うことも多くありました。しかし、言語化・文書化・自動化などの価値を改めて見直し、仕組みを整備していったことで、任せられるタスクの範囲がグッと広がり、結果的に Claude Code 導入以前よりも開発速度が上がっているのを感じています。

また、レールを敷いてあげる作業は AI エージェントを助けると同時に、開発フローそのものを見直し、情報の可視性を向上させたり、作業の自動化を推進したりする良いきっかけにもなっています。

今後も継続的に改善活動を行い、成果があれば発信も行っていきますので、その際はよろしくお願いいたします!

それでは、最後までお読みいただきありがとうございました。本記事の事例が少しでも皆様の参考になれば幸いです。



Source link

Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -