처음에는 자식 노드 중에서 p 태그
가 가장 많은 태그를 찾았습니다.
하지만 예외가 너무 많았고, 워킹 데이가 많지 않아서 라이브러리를 사용했습니다.
바로 ReadAbility
라는 라이브러리 입니다.
이 라이브러리를 통해서 본문 내용을 전부 가져올 수 있었습니다.
그 전에 Content Script
에서 popup
으로 body.innerHTML
을 전달해야 합니다.
그래야지 팝업창에서 ReadAbility
라이브러리를 사용할 수 있기 때문이죠
Content Script
에서 익스텐션 팝업창으로 보내기 위해선
chrome.runtime.sendMessage
메서드가 필요합니다.
코드로 살펴볼까요?
chrome.runtime.sendMessage({
type: "SEND_BROWSER_INFO",
hostName: getDomain(),
resultArr: resultArr,
HTMLContent: document.documentElement.outerHTML,
accessToken: result.GETSBEE_LOGIN.accessToken,
refreshToken: result.GETSBEE_LOGIN.refreshToken,
userState: result.GETSBEE_LOGIN.userState,
});
이렇게 하여 popup창으로 데이터를 보낼 수 있습니다.
background.js
는 말 그대로 백그라운드 작업을 담당합니다.
실시간 메시지를 수신하고 전달하는 역할을 하죠
코드로 살펴봅시다.
if (message.type === "SEND_BROWSER_INFO") {
// 저장: chrome.storage.local 또는 chrome.storage.sync에 데이터 저장
// eslint-disable-next-line no-undef
accessToken = message.accessToken;
refreshToken = message.refreshToken;
chrome.runtime.sendMessage({
type: "SEND_DATA",
data: {
hostName: message.hostName,
resultArr: message.resultArr,
HTMLContent: message.HTMLContent,
accessToken: message.accessToken,
refreshToken: message.refreshToken,
userState: message.userState,
},
});
}
Content Script
에서 SEND_BROWSER_INFO
를 보내면, 백그라운드에서 이를 수신하고 해당 코드를 처리합니다.
마찬가지로 크롬 팝업창
에 메시지를 보내야겠죠?
chrome.runtime.sendMessage
를 통해 보낼 수 있습니다.
이제 popup
에서 body.innerHTML
을 전달받았으므로, Readability
를 사용해 본문을 추출할 수 있습니다.
해당 본문을 토대로 Gemini API
를 호출하여 핵심 문장을 추천받으면 끝이 납니다.
코드로 알아볼까요?
async function run(model) {
try {
let prompt = `
다음 문장 배열에서 중요하다고 생각되는 문장들을 배열형식으로 추천해 주세요. 다음 조건을 만족해야 합니다:
1 그리고 꼭 배열의 크기가 5를 넘으면 안됩니다.
2. JSON형식으로 보내주세요 예를 들어, [{"중요 문장1의 인덱스" : "중요 문장1"}, {"중요 문장2의 인덱스" : "중요 문장2"}, {"중요 문장3의 인덱스" : "중요 문장3"}] 형식으로 응답해 주세요.
3. 전체적인 내용을 빠르게 파악할 수 있는 핵심 문장들을 추천해주세요, 기존 배열에서 순서에 맞게 제공해주어야 합니다.
4. 또한 기존 문장에서 문장을 추가하지말고 그냥 있는 그대로 중요 문장을 추출해주세요.
`;
if (textContents.length === 0) {
setLoading(false);
setErrorMessage("내용이 부족합니다.");
setError(true);
return;
}
const result1 = textContents.reduce((acc, item, index) => {
acc[index] = item;
return acc;
}, {});
prompt += JSON.stringify(result1);
const result = await model.generateContent(prompt);
const response = await result.response;
const text = await response.text();
let jsonData = "";
try {
jsonData = text.split("```")[1].split("json")[1];
} catch (er) {
jsonData = text;
}
const parsedData = JSON.parse(jsonData);
const sortedKeys = parsedData
.map((item) => {
const key = Object.keys(item)[0];
return parseInt(key, 10);
})
.sort((a, b) => a - b);
const sortedTextContents = sortedKeys.map((key) => textContents[key]);
setResult(sortedTextContents);
// console.log(textContents, sortedValues);
chrome.runtime.sendMessage({
type: "RECOMMEND_CLICKED",
resultArr: sortedTextContents,
});
}
Gemini API
문서를 토대로 호출한다음 응답받은 값을 sendMessage
를 통해서 background
에 보냅니다.
마찬가지로 background
에서 수신하고 ContentScript
에 전달하면 끝이 납니다.
여기까지 AI 기반 핵심 문장 추천 구현이였습니다.