Files
brain_dogfood/docs/obsidian_plugin_plan.md
T

12 KiB

뇌사료 ↔ 옵시디언 플러그인 연동 구현 계획

작성일: 2026-04-16
작업 경로: c:\project\my_util\memo_server
서버 주소: your-server-ip:5093
원격 경로: /home/your-username/Script/memo_server


1. 제품 컨셉 (확정)

뇌사료 단독:       웹 기반 빠른 캡처 메모 + AI 태깅/요약
뇌사료 + 옵시디언: 뇌사료(INPUT/캡처) → 옵시디언(PROCESS/정리/아카이브/그래프)

포지셔닝 핵심:

  • 뇌사료는 옵시디언의 "웹 프론트엔드 + AI 레이어" 역할
  • 옵시디언 사용자의 고질적 불편(로컬 파일 기반 → 모바일/웹 접근 어려움)을 해결
  • 뇌사료 → 옵시디언은 단방향 동기화 (뇌사료가 Single Source of Truth)
  • 옵시디언은 읽기/정리 전용 뷰로 사용

2. 현재 아키텍처 현황

2-1. 서버 구조 (Flask + Blueprint)

app/
├── __init__.py          # create_app(), Blueprint 등록, 보안 미들웨어
├── constants.py         # GROUP_DEFAULT="default", GROUP_FILES="files", GROUP_DONE="done"
├── database.py          # SQLite, DB_PATH=data/memos.db
├── auth.py              # @login_required 데코레이터 (세션 기반)
├── security.py          # Fernet 암호화/복호화 (PBKDF2 + ENCRYPTION_SEED)
├── ai.py                # Gemini AI 태깅/요약
└── routes/
    ├── __init__.py      # register_blueprints(app) ← 여기에 새 Blueprint 추가
    ├── memo.py          # /api/memos CRUD
    ├── file.py          # /api/files 업로드/다운로드
    ├── ai.py            # /api/ai
    ├── auth.py          # /login /logout
    ├── settings.py      # /api/settings
    └── main.py          # / 메인 페이지

2-2. DB 스키마 (SQLite: data/memos.db)

memos(
    id, title, content, summary, color,
    is_pinned, status,           -- status: 'active' | 'done'
    group_name,                  -- 'default' | 'files' | 'done' | 사용자 정의
    is_encrypted,                -- 0 | 1
    created_at, updated_at
)
tags(id, memo_id, name, source)          -- source: 'user' | 'ai'
attachments(id, memo_id, filename, original_name, file_type, size, created_at)
memo_links(id, source_id, target_id)    -- 백링크/전방링크

2-3. 현재 인증 방식

  • 세션 기반 (session['logged_in']) — 브라우저 전용
  • API Token 인증 없음 → Phase 1에서 추가 필요

2-4. 암호화 방식

# app/security.py
# PBKDF2(password + ENCRYPTION_SEED) → Fernet 키 → 본문 암호화
# .env의 ENCRYPTION_SEED 필수
encrypt_content(content, password)
decrypt_content(encrypted_data, password)  # 실패 시 None 반환

암호화 메모는 is_encrypted=1, 복호화는 /api/memos/{id}/decrypt POST로 처리.


3. 구현 계획 (3단계)


Phase 1. API Token 인증 추가 (뇌사료 서버)

목적: 세션 없이 외부에서 API를 호출할 수 있도록 Token 인증 추가
원칙: 기존 @login_required 데코레이터를 건드리지 않고 새 데코레이터 추가

1-1. .env에 토큰 추가

# .env (기존 항목 유지, 아래 추가)
OBSIDIAN_API_TOKEN=your_secret_token_here

1-2. app/auth.py에 토큰 인증 데코레이터 추가

def token_required(view):
    """API Token 기반 인증 데코레이터 (Obsidian 플러그인 전용)"""
    @functools.wraps(view)
    def wrapped_view(**kwargs):
        token = request.headers.get('X-API-Token') or request.args.get('token')
        expected = os.getenv('OBSIDIAN_API_TOKEN', '')
        if not expected or token != expected:
            return jsonify({'error': 'Unauthorized'}), 401
        return view(**kwargs)
    return wrapped_view

1-3. 새 Blueprint 파일 생성: app/routes/sync.py

# app/routes/sync.py
# 옵시디언 동기화 전용 Blueprint

sync_bp = Blueprint('sync', __name__)

# GET /api/sync/export
# 전체 메모 목록 반환 (암호화 메모는 플레이스홀더 처리)
# 쿼리파라미터: since=2024-01-01T00:00:00 (증분 동기화용)

