키보드 단축키 — globalShortcut과 accelerator
"데스크톱 앱에서 단축키는 UX의 기본" — 메뉴의 accelerator와 globalShortcut의 차이를 이해하면 효과적인 단축키 시스템을 만들 수 있습니다.
두 가지 단축키 방식
| 방식 | 범위 | 앱이 포커스 필요 | 용도 |
|---|---|---|---|
| Menu accelerator | 앱 내부 | 필요 | 메뉴 연동 단축키 |
| globalShortcut | 시스템 전체 | 불필요 | 캡처, 미디어 제어 등 |
accelerator (메뉴 단축키)
const { Menu } = require('electron');
const template = [
{
label: '파일',
submenu: [
{
label: '새 파일',
accelerator: 'CmdOrCtrl+N',
click: () => createNewFile(),
},
{
label: '저장',
accelerator: 'CmdOrCtrl+S',
click: () => saveFile(),
},
{
label: '다른 이름으로 저장',
accelerator: 'CmdOrCtrl+Shift+S',
click: () => saveFileAs(),
},
],
},
];
Menu.setApplicationMenu(Menu.buildFromTemplate(template));
accelerator 문법
CmdOrCtrl: macOS에서는 Cmd, 다른 OS에서는 CtrlAlt,Shift,Super(Windows키)Plus,Space,Tab,Backspace,Delete,EscapeF1~F24- 조합:
CmdOrCtrl+Shift+Z,Alt+F4
globalShortcut (전역 단축키)
앱이 포커스되지 않아도 동작하는 시스템 전역 단축키입니다.
const { app, globalShortcut } = require('electron');
app.whenReady().then(() => {
// 전역 단축키 등록
const registered = globalShortcut.register('CmdOrCtrl+Shift+Space', () => {
console.log('전역 단축키가 눌렸습니다!');
if (mainWindow.isVisible()) {
mainWindow.hide();
} else {
mainWindow.show();
mainWindow.focus();
}
});
if (!registered) {
console.log('단축키 등록 실패 — 이미 다른 앱이 사용 중일 수 있습니다');
}
// 등록 여부 확인
console.log(
globalShortcut.isRegistered('CmdOrCtrl+Shift+Space')
);
});
// 앱 종료 시 반드시 해제
app.on('will-quit', () => {
globalShortcut.unregisterAll();
});
주의사항
- 다른 앱의 전역 단축키와 충돌할 수 있음
- 앱 종료 시 반드시
unregisterAll()호출 - 시스템 단축키(Ctrl+C 등)를 가로채지 않도록 주의
렌더러에서 키보드 이벤트 처리
// 렌더러 — 웹 표준 방식
document.addEventListener('keydown', (e) => {
// Ctrl+S (또는 Cmd+S)로 저장
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
e.preventDefault();
window.electronAPI.saveFile();
}
// Ctrl+Shift+P로 커맨드 팔레트
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'P') {
e.preventDefault();
openCommandPalette();
}
});
실전: 커스텀 단축키 설정
// 사용자가 단축키를 커스터마이징할 수 있게
class ShortcutManager {
constructor(configPath) {
this.shortcuts = this.loadConfig(configPath);
}
loadConfig(configPath) {
const defaults = {
'newFile': 'CmdOrCtrl+N',
'save': 'CmdOrCtrl+S',
'find': 'CmdOrCtrl+F',
'toggleSidebar': 'CmdOrCtrl+B',
};
try {
const saved = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
return { ...defaults, ...saved };
} catch {
return defaults;
}
}
buildMenuTemplate(actions) {
return Object.entries(this.shortcuts).map(([action, accelerator]) => ({
label: actions[action].label,
accelerator,
click: actions[action].handler,
}));
}
}
면접 포인트 정리
accelerator는 앱 포커스 시에만,globalShortcut은 시스템 전역CmdOrCtrl은 크로스플랫폼 호환을 위한 필수 키워드globalShortcut은 앱 종료 시 반드시unregisterAll()호출- 시스템 단축키와의 충돌을 항상 고려해야 함
단축키를 설정했으면, 다음은 알림(Notification)을 구현해봅시다.
댓글 로딩 중...