//id 'org.springframework.boot' version '3.0.2' id 'org.springframework.boot' version '3.1.3'
에러 메시지
expression.EvaluationException: Accessing member 'requestUri' is forbidden for type 'class org.springframework.web.servlet.support.RequestContext' in this expression context.
원인
문제부분
<scriptth:inline="javascript">
/*<![CDATA[*/
//let loc = /*[[${#ctx.springRequestContext.requestUri}]]*/'';
#부트 버전 변경후 나머지 종속성으로 thymleaf버전도 3.1.3으로 변경되었는데 3.1에서는 제거된 방식이라고 함
처리
기존 방식
controller
@GetMapping(value="/admin/note.html")
publicStringindexGetMethod(Modelmodel) {
return"admin/note";
};
view
<scriptth:inline="javascript">
/*<![CDATA[*/
//let loc = /*[[${#ctx.springRequestContext.requestUri}]]*/'';
- 권한 부분과 콘텐츠 스크립트에서 사용할 "content_scripts"의 js 부분에 jquery.min.js를 추가했습니다. 추가가 되면 확장 프로그램이 해당 스크립트를 matches탭에 추가 해줍니다. 순서를 jquery 추가 하고 content.js를 추가해서 content.js에서 jquery를 사용할수 있습니다.
popup.html popup.js에서 jquery를 사용하기 위해 직접 불러오고 있습니다.
chrome.tabs.query({ active:true, currentWindow:true }, function (tabs) {
console.log("현재탭에 붙어있는 content에 msg보냄");
constresponse=chrome.tabs.sendMessage(
tabs[0].id,
{
from:'popup',
to:'content',
msg:msg,
// topics: extactTopics
},
function (response) {
console.log(response);
window.close();
}
);
})
}
$(document).ready(function () { //jquery사용
$("#sendMsg").on("click", function () {
console.log("clicked");
constmsg=$("#msg").val();
send_to_content(msg);
});
});
content.js 마지막 파일입니다. 직접 chatGPT DOM과 연동되는 부분입니다. 역시 jquery 예시를 위해 jquery로 부분 변환했습니다.
메시지를 수신하고 수신한 메시지를 chatGPT DOM의 대화 창에 추가 한후 키보드 이벤트를 발생시켜 submit하는 코드입니다.
jquery 예제 추가후 아래의 예시 코드는 주석을 해제해도 동작하지 않습니다. 원인을 확인 해본 결과 jquery와 충돌하는 듯 합니다. 수정방법은 manifest에서 jquery 제거, 관련 jquery 제거 후 gpt_textarea.value 값 설정, dispatchEvent를 발생 시키면 정상적으로 동작하게 됩니다.
console.log(`js 불림, 폴더구조확인용 content.js`);
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
if (message.from === 'popup') {
try {
console.log('메시지 수신1:', message);
sendResponse('메시지를 수신했습니다.');
bridge(message.msg);
}catch(error){
console.error(error);
}
}
});
function bridge(msg){
const gpt_textarea = document.querySelector('form textarea');
const gpt_button = document.querySelector('form button[class*="bottom"]')
gpt_button.disabled = true;
gpt_textarea.value = msg;
console.log(`수신한 msg->gpt에게 넘김:${msg}`);
/*
// 새로운 키보드 이벤트 생성
const event = new KeyboardEvent('keydown', {
key: 'Enter',
keyCode: 13,
code: 'Enter',
which: 13,
keyIdentifier: 'Enter',
view: window,
bubbles: true,
cancelable: true,
});
// 이벤트를 원하는 요소로 보내기
gpt_textarea.dispatchEvent(event);
*/
console.log(`주석 해제후 gpt_textarea에 엔터 키보드 이벤트전송시 질문이 openai로 전송됨`);
}
function insertDiv(){
var div = document.createElement("div");
div.style.height = "100px";
div.style.backgroundColor = "blue";
var body = document.body;
var lastChild = body.lastElementChild;
// body 요소의 맨 마지막에 div 요소를 추가합니다.
body.insertBefore(div, lastChild.nextSibling);
}
function jinsertDiv(){
var div = $("<div></div>").css({
"height": "100px",
"background-color": "red"
});
var lastChild = $("body").children().last();
// body 요소의 맨 마지막에 div 요소를 추가합니다.
lastChild.after(div);
}
jinsertDiv();
// insertDiv();
스크린샷 다 만든 후에 엔터키 이벤트가 충돌나는것을 발견 했습니다. 필요하신 분이 생기면 다음 글 작성하면서 예제코드를 하나 더 만들겠습니다. 지금은 동작하는 예시 하나 스크린샷하고 이번 카테고리 글은 마무리하겠습니다.
동일한 구조로 동작하는 확장프로그램입니다. jquery는 사용하지 않았습니다. 확장아이콘 클릭시 값이 초기화 되어 localStorage에 저정하고 불러오는 구조로 작업했습니다.
이상으로 에지브라우저에서 chatGPT 탭으로 메시지 전송후 대화에 대한 글을 마치겠습니다.
popup.js : send_to_content 함수는 위에서 설명한것과 같이 chrome.tabs.query를 통해 현재 활성화된 열린 창의 탭을 조회하고 반환합니다. 탭이 조회되면 callback을통해 조회된 tabs를 전달받고 chrome.tabs.sendMessage( tabId:number, message:any, ..) 를 통해 tab으로 메시지를 전송합니다.
그 아래 코드는 popup.html의 sendMsg버튼에 클릭 이벤트를 추가하는 부분입니다. 클릭시 send_to_content함수를 통해 메시지를 전달합니다.
스크립트가 로드될때 chrome.runtime.onMessage에 이벤트 처리 함수를 추가 합니다. 그리고 탭주소가 https://chat.openai.com/*인 경우 페이지 가장 하단에 높이가 100인 div를 삽입합니다. 예제에서는 사용자와 대화창 위치를 popup.html에 넣을 예정이지만 content.js에 대화창을 두게될 경우 예시입니다.
console.log(`js 불림, 폴더구조확인용 content.js`);
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
if (message.from === 'popup') {
try {
console.log('메시지 수신1:', message);
sendResponse('메시지를 수신했습니다.');
}catch(error){
console.error(error);
}
}
});
function insertDiv(){
var div = document.createElement("div");
div.style.height = "100px";
div.style.backgroundColor = "blue";
var body = document.body;
var lastChild = body.lastElementChild;
// body 요소의 맨 마지막에 div 요소를 추가합니다.
body.insertBefore(div, lastChild.nextSibling);
}
insertDiv();
이번글에서는 브라우저와 특정 페이지의 contents에 메시지를 전송하고 처리하는 예제를 보았습니다. 다음에는 jquery를 추가해서 content, popup쪽에서 사용하는 방법과 popup에서 작성되어 온 메시지를 기존 gpt 대화창에 입력하는 부분을 진행해 보도록 하겠습니다.
에지확장프로그램은 브라우저에서 동작하면서 각각의 탭, 그리고 탭안에 열린 페이지의 내용(content)을 우리가 원하는대로 제어할수 있도록 해줍니다. 그리고 탭들이 각각 독립적으로 동작하고 있어서 그 탭들간의 공유내용과 통신을 background라는 부분을 통해서 수행할수 있도록 합니다. 그리고 탭의 content에서 탭간 공유를 위한 background 파일에 대한 설정을 manifest.json 파일에 작성하게 됩니다.
현재 글의 주제인 chatGPT와 대화에서는 탭하나의 content를 제어하게 되어서, background는 사용을 안하게 될것같습니다.그리고 탭의 주소가 https://chat.openai.com 인 경우,그 탭의 html및 dom을 제어하게될 content.js 마지막으로 사용자의 문자를 받아서 탭에 붙어 있는 content로 문자열을 보내게 될 popup.html, popup.js파일로 구성됩니다.
동작 화면은 이전 페이지의 위 화면과 동일합니다. 단 manifest.json에 content제어 파일과 대상이 될 탭 정보 추가, 탭에서 탭안의 DOM을 제어할 content.js, 그리고 사용자와 대화할 popup.html 수정 및 popup.js 추가가 있습니다. 각각의 파일들의 주요 역할과 내용은 전 글에서 이야기했듯 아래와 같습니다.
에지확장프로그램의 구성 - Manifest 파일: 에지 확장 프로그램의 설정과 정보를 담는 JSON 형식의 파일입니다. 프로그램 이름, 버전, 아이콘, 권한 등의 정보를 정의합니다.
- Background Script (백그라운드 스크립트): 에지 확장 프로그램의 백그라운드에서 실행되는 JavaScript 코드입니다. 백그라운드에서 실행되는 주기적인 작업, 이벤트 처리 등을 담당합니다.
- Content Script (콘텐트 스크립트): 웹 페이지의 콘텐츠와 상호작용하기 위해 삽입되는 JavaScript 코드입니다. 웹 페이지의 DOM 요소에 접근하고 조작할 수 있습니다.
- Popup (팝업): 사용자 인터페이스를 제공하는 팝업 창입니다. 사용자의 입력을 받고 처리하는 등의 작업을 수행합니다.
사용자와의 인터페이스용 popup.html의 개발자 콘손을 "확장프로그램 아이콘 클릭" > 팝업된 창에서 마우스 오른쪽 클릭 > "검사" 메뉴를 클릭 하면 아래의 이미지와 같이 새창이 뜨면서 popup.html의 내용과 실행된 popup.js내용을 볼수 있습니다.
content.js 디버그 로그 확인을 위해 간단한 로깅을 추가 했습니다.
console.log(`js 불림, 폴더구조확인용 content.js`);
content.js 파일을 manifest에서 matchs 값과 탭의 주소창이 맞는 탭에 injection되어 있습니다. 따라서 지금 설정과 같은 경우 주소창의 주소가 https://chat.openai.com/* 인 탭에서 F12로 개발자 창을 열 경우 아래와 같이 실행된 content.js의 로그를 볼수 있습니다. 아래 그림의 "확장프로그램 아이콘 부분의 빨간 박스 표시"는 윗쪽 popup.html 개발자 도구 창을 열기 전의 모습입니다.
마지막으로 이번 예시에서는 사용하지 않았지만 다른 확장프로그램 개발중 background를 사용하기 위해 manifest.json에 background 제어 설정을 한경우 아래의 그림과 같이 "확장관리" 에 보시면 "서비스 작업자"라는 링크가 활성화되어 있고 이 링크를 클릭하면 background가 실행되고 있는 부분의 개발자 도구가 열리게 됩니다. 우리가 만든 Hello2는 bacground 제어 설정이 없어서 "서비스 작업자" 링크가 없습니다.
에지확장프로그램에서는 위에서 설명한 기본 세 부분이 서로 통신하며 탭과 탭의 DOM을 제어하게 됩니다.