戻る
ITトレンド

AIペアプログラミングで始めるTo-Doアプリ開発:初心者が知るべきメリットとリスク

2025/10/16
AIペアプログラミングで始めるTo-Doアプリ開発:初心者が知るべきメリットとリスク

1. AIペアプログラミングとは?Cursor AIやClaude Codeの登場

近年、AIペアプログラミングという新しい開発手法が注目を集めています。Cursor AIやClaude Code、GitHub Copilotなどのツールを使えば、プログラミング初心者でも驚くほど簡単にアプリケーションを作成できるようになりました。

AIペアプログラミングの仕組み

AIペアプログラミングツールは、自然言語での指示(プロンプト)を受け取り、それに応じたソースコードを自動生成します。まるで経験豊富なエンジニアが隣に座ってサポートしてくれるかのような体験ができます。

主要なツール:

  • Cursor AI:VSCodeベースのAIエディタ
  • Claude Code:Anthropic社のClaude AIを活用した開発ツール
  • GitHub Copilot:GitHub製のコード補完AI

社内で突然「アプリを作って」と命じられた非エンジニアの方でも、これらのツールがあれば開発を始められます。


2. To-Doアプリを作ってみよう:実践プロンプト例

それでは実際に、AIを使ってシンプルなTo-Doアプリを作成してみましょう。

基本的なプロンプト例

シンプルなTo-Doリストアプリを作成してください。
以下の機能が必要です:

【必須機能】
- タスクの追加
- タスクの完了チェック
- タスクの削除
- ローカルストレージでのデータ保存

【技術仕様】
- HTML、CSS、JavaScriptのみで実装
- フレームワークは使用しない
- レスポンシブデザイン対応
- シンプルで見やすいUI

【デザイン要件】
- 明るく清潔感のある配色
- モダンなフラットデザイン
- スマートフォンでも使いやすいサイズ感

より詳細なプロンプト例

To-Doリストアプリケーションを作成してください。

【機能要件】
1. タスク管理
   - 新規タスクの追加(テキスト入力)
   - タスクの完了/未完了の切り替え
   - タスクの削除
   - タスクの編集機能

2. フィルター機能
   - すべてのタスク表示
   - 未完了タスクのみ表示
   - 完了済みタスクのみ表示

3. データ永続化
   - ブラウザのローカルストレージに保存
   - ページリロード後もデータが残る

【技術スタック】
- Pure JavaScript(フレームワーク不使用)
- CSS3(FlexboxまたはGrid使用)
- HTML5

【UI/UX要件】
- タスク追加はEnterキーでも可能
- 完了タスクには取り消し線
- ホバー時のインタラクション
- タスクがない場合の空状態表示

【コード品質】
- 関数は単一責任の原則に従う
- 変数名は分かりやすく命名
- コメントで主要な処理を説明

3. 生成されたソースコードの事例

上記のプロンプトをAIに入力すると、以下のようなコードが生成されます。

HTML構造(index.html)

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>シンプルTo-Doリスト</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="container">
        <h1>📝 My To-Do List</h1>
        
        <!-- タスク入力エリア -->
        <div class="input-area">
            <input type="text" id="taskInput" placeholder="新しいタスクを入力...">
            <button id="addBtn">追加</button>
        </div>

        <!-- フィルターボタン -->
        <div class="filter-buttons">
            <button class="filter-btn active" data-filter="all">すべて</button>
            <button class="filter-btn" data-filter="active">未完了</button>
            <button class="filter-btn" data-filter="completed">完了済み</button>
        </div>

        <!-- タスクリスト -->
        <ul id="taskList"></ul>

        <!-- 空状態 -->
        <div id="emptyState" class="empty-state">
            <p>タスクがありません</p>
        </div>
    </div>

    <script src="script.js"></script>
</body>
</html>

JavaScript実装(script.js)

// タスクデータを管理
let tasks = JSON.parse(localStorage.getItem('tasks')) || [];
let currentFilter = 'all';

