콘텐츠
일렉트론(Electron) 팝업 창 만들기
일렉트론(Electron) 프레임워크는 웹 기술로 데스크탑 환경의 OS 에서 사용할 애플리케이션을 만들 수 있는 환경을 제공한다.
그리고 일렉트론으로 생성한 앱의 메인 화면 위에 새로운 팝업 창을 출력 할 수 있는데 오늘은 그 방법에 대해 정리하고 다뤄보았다. 방법은 간단하며 아래의 코드를 따라 한다면 쉽게 새로운 팝업 창을 출력할 수 있을 것이다.
기존 자바스크립트(JavaScript) 에서 팝업 창 만들기
순수 바닐라 JS 에서도 팝업 창을 출력할 수 있다. 팝업 창 출력을 위한 HTML 예시 코드는 다음과 같다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Popup Example</title>
<script>
function openPopup() {
// 팝업 창을 여는 함수
var url = "https://www.example.com"; // 팝업 창에 표시할 URL
var name = "popupWindow"; // 팝업 창의 이름
var specs = "width=600,height=400,left=200,top=200"; // 팝업 창의 속성
window.open(url, name, specs);
}
</script>
</head>
<body>
<h1>팝업 창 예제</h1>
<button onclick="openPopup()">팝업 창 열기</button>
</body>
</html>
HTML이 코드를 HTML 파일에 작성하고 실행하게 되면 브라우저에 팝업 창 예제가 출력 될 것이다. 거기서 팝업 창 열기 버튼을 선택하게 되면 Examle Donmain 이란 문구를 지닌 새로운 창이 생성 된다.
여기서 https://www.example.com 은 예제나 샘플 코드에 사용할 수 있도록 기본적으로 생성 되어 있는 URL 이므로 아직 개발한 팝업 창에 대한 주소가 없는 상태여서 이 URL 을 사용 하였다. var url 의 값을 다른 url 로 변경하면 원하는 사이트를 팝업 형태로 출력할 수 있다.
그럼 일렉트론의 렌더러 프로세스에 해당하는 JS 파일에 이 코드를 작성할 수 있겠지만, 일렉트론 기반의 화면을 하나 더 출력하는 방법은 아니다. 일렉트론 프레임워크로 서로 연동 되는 팝업을 생성하기 위해선 메인 프로세스에서 생성해 실행해야 한다.
일렉트론 팝업 창 생성하기
먼저 일렉트론(Electron) 에서 팝업 창을 생성하기 위해 프로세스 간 통신 방법을 알고 있어야 수월하게 진행할 수 있다.
그래서 다음과 같은 index.html 와 index.js 그리고 화면에서 팝업 창 열기 버튼을 누르면 이에 대한 렌더러와 메인 프로세스 간 통신을 구현하기 위해 preload.js, 팝업에서 열릴 popup.html 이렇게 네 개를 작성하였다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Popup Example</title>
<script>
function openPopup() {
window.electronAPI.openPopup();
}
</script>
</head>
<body>
<h1>팝업 창 예제</h1>
<button onclick="openPopup()">팝업 창 열기</button>
</body>
</html>
HTML- 메인 화면이 될 HTML 코드로 아래의 index.js 에서 호출된다.
- window.electronAPI.openPopup(): preload.js 에서 정의 되어 메인 프로세스에 메시지를 보낸다.
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
let mainWindow;
function createWindow() {
//기본 창 생성
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: true
}
})
//index.html 로드
mainWindow.loadFile('index.html')
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
function createPopup() {
popupWindow = new BrowserWindow({
width: 600,
height: 400,
parent: mainWindow,
modal: true,
show: false
});
popupWindow.once('ready-to-show', () => {
popupWindow.show();
});
popupWindow.on('closed', () => {
popupWindow = null;
});
popupWindow.loadFile('popup.html');
}
// 렌더러 프로세스에서 메시지 수신
ipcMain.on('open-popup', () => {
createPopup();
});
JavaScript- 실행 될 일렉트론 메인 코드 파일이다.
- createWindow() 함수가 앱이 활성화 되면 실행 되는 코드인 app.on(‘activate’, () => {… 에서 호출 되어 기본 창을 생성, 출력한다. 이 때, 미리 let 키워드로 mainWindow 를 함수 밖에 생성한 이유는 이후 팝업을 생성할 때 부모 창 객체가 필요하기 때문이다.
- preload 파일의 ipcRenderer.send(‘open-popup’) 에 의해 ipcMain.on(‘open-popup’, () => {… 가 실행, createPopup() 함수로 팝업이 생성된다. 이 때 createWindow 로 생성했던 mainWindow 를 parent 에 입력한다.
- popupWindow.once(‘ready-to-show’, () => {… 코드는 팝업이 표시될 준비가 되었을 때 실행 될 코드다.
- popupWindow.on(‘closed’, () => {… 코드는 팝업 창이 완전히 닫혔을 때 실행 될 코드다.
- popupWindow.loadFile(‘popup.html’); 은 프로젝트 내 지정한 경로의 html 파일을 실행 한다. 만약 특정 웹 URL 을 실행하고 싶다면 popup.loadURL(‘https://example.com’); 을 사용할 수 있다.
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld(
'electronAPI', {
openPopup: () => ipcRenderer.send('open-popup')
}
);
JavaScript- 렌더러 프로세스의 window 객체에 preload 로 작성 된 메서드 들이 추가 된다. 위의 코드로 인해 렌더러 프로세스에서 window.electronAPI.openPopup(); 을 사용할 수 있게 된다.
- ipcRenderer.send(‘요청 명’) 코드로 인해 같은 요청 명을 지닌 index.js 내의 ipcMain.on(‘요청 명’, () => {… 이 수행된다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Popup</title>
</head>
<body>
<h1>이 창은 팝업입니다.</h1>
</body>
</html>
HTML- 팝업 창을 구성할 HTML 파일 이다.
이 코드의 메인이 되는 index.js 를 실행 하여 생성 된 앱 화면 내의 버튼을 눌렀을 때 정상적으로 팝업이 생성되면 성공.
팝업 창 관련 옵션
일렉트론의 팝업 창을 생성할 때 창에 대한 옵션을 줄 수 있는데 코드를 보면 알겠지만 팝업을 위한 전용 옵션은 아니고 일렉트론으로 생성 된 화면에 부여할 수 있는 옵션들이다. 즉, 메인 화면을 생성할 때도 사용할 수 있다.
- width와 height: 팝업 윈도우의 너비와 높이를 설정한다.
- resizable: 팝업 윈도우의 크기 조정 가능 여부를 설정한다. 기본값은 true 로 false 를 부여하면 크기가 고정된다.
- movable: 팝업 윈도우를 이동할 수 있는지 여부를 설정한다. 기본값은 true 며 false 부여 시 화면의 위치가 고정된다.
- minWidth와 minHeight: 윈도우의 최소 너비와 높이를 설정한다.
- maxWidth와 maxHeight: 윈도우의 최대 너비와 높이를 설정한다.
- title: 팝업 윈도우의 제목을 설정한다.
- frame: 프레임(윈도우의 기본 테두리) 표시 여부를 설정 한다. false로 설정하면 프레임이 없는 윈도우가 생성되며 화면을 닫기 위한 별도의 버튼, 방법을 구현해야 한다.
- alwaysOnTop: 팝업 윈도우가 항상 다른 윈도우 위에 표시되도록 설정한다. 동영상 플레이어의 항상 위에 같은 기능이다.
- modal: 모달 팝업, 윈도우로 설정한다. 이는 새로운 창이 떠있는 동안 다른 창을 사용할 수 없게 하는 옵션이다.
이 옵션들은 new BrowserWindow 내의 {} 안에 키와 값을 작성하면 된다.
popupWindow = new BrowserWindow({
width: 600,
height: 400,
parent: mainWindow,
modal: true, //모달 팝업으로 설정
frame: false //프레임(테두리) 제거
});
JavaScript프레임 없는 팝업 창 이동하는 방법
위의 팝업 창 관련 옵션 중 frame 의 값을 false 로 하여 테두리를 제거 했다면 상단의 상태 표시줄도 사라지기 때문에 생성 된 팝업 창을 이동하려면 별도의 방법을 제거해야 한다.
이 때, 가장 많이 사용하는 방법은 선택하고 드래그 하면 이동하게 만들 HTML 요소에 다음과 같은 CSS 요소를 만들어 주면 해당 요소를 선택하고 드래그 할 때 팝업 창이 이동하게 된다.
CSS 코드
-webkit-app-region: drag;