Confluence

コラボレーションナレッジマネジメントWikiドキュメント管理Atlassianチーム作業

コラボレーションツール

Confluence

概要

Confluenceは、Atlassian開発のチーム向けコラボレーション・ナレッジマネジメントツールです。企業向けの階層的な情報整理、強力なアクセス制御、豊富な統合機能を提供し、3,000以上のアプリ連携が可能。大企業での標準的なナレッジマネジメントツールとして、Jiraとの統合によりDevOpsワークフローに最適化されています。管理者機能とスケーラビリティで企業向け市場をリードし、チームのドキュメント作成、プロジェクト管理、情報共有を包括的にサポートします。

詳細

Confluence 2025年版は、企業レベルのコラボレーションとナレッジマネジメントにおける決定版ツールとしての地位を確立しています。Atlassianエコシステムの中核として、Jira Software、Bitbucket、Trelloとの密接な統合により、開発チームから経営陣まで全社的な情報管理プラットフォームを提供。豊富なページテンプレート、リアルタイム共同編集、高度な検索機能、カスタムマクロ、レポート機能により、技術文書、プロジェクト計画、会議議事録、ナレッジベースを効率的に管理できます。REST API v2による外部システム連携、SAML SSO、高度な権限管理により、セキュリティと統合性を両立。クラウド版では最新のUI/UXとAI機能を導入し、モダンなワークスペース体験を実現しています。

主な特徴

  • 階層的ページ構造: スペース、ページ、サブページによる体系的な情報整理
  • リアルタイム共同編集: 複数メンバーによる同時編集とコメント機能
  • 豊富なテンプレート: プロジェクト計画、会議議事録、技術仕様書等のテンプレート
  • 強力な検索機能: ページ内容、コメント、添付ファイルの包括的検索
  • アプリマーケットプレイス: 3,000以上のサードパーティアプリ連携
  • 高度な権限管理: スペース、ページ、コンテンツレベルの細かな権限設定

メリット・デメリット

メリット

  • Atlassianエコシステムとの完璧な統合によるワークフロー効率化
  • 企業レベルのセキュリティとコンプライアンス機能(SOC2、GDPR対応)
  • 豊富なテンプレートと業界ベストプラクティスの実装
  • 強力なレポート機能とアナリティクスによる利用状況可視化
  • 大規模組織対応のスケーラビリティと安定性
  • 24/7サポートと充実したドキュメント・トレーニング
  • REST APIによる柔軟なシステム統合とカスタマイズ
  • 継続的な機能追加とセキュリティアップデート

デメリット

  • 高額な利用料金(中小企業には負担が大きい)
  • 複雑なUI設定で初期導入時の学習コストが高い
  • Atlassianエコシステム外のツールとの統合制限
  • オンプレミス版のサポート終了(2024年2月)によるクラウド移行必要
  • カスタマイズにはマーケットプレイスアプリが必要で追加コスト発生
  • 大量データ時の検索パフォーマンス低下
  • 過度に複雑な権限設定による運用負荷増加

参考ページ

書き方の例

基本設定とスペース作成

# Confluence Cloudへのアクセス設定
# 1. Atlassianアカウント作成: https://id.atlassian.com
# 2. APIトークン生成: https://id.atlassian.com/manage-profile/security/api-tokens
# 3. 管理権限の確認: 組織管理者から権限付与

# 基本的なスペース構成例
チーム名スペース/
├── プロジェクト管理/
│   ├── プロジェクト計画
│   ├── 進捗レポート
│   └── 完了報告
├── 技術文書/
│   ├── API仕様書
│   ├── アーキテクチャ設計
│   └── 運用手順書
└── 会議記録/
    ├── 週次ミーティング
    ├── 月次レビュー
    └── 意思決定記録

REST API基本操作

import requests
from requests.auth import HTTPBasicAuth
import json

# Confluence REST API設定
CONFLUENCE_URL = "https://your-domain.atlassian.net"
API_TOKEN = "your-api-token"
EMAIL = "[email protected]"

