✨ 주요 기능
✅ 예전 대화 클릭 시 자동으로 대화 내용을 감지
✅ .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": [
],
"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);
}
});
🔧 설치 방법
- 위 파일들을 chatgpt-saver 폴더에 저장
- 크롬 주소창에 chrome://extensions 입력
- 우측 상단 개발자 모드 ON
- "압축해제된 확장 프로그램 로드" → 폴더 선택
- ChatGPT(https://chatgpt.com) 접속
- 예전 대화 하나 클릭 → 자동 저장 확인 (콘솔 로그도 확인 가능)
✅ 사용 예시
- 대화 1 클릭 → GPT 대화 저장됨: 제목.json 자동 다운로드
- 대화 2 클릭 → 또 저장
- 같은 대화 다시 열면? 저장 안 됨 (중복 방지 OK)
📥 저장 파일 예시
json
복사편집
[ { "index": 1, "role": "user", "content": "오늘 점심 뭐 먹을까?" }, { "index": 2, "role": "assistant", "content": "된장찌개 추천드립니다!" } ]
시행결과

예상 질문
Q: 다운로드 폴더 변경은 안되나요?
A: 안되요 이건 브라우저 밑에서노는 서비스 워커에요 감히 브라우저 님의 심기를 거스를 수는 없죠..
Q: 동작 원리가 뭔가요?
A: 플러그인으로 웹 스크랩핑으로 특정 도메인 변경 사항을 감지하는 거에요. 그리고 내가 전에 했던 질문들에 대해서 사이드메뉴에서 클릭하면 해당 질문도 다운되요.
'개발자 일기 > 좌충우돌 주니어 개발자 도전기' 카테고리의 다른 글
| 포트폴리오 (0) | 2025.05.02 |
|---|---|
| 🛠 실전 운영 매뉴얼 1.0: 공실 공유오피스 플랫폼 (0) | 2025.04.24 |
| [ChatGPT 자동 감정 분석 플러그인 개발기] (0) | 2025.04.15 |
| 캔버스 자동 저장 스크립트 (0) | 2025.04.14 |
| 코드넘어 소통으로 (0) | 2025.03.30 |