관리자 프로그램은 Electron
으로 개발된 데스크톱 어플리케이션입니다.
그로인해 업데이트가 필요할 때, 병원 측에 별도로 연락하여 업데이트 버튼을 눌러야 하는 불편함이 있습니다.
특히, 현재와 같이 잦은 업데이트가 필요한 초기 단계에서는 병원과의 불필요한 소통이 발생할 수 있으며, 신속한 업데이트 적용이 어려운 문제가 있습니다.
(또한 버그 픽스가 바로바로 반영이 되지 않습니다.)
이러한 관리자 프로그램 업데이트 방식을 개선하기 위하여 로그인 후 실제 수검자 데이터를 조작하는 페이지는
electron
에서 제공해주는 webview
태그를 사용하여 배포된 웹사이트를 보여주는 방식으로 개선합니다.
로그인 페이지 : Electron
의 Renderer 프로세스에서 보여줌
수검자 데이터 조작 페이지 : Electron
의 Renderer 프로세스에서 보여줌
로그인 페이지 : Electron
의 Renderer 프로세스에서 보여줌
수검자 데이터 조작 페이지 : webview
태그를 사용하여 외부 웹사이트를 띄워줌, 외부 프로젝트로 분리된 수검자 데이터 조작 페이지는 vite
를 사용하여 개발
Electron
에서 webview
로는 아래와같은 방식으로 메세지를 전송하는것이 가능합니다.
import React, { useEffect, useRef } from "react";
const FullScreenWebview = () => {
const webviewRef = useRef(null); // WebView 참조
const sendMessageToWebview = () => {
webviewRef.current.contentWindow.postMessage( <- 이거로 메세지 보냄
"여기는 일렉트론 메시지를 보낸다",
"*"
);
};
return (
<div
style={{
backgroundColor: "#edeff2",
width: "100dvw",
height: "100dvh",
}}
>
<div
style={{ width: 40, height: 40, backgroundColor: "red" }}
onClick={() => {
sendMessageToWebview();
}}
>
버튼
</div>
<div style={{ height: "100%", width: "100%" }}>
<webview
ref={webviewRef}
src={"http://localhost:5173/"} // Vite 서버 URL
style={{ width: "100%", height: "100%" }}
allowFullScreen
/>
</div>
</div>
);
};
export default FullScreenWebview;
export default function InReactComponent() {
window.addEventListener("message", (event) => {
console.log("여기는 Vite 메세지를 받았다. -> 받은 메세지 :", event.data);
});
return (
<div>SomethingComponentContetns</div>
);
}
그러나 webview
로 띄워지는 외부 프로젝트(현재 vite
로 개발된 웹페이지)는 Electron
으로 메세지를 전송할 수 없습니다.
그러나 Electron
에서 webview
로 보여지는 페이지의 console 기록은 읽는것이 가능합니다.
import React, { useEffect, useRef } from "react";
const FullScreenWebview = () => {
const webviewRef = useRef(null); // WebView 참조
useEffect(() => {
const webviewElement = webviewRef.current;
if (webviewElement) {
const handleWebviewConsole = () => {
// 이곳의 eventListener에서 웹뷰의 콘솔로그 기록을 읽는것이 가능
webviewElement.addEventListener(
"console-message",
(e: { message: string }) => {
console.log("Guest page logged a message:", e.message);
}
);
webviewElement.openDevTools();
};
webviewElement.addEventListener("dom-ready", handleWebviewConsole);
return () => {
if (webviewElement) {
webviewElement.removeEventListener("dom-ready", handleWebviewConsole);
}
};
}
}, []);
const sendMessageToWebview = () => {
webviewRef.current.contentWindow.postMessage( <- 이거로 메세지 보냄
"여기는 일렉트론 메시지를 보낸다",
"*"
);
};
return (
<div
style={{
backgroundColor: "#edeff2",
width: "100dvw",
height: "100dvh",
}}
>
<div
style={{ width: 40, height: 40, backgroundColor: "red" }}
onClick={() => {
sendMessageToWebview();
}}
>
버튼
</div>
<div style={{ height: "100%", width: "100%" }}>
<webview
ref={webviewRef}
src={"http://localhost:5173/"} // Vite 서버 URL
style={{ width: "100%", height: "100%" }}
allowFullScreen
/>
</div>
</div>
);
};
export default FullScreenWebview;
따라서 webview
→ Electron
으로 메세지를 전송할 상황의 경우에는 console을 사용하여 메세지를 전달하는 방식으로 통신 방법을 설정하였습니다.
허나 console.log의 경우 노출되어있기 떄문에 별도의 데이터를 출력하는 경우는 없어야하며
reducer와 같이 action 상태를 전달하는 방식으로 통신이 이루어 집니다.
또한 보안을 강화하기 위해 console.debug를 사용하여 메세지를 전달합니다.
(console.debug를 사용하면 개발환경에서만 개발자도구에서 출력이 가능합니다)
아래는 console.debug를 통해 메세지를 전달하는 함수 코드의 예시입니다.
const sendMessageToElectron = () => {
// Electron으로 메시지 보내기
const sendData = {
type: "sendFromWebAdmin",
action: "logout",
executeFunction: `
console.log('executeFunction')
`,
};
console.debug(JSON.stringify(sendData));
};
webview
→ Electron
으로 메세지를 전달할시에는 아래와 같은 객체형태로 데이터를 console.debug를 통해 데이터를 전달해야하며 각 action에 따른 Electron에서의 처리를 정의합니다.
{
type:'sendFromWebAdmin',
action : "logout" | "executeFunction" | "newWindowOpen" | "messageRecieveReady",
executeFunction? : 'console.log('이 string이 Electron에서 함수로서 실행됩니다.')',
newWindowUrl? :string;
}
webview
내부의 웹페이지도 로그아웃되며 실제 Electron
어플리케이션에서도 로그아웃이 실행됩니다.
Electron
에 저장된 토큰또한 다 지워집니다.
{
type:'sendFromWebAdmin',
action : "logout",
}
executeFunction 필드를 통해 전달받은 javascript 코드들이 Electron
에서 실제로 실행됩니다.
executeFunction필드에는 import 같이 외부 모듈을 가져오는 것을 불가능하며 alert나 console.log같이
javascript 고유의 기능들만이 실행 가능합니다.
{
type:'sendFromWebAdmin',
action : "logout",
executeFunction : `
아래와 같은 형식의 실행될 Javascript code 들
console.log('someThing');
alert('someThjing2');
`
}
새로운 창이 띄워집니다.
{
type:'sendFromWebAdmin',
action : "newWindowOpen",
newWindowUrl: '새창으로 열고자 하는 url(ex. 공지버튼 눌러서 공지창 열기)'
}
webveiw
(vite 프로젝트) 에서 돔트리가 완성된 후 메세지를 수신할 준비가 되었음을 알려줍니다.
Electron
에서 해당 메세지를 수신하면 webview
로 accessToken을 전달합니다.
{
type:'sendFromWebAdmin',
action : "messageRecieveReady",
}
Electron
앱으로 받아온 후 저장합니다.webview
로 로드합니다.webview
내부의 dom 트리가 완성된 후 Electron
으로 부터 데이터(access token)을 받을 준비가 완료된 상태알림을 Electron
으로 전달합니다.webview
에서 logout, newWindowOpen 등의 메시지를 보내면 Electron에서 처리할 수 있도록 설정합니다.webveiw
에서 이제 Electron
으로부터 메세지를 받을 수 있는 상태가 되었음을 전달합니다.Electron
에 저장된 access token을 webview
내부 페이지로 전달합니다.위 프로세스들이 완료되면 webview 내부에서는 access token을 가지고 수검자 정보를 처리할 수 있습니다.
(검수, 전송, 삭제 등의 기능)