class ConfluenceAPI:
    def __init__(self, base_url, email, api_token):
        self.base_url = base_url.rstrip('/')
        self.session = requests.Session()
        self.session.auth = HTTPBasicAuth(email, api_token)
        self.session.headers.update({
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        })
    
    def get_spaces(self):
        """スペース一覧取得"""
        url = f"{self.base_url}/rest/api/space"
        response = self.session.get(url)
        response.raise_for_status()
        return response.json()
    
    def get_page(self, page_id, expand="body.storage,version"):
        """ページ情報取得"""
        url = f"{self.base_url}/rest/api/content/{page_id}"
        params = {"expand": expand}
        response = self.session.get(url, params=params)
        response.raise_for_status()
        return response.json()
    
    def create_page(self, space_key, title, content, parent_id=None):
        """新規ページ作成"""
        url = f"{self.base_url}/rest/api/content"
        
        page_data = {
            "type": "page",
            "title": title,
            "space": {"key": space_key},
            "body": {
                "storage": {
                    "value": content,
                    "representation": "storage"
                }
            }
        }
        
        if parent_id:
            page_data["ancestors"] = [{"id": parent_id}]
        
        response = self.session.post(url, data=json.dumps(page_data))
        response.raise_for_status()
        return response.json()
    
    def update_page(self, page_id, title, content, version_number):
        """ページ更新"""
        url = f"{self.base_url}/rest/api/content/{page_id}"
        
        page_data = {
            "id": page_id,
            "type": "page",
            "title": title,
            "body": {
                "storage": {
                    "value": content,
                    "representation": "storage"
                }
            },
            "version": {
                "number": version_number + 1
            }
        }
        
        response = self.session.put(url, data=json.dumps(page_data))
        response.raise_for_status()
        return response.json()
    
    def search_content(self, query, type="page"):
        """コンテンツ検索"""
        url = f"{self.base_url}/rest/api/search"
        params = {
            "cql": f"type={type} and text ~ \"{query}\"",
            "expand": "content.body.storage"
        }
        response = self.session.get(url, params=params)
        response.raise_for_status()
        return response.json()

# 使用例
confluence = ConfluenceAPI(CONFLUENCE_URL, EMAIL, API_TOKEN)

# スペース一覧表示
spaces = confluence.get_spaces()
for space in spaces['results']:
    print(f"スペース: {space['name']} (key: {space['key']})")

# 新規ページ作成
page_content = """
<h1>プロジェクトキックオフ</h1>
<h2>目的</h2>
<p>新プロジェクトの開始に向けた準備と役割分担を明確化する</p>

<h2>参加者</h2>
<ul>
<li>プロジェクトマネージャー: 田中</li>
<li>開発リーダー: 佐藤</li>
<li>デザイナー: 鈴木</li>
</ul>

<h2>スケジュール</h2>
<table>
<tr><th>フェーズ</th><th>期間</th><th>担当</th></tr>
<tr><td>設計</td><td>2週間</td><td>佐藤</td></tr>
<tr><td>実装</td><td>4週間</td><td>開発チーム</td></tr>
<tr><td>テスト</td><td>1週間</td><td>QAチーム</td></tr>
</table>
"""

new_page = confluence.create_page(
    space_key="DEV",
    title="プロジェクトキックオフ 2025-01-01",
    content=page_content
)
print(f"新規ページ作成: {new_page['_links']['webui']}")

ページテンプレートとマクロ活用

<!-- プロジェクト計画テンプレート -->
<ac:structured-macro ac:name="info">
<ac:parameter ac:name="title">プロジェクト基本情報</ac:parameter>
<ac:rich-text-body>
<table>
<tr><th>項目</th><th>内容</th></tr>
<tr><td>プロジェクト名</td><td>[プロジェクト名を入力]</td></tr>
<tr><td>開始日</td><td><time datetime="2025-01-01" /></td></tr>
<tr><td>完了予定日</td><td><time datetime="2025-03-31" /></td></tr>
<tr><td>予算</td><td>[予算を入力]</td></tr>
</table>
</ac:rich-text-body>
</ac:structured-macro>

