개발자 일기/좌충우돌 주니어 개발자 도전기

🧠 ChatGPT 대화 자동 저장 크롬 확장 프로그램 만들기 (JSON 실시간 저장까지!)

parklog 2025. 4. 13. 11:25

✨ 주요 기능

✅ 예전 대화 클릭 시 자동으로 대화 내용을 감지
✅ .json 파일로 내 컴퓨터에 자동 다운로드
✅ 한 대화당 1번만 저장 (중복 방지)
✅ 여러 개 대화도 순차 저장 가능
✅ 추가 버튼 클릭 없이 100% 자동화


📦 폴더 구조

css
복사편집
chatgpt-saver/ ├── manifest.json ├── content.js ├── popup.html ← (선택) ├── popup.js ← (선택)

🛠 manifest.json

{
    "manifest_version": 3,
    "name": "ChatGPT 기록 자동 저장기",
    "version": "1.0",
    "permissions": ["storage", "scripting", "activeTab"],
    "host_permissions": [
    ],
    "background": {
      "service_worker": "background.js"
    },
    "content_scripts": [
      {
        "matches": [
          "https://chat.openai.com/*",
          "https://chatgpt.com/*"
        ],
        "js": ["content.js"]
      }
    ],
    "action": {
      "default_popup": "popup.html",
      "default_title": "GPT 저장기"
    }
  }
 

🧩 핵심 파일 content.js

let lastSavedId = null;

function extractChatMessages() {
  const messageBubbles = document.querySelectorAll('[data-message-author-role]');
  const result = [];

  messageBubbles.forEach((el, i) => {
    const role = el.getAttribute('data-message-author-role');
    const content = el.innerText.trim();
    if (content) {
      result.push({
        index: i + 1,
        role,
        content
      });
    }
  });

  return result;
}

function triggerDownload(data, filename) {
  const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = filename + ".json";
  document.body.appendChild(a);
  a.click();
  a.remove();
  URL.revokeObjectURL(url);
}

function saveChat() {
  const currentId = window.location.pathname;

  // 대화 내용이 충분히 렌더링됐는지 체크
  const messages = document.querySelectorAll('[data-message-author-role]');
  if (messages.length === 0) return;

  if (currentId === lastSavedId) return;

  const data = extractChatMessages();
  const title = document.title + " - " + new Date().toLocaleString();

  if (data.length > 0) {
    chrome.storage.local.set({ [title]: data }, () => {
      console.log("✅ GPT 대화 저장됨:", title);
    });

    triggerDownload(data, title.replace(/[\\/:*?"<>|]/g, "_"));
    lastSavedId = currentId;
  }
}

// 주소 변경 감지 + DOM 렌더링 후 실행까지 기다림
let prevPath = window.location.pathname;

setInterval(() => {
  const currentPath = window.location.pathname;
  if (currentPath !== prevPath) {
    prevPath = currentPath;
    lastSavedId = null;

    // 대화가 완전히 로드되었는지 기다렸다가 저장
    const checkLoaded = setInterval(() => {
      const messages = document.querySelectorAll('[data-message-author-role]');
      if (messages.length > 0) {
        saveChat();
        clearInterval(checkLoaded);
      }
    }, 500);
  }
}, 1000); // URL 변경 감지 간격

 

📄 3. popup.html

 

<!DOCTYPE html>
<html>
  <head><title>GPT 저장기</title></head>
  <body>
    <h3>📘 저장된 대화</h3>
    <ul id="chatList"></ul>
    <script src="popup.js"></script>
  </body>
</html>

 

 

📄 4. popup.js

 

chrome.storage.local.get(null, (items) => {
    const chatList = document.getElementById("chatList");
    for (const key in items) {
      const li = document.createElement("li");
      li.textContent = key;
      chatList.appendChild(li);
    }
  });
 

🔧 설치 방법

  1. 위 파일들을 chatgpt-saver 폴더에 저장
  2. 크롬 주소창에 chrome://extensions 입력
  3. 우측 상단 개발자 모드 ON
  4. "압축해제된 확장 프로그램 로드" → 폴더 선택
  5. ChatGPT(https://chatgpt.com) 접속
  6. 예전 대화 하나 클릭 → 자동 저장 확인 (콘솔 로그도 확인 가능)

✅ 사용 예시

  • 대화 1 클릭 → GPT 대화 저장됨: 제목.json 자동 다운로드
  • 대화 2 클릭 → 또 저장
  • 같은 대화 다시 열면? 저장 안 됨 (중복 방지 OK)

📥 저장 파일 예시

json
복사편집
[ { "index": 1, "role": "user", "content": "오늘 점심 뭐 먹을까?" }, { "index": 2, "role": "assistant", "content": "된장찌개 추천드립니다!" } ]

 

시행결과


 

 

예상 질문 

 

Q: 다운로드 폴더 변경은 안되나요?

 

A: 안되요 이건 브라우저 밑에서노는 서비스 워커에요 감히 브라우저 님의 심기를 거스를 수는 없죠..

 

Q: 동작 원리가 뭔가요?

 

A: 플러그인으로 웹 스크랩핑으로 특정 도메인 변경 사항을 감지하는 거에요. 그리고 내가 전에 했던 질문들에 대해서 사이드메뉴에서 클릭하면 해당 질문도 다운되요.