// DOM要素の取得
const taskInput = document.getElementById('taskInput');
const addBtn = document.getElementById('addBtn');
const taskList = document.getElementById('taskList');
const filterBtns = document.querySelectorAll('.filter-btn');
const emptyState = document.getElementById('emptyState');

// 初期化
document.addEventListener('DOMContentLoaded', () => {
    renderTasks();
});

// タスク追加
addBtn.addEventListener('click', addTask);
taskInput.addEventListener('keypress', (e) => {
    if (e.key === 'Enter') addTask();
});

function addTask() {
    const text = taskInput.value.trim();
    if (text === '') return;

    const task = {
        id: Date.now(),
        text: text,
        completed: false,
        createdAt: new Date().toISOString()
    };

    tasks.unshift(task);
    saveTasks();
    renderTasks();
    taskInput.value = '';
}

// タスク削除
function deleteTask(id) {
    tasks = tasks.filter(task => task.id !== id);
    saveTasks();
    renderTasks();
}

// タスク完了切り替え
function toggleTask(id) {
    const task = tasks.find(t => t.id === id);
    if (task) {
        task.completed = !task.completed;
        saveTasks();
        renderTasks();
    }
}

// フィルター切り替え
filterBtns.forEach(btn => {
    btn.addEventListener('click', () => {
        filterBtns.forEach(b => b.classList.remove('active'));
        btn.classList.add('active');
        currentFilter = btn.dataset.filter;
        renderTasks();
    });
});

// タスク描画
function renderTasks() {
    const filteredTasks = getFilteredTasks();
    
    if (filteredTasks.length === 0) {
        taskList.style.display = 'none';
        emptyState.style.display = 'block';
        return;
    }

    taskList.style.display = 'block';
    emptyState.style.display = 'none';

    taskList.innerHTML = filteredTasks.map(task => `
        
            
            ${escapeHtml(task.text)}
            削除
        
    `).join('');
}

// フィルタリング
function getFilteredTasks() {
    switch(currentFilter) {
        case 'active':
            return tasks.filter(t => !t.completed);
        case 'completed':
            return tasks.filter(t => t.completed);
        default:
            return tasks;
    }
}

// ローカルストレージ保存
function saveTasks() {
    localStorage.setItem('tasks', JSON.stringify(tasks));
}

// XSS対策
function escapeHtml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
}

スタイル(style.css)

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    min-height: 100vh;
    padding: 20px;
}

.container {
    max-width: 600px;
    margin: 0 auto;
    background: white;
    border-radius: 16px;
    padding: 32px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.3);
}

h1 {
    text-align: center;
    color: #333;
    margin-bottom: 24px;
    font-size: 28px;
}

.input-area {
    display: flex;
    gap: 8px;
    margin-bottom: 20px;
}

#taskInput {
    flex: 1;
    padding: 12px 16px;
    border: 2px solid #e0e0e0;
    border-radius: 8px;
    font-size: 16px;
    transition: border-color 0.3s;
}

#taskInput:focus {
    outline: none;
    border-color: #667eea;
}

#addBtn {
    padding: 12px 24px;
    background: #667eea;
    color: white;
    border: none;
    border-radius: 8px;
    font-size: 16px;
    cursor: pointer;
    transition: background 0.3s;
}

#addBtn:hover {
    background: #5568d3;
}

.filter-buttons {
    display: flex;
    gap: 8px;
    margin-bottom: 20px;
}

.filter-btn {
    flex: 1;
    padding: 8px 16px;
    background: #f5f5f5;
    border: 2px solid #e0e0e0;
    border-radius: 8px;
    cursor: pointer;
    transition: all 0.3s;
}

.filter-btn.active {
    background: #667eea;
    color: white;
    border-color: #667eea;
}

#taskList {
    list-style: none;
}

.task-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px;
    background: #f9f9f9;
    border-radius: 8px;
    margin-bottom: 8px;
    transition: all 0.3s;
}

.task-item:hover {
    background: #f0f0f0;
    transform: translateX(4px);
}

.task-item.completed .task-text {
    text-decoration: line-through;
    color: #999;
}

.task-text {
    flex: 1;
    font-size: 16px;
}