<!-- ステータスマクロ -->
<h2>プロジェクトステータス</h2>
<ac:structured-macro ac:name="status">
<ac:parameter ac:name="colour">Green</ac:parameter>
<ac:parameter ac:name="title">進行中</ac:parameter>
</ac:structured-macro>

<!-- タスクリスト -->
<h2>タスクリスト</h2>
<ac:task-list>
<ac:task>
<ac:task-id>1</ac:task-id>
<ac:task-status>incomplete</ac:task-status>
<ac:task-body>要件定義書の作成</ac:task-body>
</ac:task>
<ac:task>
<ac:task-id>2</ac:task-id>
<ac:task-status>complete</ac:task-status>
<ac:task-body>チーム編成</ac:task-body>
</ac:task>
</ac:task-list>

<!-- Jira Issues マクロ -->
<ac:structured-macro ac:name="jira">
<ac:parameter ac:name="server">https://your-domain.atlassian.net</ac:parameter>
<ac:parameter ac:name="jqlQuery">project = "MYPROJECT" AND status != Done</ac:parameter>
<ac:parameter ac:name="columns">key,summary,type,status,assignee</ac:parameter>
</ac:structured-macro>

<!-- チームメンバー情報 -->
<h2>チームメンバー</h2>
<ac:structured-macro ac:name="user-profile">
<ac:parameter ac:name="user">@tanaka</ac:parameter>
</ac:structured-macro>

<!-- 会議議事録テンプレート -->
<h1>週次ミーティング議事録</h1>
<ac:structured-macro ac:name="info">
<ac:parameter ac:name="title">ミーティング情報</ac:parameter>
<ac:rich-text-body>
<p><strong>日時:</strong> <time datetime="2025-01-08T10:00" /></p>
<p><strong>場所:</strong> 会議室A / Zoom</p>
<p><strong>司会:</strong> @moderator</p>
<p><strong>書記:</strong> @secretary</p>
</ac:rich-text-body>
</ac:structured-macro>

<h2>参加者</h2>
<ul>
<li><ac:link><ri:user ri:account-id="user1" /></ac:link></li>
<li><ac:link><ri:user ri:account-id="user2" /></ac:link></li>
</ul>

<h2>議事内容</h2>
<h3>前回アクションアイテムの確認</h3>
<!-- 前回の未完了アイテムを参照 -->
<ac:structured-macro ac:name="excerpt-include">
<ac:parameter ac:name="nopanel">true</ac:parameter>
<ac:parameter ac:name="">前回ミーティング</ac:parameter>
</ac:structured-macro>

<h3>今回の議題</h3>
<ol>
<li>プロジェクト進捗確認</li>
<li>課題と対策検討</li>
<li>次期計画の検討</li>
</ol>

<h2>決定事項</h2>
<ac:structured-macro ac:name="tip">
<ac:rich-text-body>
<ul>
<li>決定事項1</li>
<li>決定事項2</li>
</ul>
</ac:rich-text-body>
</ac:structured-macro>

<h2>アクションアイテム</h2>
<table>
<tr><th>アクション</th><th>担当者</th><th>期限</th><th>ステータス</th></tr>
<tr>
<td>タスク1の実行</td>
<td><ac:link><ri:user ri:account-id="user1" /></ac:link></td>
<td><time datetime="2025-01-15" /></td>
<td><ac:structured-macro ac:name="status">
<ac:parameter ac:name="colour">Blue</ac:parameter>
<ac:parameter ac:name="title">新規</ac:parameter>
</ac:structured-macro></td>
</tr>
</table>

権限管理とワークフロー設定