# POST /api/sync/decrypt/<id>
# 단일 암호화 메모 복호화 반환
# 헤더: X-Memo-Password: 비밀번호

# GET /api/sync/groups
# 그룹 목록 반환

1-4. app/routes/__init__.py에 Blueprint 등록

from .sync import sync_bp
app.register_blueprint(sync_bp)

완료 기준: curl -H "X-API-Token: xxx" http://서버/api/sync/export 가 JSON 반환


Phase 2. Python 동기화 스크립트 (로컬 실행)

목적: 뇌사료 API를 호출해서 옵시디언 Vault에 .md 파일로 저장
실행 방식: Windows Task Scheduler 또는 cron으로 주기 실행 (5~10분)
위치: 프로젝트 루트의 obsidian_sync/ 폴더

2-1. 파일 구조

obsidian_sync/
├── obsidian_sync.py     # 메인 동기화 스크립트
├── config.json          # 설정 파일
└── last_sync.txt        # 마지막 동기화 시각 저장 (증분 동기화용)

2-2. obsidian_sync/config.json

{
    "server_url": "http://your-server-ip:5093",
    "api_token": "your_secret_token_here",
    "vault_path": "C:/Users/your-username/Documents/ObsidianVault/뇌사료",
    "sync_interval_minutes": 10,
    "encrypted_memo_handling": "placeholder",
    "frontmatter": true,
    "group_to_folder": {
        "default": "inbox",
        "files": "files",
        "done": "archive"
    }
}

2-3. 변환 규칙 (뇌사료 → .md)

뇌사료 필드 옵시디언 변환
title 파일명 + H1 헤더
content 본문 (HTML → Markdown 변환)
tags frontmatter tags: + 본문 #태그
group_name 하위 폴더 분류
backlinks 본문 하단 [[링크제목]]
is_encrypted=1 [🔒 암호화된 메모 — 뇌사료에서 확인]
created_at frontmatter date:
updated_at frontmatter updated:
summary frontmatter summary:

2-4. 생성될 .md 예시

---
id: 42
date: 2026-04-15
updated: 2026-04-16
tags: [python, flask, ai]
source: 뇌사료
group: default
---

# 메모 제목

본문 내용...