.delete-btn {
    padding: 6px 12px;
    background: #ff4757;
    color: white;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.3s;
}

.delete-btn:hover {
    background: #e84118;
}

.empty-state {
    display: none;
    text-align: center;
    padding: 40px;
    color: #999;
}

@media (max-width: 600px) {
    .container {
        padding: 20px;
    }
    
    h1 {
        font-size: 24px;
    }
}

コードの特徴

  • シンプルな構造:フレームワーク不使用で理解しやすい
  • データ永続化:LocalStorageでブラウザに保存
  • レスポンシブ対応:スマホでも快適に使える
  • XSS対策:入力値をエスケープ処理

4. アプリの公開方法:デプロイまでの流れ

作成したTo-Doアプリを実際にインターネット上で公開する方法を紹介します。

方法1:GitHub Pagesで無料公開

手順:

  1. GitHubアカウント作成

  2. リポジトリ作成

    • 「New repository」をクリック
    • リポジトリ名:todo-app(任意)
    • Public を選択
  3. ファイルをアップロード

    • index.htmlstyle.cssscript.js をアップロード
  4. GitHub Pages有効化

    • Settings → Pages
    • Source: Deploy from a branch
    • Branch: main → Save
  5. 公開完了

    • 数分後、https://ユーザー名.github.io/todo-app/ でアクセス可能

方法2:Netlifyでワンクリックデプロイ

手順:

  1. Netlifyアカウント作成

  2. ドラッグ&ドロップでデプロイ

    • ファイル3つをフォルダにまとめる
    • Netlify Drop にドラッグ&ドロップ
  3. 即座に公開

    • 自動的にURLが発行される
    • 独自ドメインも設定可能

方法3:Vercelで高速デプロイ

特徴:

  • Next.jsやReactアプリに最適
  • 自動ビルド&デプロイ
  • 無料プランでも高性能

手順:

  1. GitHubと連携
  2. リポジトリを選択
  3. 自動デプロイ開始

5. 仕様書なき開発の落とし穴:バイブコーディングのリスク

AIペアプログラミングは非常に便利ですが、重大なリスクがあることを理解しておく必要があります。

リスク1:仕様の曖昧さによる機能不全

問題点:

  • プロンプトだけでは詳細な仕様が伝わらない
  • 「タスク管理アプリ」と言っても、求める機能は人それぞれ
  • 改修を重ねるうちに、当初の目的と異なるシステムになる

具体例:

最初の要望:「シンプルなTo-Doアプリ」
↓ 改修1:「期限機能を追加して」
↓ 改修2:「カテゴリー分けできるようにして」
↓ 改修3:「共有機能も欲しい」
↓ 結果:複雑で保守不可能なコードに

リスク2:セキュリティの脆弱性

AIが生成したコードには、セキュリティ上の問題が潜んでいることがあります。

よくある脆弱性:

  1. XSS(クロスサイトスクリプティング)

    • ユーザー入力をそのまま表示
    • 悪意あるスクリプトの実行リスク
  2. 認証・認可の不備

    • パスワードの平文保存
    • セッション管理の不適切な実装
  3. SQLインジェクション

    • データベース操作の脆弱性
    • 情報漏洩のリスク
  4. APIキーの露出

    • GitHubに秘密鍵をコミット
    • フロントエンドに認証情報を埋め込み

リスク3:技術的負債の蓄積

問題点:

  • コードの構造が一貫しない
  • テストコードがない
  • ドキュメントがない
  • 他の開発者が理解できない

結果:

  • バグ修正に膨大な時間がかかる
  • 機能追加が困難になる
  • 最終的にフルリライトが必要に

リスク4:スケーラビリティの欠如

問題点:

  • 小規模では動くが、大規模では破綻
  • パフォーマンス問題が後から発覚
  • データ量増加に耐えられない設計

具体例:

  • To-Doが1000件になるとブラウザがフリーズ
  • 同時アクセスが増えるとサーバーダウン
  • データベース設計が不適切で検索が遅い

6. MVP開発と仕様駆動開発:プロに任せるべき理由

