Repository navigation
Output Format
한국어 | English
세션(대화) 1개당 마크다운 노트 1개가 생성됩니다.
- frontmatter에
title/session_id/url/date/turns_count/content_hash/tags를 담습니다. - 본문은
> [!question]- User (...)/> [!tip]- <Vendor> (...)callout으로 turn을 나열합니다 (Obsidian 표시 형식을 그대로 보존). - 이미지·파일 첨부는
Attachments/로 복사되고 가능하면![[...]]로 임베드됩니다.
각 callout 바로 앞에는 다음과 같은 형태의 HTML 주석이 붙습니다:
<!-- turn: {"turn_index": 0, "role": "user", "parent_turn_index": null, "has_attachment": false} -->Obsidian 미리보기에는 보이지 않지만, RAG 청킹 파이프라인이 callout 문법
([!question] vs [!tip])이나 "다음 질문 직전까지" 같은 순서 휴리스틱 없이 바로 QA
쌍·세션 경계·첨부 맥락을 읽어갈 수 있게 합니다.
-
turn_index: 그 노트 안에서의 turn 순번. -
role:user또는 벤더(assistant) 쪽 role. -
parent_turn_index: 그 답변이 어느 질문(turn_index)에 대한 것인지. 질문 턴은 항상null(새 turn window의 시작). 같은 질문에 답변이 여러 턴으로 나뉘어도(실제로 발생함 — 긴 응답이 메시지 여러 개로 쪼개지는 경우) 전부 같은parent_turn_index를 가리킵니다. -
has_attachment: 그 턴 바로 뒤에 첨부파일 블록이 붙는지 여부.
이 계산은 common/session_markdown.py::build_session_markdown() 한 곳에서, turn
리스트를 role 순서대로 훑으며 벤더 무관하게 이뤄집니다(vendors/chatgpt.py,
vendors/gemini.py는 관여하지 않음).
content_hash는 frontmatter를 제외한 본문(body) 전체를 SHA-256으로 해시한 값입니다.
turn 메타데이터 주석도 본문에 포함되므로 자동으로 해시 대상에 들어갑니다. 이 값이
Configuration에서 설명한 upsert 판정(created/updated/unchanged)의
기준입니다.
ChatGPT의 conversations.json은 대화마다 실제 title 필드를 제공합니다(사용자가 채팅
목록에서 보는 제목과 동일, 없을 때만 첫 사용자 메시지의 첫 문장으로 대체). 반면 Gemini의
내 활동.html에는 대화별 제목이 아예 없습니다 — 유일하게 제목처럼 보이는 필드
(class="... title")는 세션마다 다른 값이 아니라 "Gemini 앱"이라는 고정 제품명뿐입니다.
그래서 Gemini는 항상 첫 질문의 첫 문장을 title로 대신 씁니다(first_sentence(...)).
이 벤더 간 차이 때문에 두 벤더 모두 파일명은 title이 아니라 session_id로
통일했습니다(vendors/chatgpt.py/vendors/gemini.py의 sanitize_filename(cid/sid, ...)).
title을 파일명 기준으로 썼다면:
- Gemini의 title은 첫 메시지에서 유도된 값이라 벤더마다 안정성이 다르고, 서로 다른 세션이 같은 첫 문장을 가지면 파일명이 충돌할 수 있습니다.
- upsert는 "같은 세션 = 같은 파일 경로"를 전제로 동작합니다(Configuration 참고). title을 파일명으로 쓰면 title 계산 로직이 바뀌거나 원본 첫 메시지가 살짝 달라지는 것만으로도 새 파일이 생기면서 기존 노트와의 연결이 끊깁니다.
session_id는 원본(ChatGPT의 conversation_id, Gemini의 세션 URL)에서 그대로 온 고유
식별자라 이런 문제가 없습니다 — title은 frontmatter에만 표시용으로 남고, 실제 파일 경로와
upsert 판정은 전부 session_id 기준입니다.
Claude는 conversations.json의 일반 대화엔 대체로 name이 채워져 있지만,
design_chats/*.json의 프로젝트 대화는 사용자가 이름을 안 바꾸면 그냥 "Chat"처럼
제네릭한 값으로 남아있는 경우가 흔합니다 — Gemini와 같은 이유로 Claude도 파일명은
title이 아니라 대화 uuid(session_id) 기준입니다.
다른 벤더는 result/<vendor>/*.md로 평평하게 쓰지만, Claude는 프로젝트에 묶인 대화만
result/claude/<프로젝트명>/*.md처럼 프로젝트별 하위 폴더에 씁니다(프로젝트에 안 묶인
일반 대화는 다른 벤더와 동일하게 평평하게 씀). 프로젝트명은 design_chats/*.json에
인라인으로 박힌 project.name에서 얻고, 파일시스템에 못 쓰는 문자는
sanitize_filename()으로 정리합니다. --publish도 이 하위 폴더 구조를 그대로
vault에 재현합니다(Configuration 참고).
memories.json(기억 기능 요약), login_history.json(로그인 이력), users.json(계정
정보), projects/*.json의 docs 필드(프로젝트 지식 파일)는 대화가 아니므로 변환하지
않습니다. 이 export에는 첨부파일 실 바이트가 전혀 들어있지 않아서(참조 파일명만 있음)
첨부파일은 항상 "누락" 안내 텍스트로만 표시됩니다.
관련 문서: Architecture