# Confluence権限管理API
class ConfluencePermissions:
    def __init__(self, confluence_api):
        self.api = confluence_api
    
    def get_space_permissions(self, space_key):
        """スペース権限取得"""
        url = f"{self.api.base_url}/rest/api/space/{space_key}/permission"
        response = self.api.session.get(url)
        response.raise_for_status()
        return response.json()
    
    def add_space_permission(self, space_key, user_key, permission_type):
        """スペース権限追加"""
        url = f"{self.api.base_url}/rest/api/space/{space_key}/permission"
        
        permission_data = {
            "subject": {
                "type": "user",
                "identifier": user_key
            },
            "operation": {
                "operation": permission_type,  # "read", "administer", etc.
                "targetType": "space"
            }
        }
        
        response = self.api.session.post(url, data=json.dumps(permission_data))
        response.raise_for_status()
        return response.json()
    
    def add_page_restriction(self, page_id, restrictions):
        """ページアクセス制限追加"""
        url = f"{self.api.base_url}/rest/api/content/{page_id}/restriction"
        
        restriction_data = {
            "restrictions": restrictions
        }
        
        response = self.api.session.post(url, data=json.dumps(restriction_data))
        response.raise_for_status()
        return response.json()

# 使用例:階層的権限設定
permissions = ConfluencePermissions(confluence)

# 技術文書スペースの権限設定
space_permissions = permissions.get_space_permissions("TECH")

# 新規メンバーに読み取り権限を付与
permissions.add_space_permission(
    space_key="TECH",
    user_key="[email protected]",
    permission_type="read"
)

# 機密ページに制限を設定
sensitive_page_restrictions = [
    {
        "operation": "read",
        "restrictions": {
            "user": [
                {"type": "known", "username": "[email protected]"},
                {"type": "known", "username": "[email protected]"}
            ]
        }
    }
]

permissions.add_page_restriction("123456", sensitive_page_restrictions)

自動化とCI/CD統合

# CI/CDパイプラインとの統合例
import os
from datetime import datetime