AIツールでプロトタイプを作ることはできますが、本格的なシステム開発には専門知識が必要です。

当社の強み:MVP開発

MVP(Minimum Viable Product)とは?

  • 最小限の機能で市場検証を行うプロダクト
  • 素早くリリースし、ユーザーの反応を見る
  • 無駄な機能開発を避け、コストを最適化

当社のMVP開発プロセス:

  1. 要件ヒアリング

    • ビジネス目標の明確化
    • ターゲットユーザーの特定
    • 必須機能と優先順位の決定
  2. 仕様設計

    • 画面設計・UI/UX設計
    • データベース設計
    • システムアーキテクチャ設計
  3. 迅速な開発

    • AIツールも活用した効率的な実装
    • ただし、コードレビューと品質管理は徹底
    • セキュリティチェック実施
  4. テスト&リリース

    • 自動テストの実装
    • 本番環境へのデプロイ
    • モニタリング体制の構築

当社の強み:仕様駆動開発

仕様駆動開発とは?

  • 明確な仕様書をベースに開発を進める手法
  • 後戻りを防ぎ、開発コストを削減
  • 保守性・拡張性の高いシステムを実現

仕様書の重要性:

項目仕様書あり仕様書なし(バイブコーディング)
開発の方向性ブレない都度変わる
バグの発見早期発見後から発覚
改修コスト低い高い
セキュリティ設計段階で対策後付けで対応
引き継ぎスムーズ困難

当社が作成する仕様書:

  • 要件定義書
  • 機能仕様書
  • 画面設計書
  • データベース設計書
  • API仕様書
  • セキュリティ要件書

なぜプロに任せるべきか?

1. セキュリティの確保

  • OWASP Top 10 対策
  • 個人情報保護法への対応
  • 脆弱性診断の実施

2. スケーラビリティの実現

  • 将来の成長を見据えた設計
  • パフォーマンス最適化
  • クラウドインフラの適切な選定

3. 保守性の高いコード

  • コーディング規約の遵守
  • 自動テストの整備
  • 継続的インテグレーション(CI/CD)

4. 法的リスクの回避

  • ライセンス管理
  • 著作権の確認
  • 契約書・利用規約の整備

5. コストの最適化

  • 技術的負債を生まない設計
  • 長期的な運用コストの削減
  • 無駄な作り直しを防ぐ

まとめ:AIツールとプロの開発の使い分け

AIペアプログラミングが向いているケース

✅ 個人的な学習・スキルアップ
✅ 社内ツールのプロトタイプ作成
✅ 小規模な静的サイト
✅ 概念実証(PoC)

プロに依頼すべきケース

✅ 顧客情報を扱うシステム
✅ 金銭取引が発生するサービス
✅ 複数人で利用する業務システム
✅ 長期運用が前提のサービス
✅ セキュリティが重要なシステム


当社にご相談ください

「AIで作ってみたけれど、このままで大丈夫?」
「プロトタイプはできたけど、本番環境にするには?」
「セキュリティが心配…」

そんな不安をお持ちの方は、ぜひ当社にご相談ください。

当社のサービス

  • MVP開発支援:アイデアを素早く形にします
  • 仕様駆動開発:明確な設計でブレない開発
  • コードレビュー:既存コードの問題点を洗い出し
  • リファクタリング:保守性の高いコードに改善
  • セキュリティ診断:脆弱性を徹底チェック

相談受付中

まずはお気軽にお問い合わせください。
経験豊富なエンジニアが、あなたのプロジェクトを成功に導きます。

お問い合わせ: お問い合わせはこちら

西村 力也

西村 力也

代表取締役

2002年からWeb制作・システム開発に従事。React、Next.js、TypeScriptを中心としたモダンなフロントエンド開発の専門家。AI検索最適化(AIO)の先駆者として、ChatGPT、Perplexity等のAI検索エンジン対応を推進。三重県津市を拠点に、東海地方の企業様のデジタル変革を支援しています。

React/Next.js開発TypeScriptAI検索最適化(AIO)SEO/MEO対策