ChatGPT를 사용한 뉴스 요약 : 크롬 익스텐션 개발기
서론
아래 포스팅을 보면 알 수 있듯이, ChatGPT를 사용해 해외 뉴스를 매일매일 요약하고 있다.
불편했던 점은
ChatGPT가 대화의 히스토리를 기억한다고 하지만, 대화가 길어지면 처음 요구 했던 내용을 종종 잊어버린다
그렇기 때문에
뉴스 요약을 하는 과정 중간 중간 마다 엉뚱하게 요약을 하는 일이 발생했다.
그래서 매 번 대화할때마다 원하는 프롬프트를 계속 집어넣기로 했다.
하지만
해당 프롬프트를 매번 Ctrl + C/V 하는 과정은 놀랍게도 대한민국에서는 매우 귀찮은 일이 아닌가 싶다.
그래서 해당 프롬프트 내용을 앞에 붙여서 보내주는 버튼을 확장프로그램으로 만들기로 했다.
- 확장 프로그램 팝업창
- 생성 된 버튼
버튼의 역할은 매우 간단하다
버튼의 역할은 단순하게
"뉴스를 요약할 때 어쩌꼬 저쩌고"를 입력된 뉴스 내용 앞에 붙여서 전송해 주는 역할이다
개발
1. Manifest V3
manifest_version은 3으로 사용했다
"manifest_version": 3
2. 권한
2.1 Permissions
"permissions": [
"activeTab",
"storage"
],
ActiveTab
- 현재 활성중인 탭에 대해 다룰 수 있는 API 사용 권한
Storage
- 일종의 브라우저 데이터베이스 API 사용 권한인데, 토글스위치의 On/Off 상태 정보를 저장하기 위해 사용
2.2 Host_permissions
- 특정 사이트에서만 크롬 익스텐션이 동작할 수 있도록 호스트 권한 설정
"host_permissions": [
"https://chat.openai.com/*"
],
3. popup.js
1. 토글 스위치 상태 확인:
- chrome.storage.local.get 함수를 사용해서 storage 내부 isButtonEnabled 키의 값을 가져옴
- 스토리지에 isButtonEnabled 키의 값이 있는 경우, 이 값을 사용하여 토글스위치의 체크 상태를 설정
2. 토글 스위치 이벤트 리스너:
- 토글 스위치에 'change' 이벤트 리스너를 추가해서. 사용자가 스위치를 토글 하면 이 리스너 호출
- 이 리스너는 먼저 chrome.storage.local.set 함수를 사용하여 `isButtonEnabled 키의 값 변경.
- 그 다음 활성화된 탭을 찾아서 `TOGGLE_BUTTON` 메시지를 보냈음. 메시지는 `content.js` 스크립트에서 처리
document.addEventListener('DOMContentLoaded', function () {
var toggleSwitch = document.querySelector('#toggleSwitch');
if (toggleSwitch) {
// 팝업이 열릴 때마다 토글의 상태를 확인합니다.
chrome.storage.local.get('isButtonEnabled', function(data) {
if (data.hasOwnProperty('isButtonEnabled')) {
toggleSwitch.checked = data.isButtonEnabled;
}
});
toggleSwitch.addEventListener('change', function () {
// 토글의 상태를 변경하고, background script에 메시지를 보냅니다.
chrome.storage.local.set({isButtonEnabled: toggleSwitch.checked}, function() {
console.log('Value is set to ' + toggleSwitch.checked);
});
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
if (tabs.length > 0) {
chrome.runtime.sendMessage({cmd: 'TOGGLE_BUTTON', value: toggleSwitch.checked, tabId: tabs[0].id});
}
});
});
}
});
4. Service-Worker.js
해당 스크립트에서는 일부 코드 중, Promise를 사용해서 수정한 코드
Promise를 사용하지 않은 원래의 코드
- `chrome.storage.local.set` 함수의 콜백 함수 안에서 `chrome.tabs.query` 함수를 호출하고 있는데,
- 이는 `chrome.storage.local.set` 함수의 작업이 끝나고 나서 `chrome.tabs.query` 함수의 작업을 수행
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.cmd === 'TOGGLE_BUTTON') {
chrome.storage.local.set({isButtonEnabled: request.value}, () => {
console.log('Value is set to ' + request.value);
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
if (tabs.length > 0) {
try {
chrome.tabs.sendMessage(tabs[0].id, {cmd: 'TOGGLE_BUTTON', value: request.value});
} catch (error) {
console.error('Failed to send message to tab', tabs[0].id, error);
}
}
});
// sendResponse 호출
sendResponse({status: 'success'});
});
return true;
}
});
Promise를 사용한 수정된 코드:
- Promise를 사용한 수정된 코드에서는, `chrome.storage.local.set` 함수의 콜백 함수 안에서 Promise를 생성하고, 이 Promise가 해결(resolve)될 때까지 기다림
- 이는 `chrome.storage.local.set` 함수의 작업이 끝나고 나서 다음 작업을 수행하기 위함
- 비동기 작업흐름이 명확해져서 좋고 오류 처리가 더 간편하다는 장점이 있는 것 같음
chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
if (request.cmd === 'TOGGLE_BUTTON') {
await new Promise(resolve => {
chrome.storage.local.set({isButtonEnabled: request.value}, () => {
console.log('Value is set to ' + request.value);
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
if (tabs.length > 0) {
try {
chrome.tabs.sendMessage(tabs[0].id, {cmd: 'TOGGLE_BUTTON', value: request.value});
} catch (error) {
console.error('Failed to send message to tab', tabs[0].id, error);
}
}
});
// sendResponse 호출
sendResponse({status: 'success'});
resolve();
});
});
// 리스너가 비동기 응답을 보낼 것임을 나타냅니다.
return true;
}
});
Prommise를 사용하게 된 이유
아래 줌 인터넷 테크 블로그를 참조하다가
다음과 같은 문구를 발견해서 찾아보고 바로 사용한듯..
content.js
- 뉴스 내용 앞에 들어갈 프롬프트를 아래처럼 정의해 놨음
newButton.onclick = function() {
inputField.value = `
너의 역할은 해외 증권 뉴스를 한국어로 요약하는 한국 증권사 직원이다
너가 요약한 뉴스는 일반인들이 읽기때문에 이해하기 쉽도록 한국어로 요약해야한다
70단어 이내로 요약해라
2가지 포맷을 지켜라
- 제목 : <제목>
- 요약 : <요약>
${inputField.value}`;
sendButton.click();
};
뉴스를 복사 붙여 넣기만 하면, 앞에 프롬프트를 같이 보내주는 용도
스토리지에서'isButtonEnabled'라는 키의 값을 가져와서, 그 값이 true인 경우 addButton 함수를 호출하고,
그렇지 않은 경우 removeButton 함수를 호출
chrome.storage.sync.get('isButtonEnabled', function(data) {
if (data.isButtonEnabled) {
addButton();
} else {
removeButton();
}
});
결과
팝업 창
끝으로
몇 가지 에러가 남아있어서 해결해야 하는 데, 쉽지가 않다
참조
'MLOps > Development' 카테고리의 다른 글
만약 내가 Seller라면, 어떤 물건을 팔까? (1) (0) | 2023.05.30 |
---|---|
코드 품질 향상을 위한 FastAPI 기반 코드 리팩토링 (0) | 2023.05.22 |
아이디어스 스크래퍼(Puppeteer, Electron) (0) | 2023.05.07 |
쿠팡 상품 정보 수집기 v1.1.0 (0) | 2023.04.29 |
쿠팡 상품 정보 수집기(Python, Pyside6) (0) | 2023.04.23 |