AIエージェントが生み出すありがちなボイラープレートを削ぎ落とす作業環境設定
TuBrief 편집팀
2026년 7월 24일
0
Computing/Software원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
커뮤니티의 다른 글
댓글 (0)
Log in to leave a comment
아직 작성된 글이 없습니다
원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
Log in to leave a comment
아직 작성된 글이 없습니다
AIエージェントを実際の開発環境に導入してみると、すぐに底が見えてしまいます。ドメインの文脈を理解しないまま機械的にファクトリーパターンを乱用したり、全く役に立たないユーティリティ関数ばかりを無限に吐き出したりしがちです。GitClearが2024年に発表した6億2,300万行のコミット分析レポートによると、AIツールの普及後、コードの重複は81%増加し、既存コードを整理するリファクタリングの割合は25%から10%未満へと急落しました。コンテキストウィンドウの最新性バイアス(Recency Bias)により、エージェントはリスクを避けるため、学習データ内で最も一般的な標準パターンへと逃避し続けます。チームで共有するアーキテクチャルールや同期ロジックをコンテキストファイルとして明示し、エージェントの誤作動を抑え込む必要があります。
開発ツールごとにバラバラな指示を統合・管理するには、プロジェクトのルートディレクトリに「唯一の真実のソース(Single Source of Truth)」として機能する AGENTS.md を配置することから始めます。CursorやClaude Codeなどのツールはこのルールを読み込みます。単一の .cursorrules ファイルはすでに遥か昔に廃止されました。.cursor/rules/ ディ렉トリ内にMDCファイルとして分割して配置し、Claude Code環境では CLAUDE.md 内で @AGENTS.md を読み込むことで、ルールが形骸化・漏れ出る現象を防ぎます。
apps/api/src/common/dto.services/shared/uow.`
コンテキストの総量が800行、約2,000トークンを超えると、エージェントは上部に記載された制約条件を無視し始めます。AGENTS.md には絶対に譲れない禁止事項だけを残し、詳細なアーキテクチャ決定記録(ADR)は docs/context/ ディ렉トリへ切り出すべきです。
AGENTS.md を作成し、単一実装インターフェースの禁止や防御的な try-catch の禁止条件を記述します。.cursor/rules/backend-constraints.mdc に対象ファイルパス(globs)と YAML Frontmatter の制約を設定します。CLAUDE.md に @AGENTS.md 構文を追加し、環境を合わせます。一見すると問題なさそうに見えるエージェントのコードの裏には、罠が隠れています。Veracodeの2024年の研究結果によると、AIが提案したコードの45%で OWASP Top 10 レベルのセキュリティ脆弱性が発見されました。失敗しそうなロジックを try-catch で安易に囲み、空のオブジェクトや null を返してエラーを隠蔽する行為は、人間が執筆するときよりも47%も頻繁に発生しています。Read-Modify-Write 操作における楽観的ロックの考慮漏れや、ループ内でのDB呼び出しによる N+1 問題も頻繁に発生します。
| 検証領域 | 詳細検証項目 | リスクパターンおよびエージェントの罠 | マージ遮断基準 |
|---|---|---|---|
| セキュリティ脆弱性 | Parameterized Query(プレースホルダ)の使用有無、テナント分離、未承認パッケージの確認 | 文字列結合による SQL インジェクション、ハルシネーションによって生成された未検証パッケージの呼び出し | 入力値検証の漏れ、出所不明な外部依存関係の追加時に遮断 |
| パフォーマンスボトルネック | ORMの遅延読み込み(Lazy Loading)、Hot path 内の多重ループ、DBインデックス | ループ内での個別にエンティティを巡回するクエリ、メモリ上でのテーブル全体のフィルタリング | ループ内にDBおよび外部API呼び出しが存在する場合に遮断、ページネーション未適用時に遮断 |
| 型安全性 | Strict Type 検証、Boundary(境界)例外処理、排他・コンカレンシー制御 | as any の乱用、Empty Catch ブロックによるエラー隠蔽 |
any および無分別な as キャストが存在する場合に遮断、ロギングのない Catch ブロックを遮断 |
エージェントが生成するテストコードは、実装コードをそのままコピー&ペーストしてなぞるだけの「同義語反復(トートロジー)テスト」になりがちです。このようなテストは、実際のビジネスロジックの欠陥を全く検知できません。「すでに存在するユーティリティがある場合、エージェントが新規作成したユーティリティは削除し、既存コードを再利用する」というルールを強力に適用する必要があります。
any 禁止項目を追加します。as any やループ内の await を検知した場合はコミットを弾くようにします。複雑な決済・精算ロジックやステートマシンベースの注文処理を単一のプロンプトで流し込むと、エージェントはツール呼び出しのループに陥るか、形だけのスカスカなコードしか吐き出さなくなります。スキーマ設計、API インターフェース、例外処理、ビジネスルールを一度に処理しようとして、トークンの割り当て順序が混乱するためです。
`
[ステップ1: データモデリング] -> DBエンティティ、Zodスキーマ生成
│
▼ (出力結果をコンテキストとして伝達)
[ステップ2: インターフェース定義] -> API DTO、Custom Error、サービスシグネチャ定義
│
▼ (ステップ1+2の出力結果をコンテキストとして伝達)
[ステップ3: ビジネスロジック実装] -> トランザクション、状態遷移、コンカレンシー制御の完成
`
このプロセスを手動でやり取りするのは非常に手間がかかります。CLI 自動化スクリプト(scripts/agent-decomposed-build.ts)を作成し、前のステップの出力結果が次のステップの入力コンテキストとして入るように連携させておくのが賢明です。
`typescript
import { execSync } from 'child_process';
import * as fs from 'fs';
interface TaskPipeline {
featureName: string;
stage1Prompt: string;
stage2Prompt: string;
stage3Prompt: string;
}
async function runDecomposedAgentPipeline(pipeline: TaskPipeline) {
console.log([Stage 1] Executing Data Modeling for ${pipeline.featureName}...);
const stage1Output = execSync(claude --print "${pipeline.stage1Prompt}").toString();
fs.writeFileSync(./tmp/${pipeline.featureName}_stage1.ts, stage1Output);
console.log([Stage 2] Executing Interface Definition...);
const stage2InputPrompt = ${pipeline.stage2Prompt}\n\nContext Models:\n${stage1Output};
const stage2Output = execSync(claude --print "${stage2InputPrompt}").toString();
fs.writeFileSync(./tmp/${pipeline.featureName}_stage2.ts, stage2Output);
console.log([Stage 3] Executing Business Logic Implementation...);
const stage3InputPrompt = ${pipeline.stage3Prompt}\n\nContext Models:\n${stage1Output}\n\nContext Contracts:\n${stage2Output};
const stage3Output = execSync(claude --print "${stage3InputPrompt}").toString();
fs.writeFileSync(./src/services/${pipeline.featureName}.service.ts, stage3Output);
console.log([Pipeline Complete] Business logic generated cleanly without cognitive stagnation.);
}
`
scripts/agent-decomposed-build.ts を作成し、前の出力が次のプロンプトのコンテキストに入るよう接続します。AIコーディングツールを使えば使うほど、「なぜこのように実装したのか」という理由が抜け落ちた「書き込み専用コード」が蓄積していきます。アーキテクチャ選択におけるトレードオフが記録されていないコードは、後から人間が手を加える際に大きな負担となります。エージェントがコードを生成する際、TSDoc 標準コメントをソースコード内に記述するよう AGENTS.md で強制する必要があります。
`typescript
/**
`
開発者ごとにエージェントの設定がズレるのを防ぐには、AGENTS.md を唯一の真実のソース(SSOT)として配置し、コミット時に CLAUDE.md や .cursor/rules/global.mdc へ同期するスクリプト(tools/sync-agent-rules.ts)を運用します。
`typescript
import * as fs from 'fs';
import * as path from 'path';
const AGENTS_MD_PATH = path.join(__dirname, '../AGENTS.md');
const CLAUDE_MD_PATH = path.join(__dirname, '../CLAUDE.md');
const CURSOR_RULE_PATH = path.join(__dirname, '../.cursor/rules/global.mdc');
function syncRules() {
if (!fs.existsSync(AGENTS_MD_PATH)) {
console.error('Error: AGENTS.md does not exist.');
process.exit(1);
}
const baseRules = fs.readFileSync(AGENTS_MD_PATH, 'utf-8');
const claudeContent = # AUTOMATICALLY GENERATED FROM AGENTS.md - DO NOT EDIT DIRECTLY\n\n${baseRules};
fs.writeFileSync(CLAUDE_MD_PATH, claudeContent);
const mdcHeader = ---\ndescription: Global Agent Rule Sync\nglobs: **/*\nalwaysApply: true\n---\n\n;
fs.writeFileSync(CURSOR_RULE_PATH, ${mdcHeader}${baseRules});
console.log('Successfully synchronized AGENTS.md to CLAUDE.md and Cursor MDC rules.');
}
syncRules();
`