---
**Tags:** #python #flask #ai
**Links:** [[관련 메모 제목]]
**Source:** [뇌사료에서 열기](http://your-server-ip:5093)

완료 기준: 스크립트 실행 후 Vault 폴더에 .md 파일 생성 확인


Phase 3. TypeScript 옵시디언 플러그인 (선택적 고도화)

목적: Phase 2가 안정화된 후, 옵시디언 내에서 직접 UI 제공
전제조건: Phase 1, 2 완료 후 진행
개발 언어: TypeScript (옵시디언 플러그인 필수)

3-1. 플러그인 저장소 구조

obsidian-brainsryo-plugin/    # 별도 Git 저장소 권장
├── src/
│   ├── main.ts               # 플러그인 진입점
│   ├── api.ts                # 뇌사료 API 클라이언트
│   ├── converter.ts          # 뇌사료 JSON → Obsidian .md 변환
│   ├── settings.ts           # 플러그인 설정 UI
│   └── modal.ts              # 암호화 메모 비밀번호 입력 모달
├── manifest.json
├── package.json
└── tsconfig.json

3-2. 플러그인 설정 항목 (UI)

뇌사료 서버 URL:  [http://your-server-ip:5093]
API Token:        [***************]
저장 폴더:        [뇌사료/]
동기화 주기:      [10분]
암호화 메모 처리: [플레이스홀더 ▼]  ← 또는 "비밀번호 입력"
자동 동기화:      [ON/OFF]

3-3. 암호화 메모 처리 흐름 (플러그인 버전)

옵시디언에서 암호화 메모 클릭
  → 비밀번호 입력 모달 표시 (Obsidian Modal API)
  → POST /api/sync/decrypt/{id} (헤더: X-Memo-Password)
  → 복호화 성공 시 임시 .md 생성 후 표시
  → 닫으면 임시 파일 삭제 (디스크에 평문 저장 안 함)

3-4. 개발 우선순위

  1. 단방향 동기화 (뇌사료 → 옵시디언) 기본 버전
  2. 설정 UI
  3. 증분 동기화 (마지막 동기화 이후 변경분만)
  4. 암호화 메모 지원 (비밀번호 모달)
  5. (미래) 옵시디언 → 뇌사료 import 기능

4. 구현 순서 체크리스트

Phase 1 — API Token (뇌사료 서버 수정)

  • .envOBSIDIAN_API_TOKEN 추가
  • .env.example에도 항목 추가 (값 없이)
  • app/auth.pytoken_required 데코레이터 추가
  • app/routes/sync.py 파일 생성
    • GET /api/sync/export 엔드포인트 (since 파라미터 지원)
    • POST /api/sync/decrypt/<id> 엔드포인트
    • GET /api/sync/groups 엔드포인트
  • app/routes/__init__.pysync_bp 등록
  • 서버 배포 (python deploy.py — 사용자 승인 필수)

Phase 2 — Python 동기화 스크립트

  • obsidian_sync/ 폴더 생성
  • obsidian_sync/config.json 작성
  • obsidian_sync/obsidian_sync.py 작성
    • API 호출 (Token 인증)
    • HTML → Markdown 변환 (markdownify 라이브러리)
    • frontmatter 생성
    • 태그/백링크 변환
    • 그룹 → 폴더 분류
    • 증분 동기화 (last_sync.txt)
    • 암호화 메모 플레이스홀더 처리
  • 스크립트 테스트 (실제 Vault에 파일 생성 확인)
  • Windows Task Scheduler 등록

Phase 3 — TypeScript 옵시디언 플러그인 (나중에)

  • Node.js 개발 환경 세팅
  • obsidian-sample-plugin 템플릿 클론
  • API 클라이언트 구현
  • 설정 UI 구현
  • 동기화 로직 구현
  • 암호화 메모 모달 구현
  • 로컬 설치 테스트 (.obsidian/plugins/ 복사)

5. API 스펙 (Phase 1에서 구현할 엔드포인트)

GET /api/sync/export

Headers: X-API-Token: {OBSIDIAN_API_TOKEN}
Params:
  - since (optional): ISO 8601 datetime, 이 시각 이후 수정된 메모만 반환
  - limit (optional): 기본 1000
Response:
[
  {
    "id": 42,
    "title": "메모 제목",
    "content": "<p>HTML 본문</p>",
    "summary": "AI 요약",
    "tags": [{"name": "python", "source": "ai"}, ...],
    "group_name": "default",
    "is_encrypted": false,
    "is_pinned": false,
    "backlinks": [{"source_id": 10, "title": "다른 메모"}],
    "links": [{"target_id": 20, "title": "링크된 메모"}],
    "created_at": "2026-04-15T10:00:00",
    "updated_at": "2026-04-16T08:00:00"
  },
  // is_encrypted=true인 경우:
  {
    "id": 99,
    "title": "암호화된 메모",
    "content": null,
    "is_encrypted": true,
    ...
  }
]

POST /api/sync/decrypt/<id>

Headers:
  X-API-Token: {OBSIDIAN_API_TOKEN}
  X-Memo-Password: {메모_비밀번호}
Response (성공): {"content": "복호화된 본문"}
Response (실패): {"error": "Invalid password"}, 403

GET /api/sync/groups

Headers: X-API-Token: {OBSIDIAN_API_TOKEN}
Response: {"groups": ["default", "files", "done", "custom_group1", ...]}

6. 주의사항 및 설계 원칙

단방향 원칙: 뇌사료 → 옵시디언 방향만 동기화. 옵시디언에서 .md를 수정해도 뇌사료 DB에는 반영되지 않음. 양방향 동기화는 충돌 처리 복잡도가 높아 Phase 3 이후 별도 검토.

암호화 메모 보안: 복호화된 본문은 절대 디스크에 저장하지 않음. Phase 2 스크립트는 기본적으로 encrypted_memo_handling: "placeholder" 유지.

파일명 규칙: 옵시디언 파일명 특수문자 금지 (/ \ : * ? " < > |) 뇌사료 제목의 해당 문자는 _로 치환. 중복 시 제목_id42.md 형식.


7. 작업 이어받기 안내 (다른 AI 인스턴스용)

  1. 먼저 읽을 파일들:

    • app/auth.py — 현재 인증 구조 확인
    • app/routes/__init__.py — Blueprint 등록 방식 확인
    • app/routes/memo.py — 기존 API 패턴 참고
    • app/security.py — 암호화/복호화 함수 확인
    • .envOBSIDIAN_API_TOKEN 추가 여부 확인
  2. 시작점: Phase 1 체크리스트 항목 순서대로 진행

  3. 배포 방법: 수정 완료 후 python deploy.py 실행 (반드시 사용자 승인 후 실행 — 사용자 규칙)

  4. 테스트:

    curl -H "X-API-Token: {토큰}" http://your-server-ip:5093/api/sync/export
    
  5. 추가 의존성: pip install markdownify (Phase 2 스크립트에서 필요)