class ConfluenceAutomation:
    def __init__(self, confluence_api):
        self.api = confluence_api
    
    def create_release_notes(self, version, changelog, jira_issues):
        """リリースノート自動生成"""
        
        # JiraチケットのリンクHTML生成
        jira_links = []
        for issue in jira_issues:
            jira_links.append(f'<ac:structured-macro ac:name="jira">
<ac:parameter ac:name="key">{issue}</ac:parameter>
</ac:structured-macro>')
        
        content = f"""
        <h1>リリースノート v{version}</h1>
        <p><strong>リリース日:</strong> {datetime.now().strftime('%Y-%m-%d')}</p>
        
        <h2>新機能・改善</h2>
        <ac:structured-macro ac:name="info">
        <ac:rich-text-body>
        {changelog}
        </ac:rich-text-body>
        </ac:structured-macro>
        
        <h2>修正された問題</h2>
        {''.join(jira_links)}
        
        <h2>既知の問題</h2>
        <ac:structured-macro ac:name="warning">
        <ac:parameter ac:name="title">注意事項</ac:parameter>
        <ac:rich-text-body>
        <p>現在調査中の問題については、Jiraでトラッキングしています。</p>
        </ac:rich-text-body>
        </ac:structured-macro>
        """
        
        return self.api.create_page(
            space_key="RELEASE",
            title=f"リリースノート v{version}",
            content=content
        )
    
    def update_api_documentation(self, openapi_spec):
        """API仕様書自動更新"""
        content = f"""
        <h1>API仕様書</h1>
        <p><strong>更新日:</strong> {datetime.now().strftime('%Y-%m-%d %H:%M')}</p>
        
        <ac:structured-macro ac:name="code">
        <ac:parameter ac:name="language">yaml</ac:parameter>
        <ac:parameter ac:name="title">OpenAPI Specification</ac:parameter>
        <ac:rich-text-body>
        <![CDATA[{openapi_spec}]]>
        </ac:rich-text-body>
        </ac:structured-macro>
        """
        
        # 既存API仕様書ページを検索
        search_results = self.api.search_content("API仕様書")
        
        if search_results['results']:
            # 既存ページを更新
            page = search_results['results'][0]
            page_id = page['content']['id']
            current_version = page['content']['version']['number']
            
            return self.api.update_page(
                page_id=page_id,
                title="API仕様書",
                content=content,
                version_number=current_version
            )
        else:
            # 新規ページ作成
            return self.api.create_page(
                space_key="DEV",
                title="API仕様書",
                content=content
            )

# GitHub Actions / GitLab CI での使用例
def main():
    # 環境変数からConfluence設定を取得
    confluence_url = os.getenv('CONFLUENCE_URL')
    email = os.getenv('CONFLUENCE_EMAIL')
    api_token = os.getenv('CONFLUENCE_API_TOKEN')
    
    confluence = ConfluenceAPI(confluence_url, email, api_token)
    automation = ConfluenceAutomation(confluence)
    
    # Git情報からリリースノート生成
    version = os.getenv('RELEASE_VERSION', '1.0.0')
    changelog = os.getenv('CHANGELOG', '機能改善とバグ修正')
    jira_issues = os.getenv('JIRA_ISSUES', '').split(',')
    
    # リリースノート作成
    release_page = automation.create_release_notes(version, changelog, jira_issues)
    print(f"リリースノート作成完了: {release_page['_links']['webui']}")
    
    # API仕様書更新(OpenAPIファイルがある場合)
    if os.path.exists('openapi.yaml'):
        with open('openapi.yaml', 'r', encoding='utf-8') as f:
            openapi_spec = f.read()
        
        api_page = automation.update_api_documentation(openapi_spec)
        print(f"API仕様書更新完了: {api_page.get('_links', {}).get('webui', 'N/A')}")

if __name__ == "__main__":
    main()

Advanced活用法とカスタムマクロ

// Confluence カスタムマクロ開発例(Atlassian Connect)
// atlassian-connect.json設定例
{
  "name": "Custom Dashboard Macro",
  "description": "カスタムダッシュボードマクロ",
  "key": "custom-dashboard",
  "baseUrl": "https://your-app.example.com",
  "vendor": {
    "name": "Your Company",
    "url": "https://yourcompany.com"
  },
  "authentication": {
    "type": "jwt"
  },
  "scopes": ["read", "write"],
  "modules": {
    "staticContentMacros": [
      {
        "url": "/dashboard",
        "description": {
          "value": "プロジェクトダッシュボード表示"
        },
        "name": {
          "value": "Dashboard"
        },
        "key": "dashboard-macro",
        "bodyType": "none",
        "outputType": "block",
        "featured": true,
        "categories": ["reporting"],
        "parameters": [
          {
            "identifier": "project",
            "name": {
              "value": "プロジェクト"
            },
            "type": "string",
            "required": true
          }
        ]
      }
    ]
  },
  "apiVersion": 1,
  "lifecycle": {
    "installed": "/installed",
    "uninstalled": "/uninstalled"
  }
}

// マクロレンダリングのNode.js実装例
const express = require('express');
const atlassianJwt = require('atlassian-jwt');

const app = express();

app.get('/dashboard', (req, res) => {
  // JWTトークン検証
  const token = req.query.jwt;
  const decoded = atlassianJwt.decode(token, process.env.CLIENT_SECRET);
  
  // プロジェクトパラメータ取得
  const projectKey = req.query.project;
  
  // ダッシュボードHTML生成
  const dashboardHtml = `
    <div style="border: 1px solid #ddd; padding: 15px; border-radius: 5px;">
      <h3>プロジェクト: ${projectKey}</h3>
      <div style="display: flex; justify-content: space-between;">
        <div class="metric">
          <h4>完了タスク</h4>
          <span style="font-size: 24px; color: green;">85%</span>
        </div>
        <div class="metric">
          <h4>残り日数</h4>
          <span style="font-size: 24px; color: orange;">12日</span>
        </div>
        <div class="metric">
          <h4>チーム効率</h4>
          <span style="font-size: 24px; color: blue;">92%</span>
        </div>
      </div>
      <div style="margin-top: 15px;">
        <canvas id="progress-chart" width="400" height="200"></canvas>
      </div>
    </div>
    <script>
      // Chart.js等でグラフ描画
    </script>
  `;
  
  res.send(dashboardHtml);
});