"다이얼로그는 OS 네이티브 UI를 활용하는 대표 기능" — 웹에서는 불가능한 네이티브 파일 선택기와 시스템 알림을 Electron에서 쓸 수 있습니다.


파일 열기 다이얼로그

JAVASCRIPT
const { dialog, ipcMain } = require('electron');

ipcMain.handle('dialog:openFile', async (event) => {
  const win = BrowserWindow.fromWebContents(event.sender);
  const result = await dialog.showOpenDialog(win, {
    title: '파일 선택',
    defaultPath: app.getPath('documents'),
    properties: ['openFile', 'multiSelections'],
    filters: [
      { name: '텍스트 파일', extensions: ['txt', 'md'] },
      { name: '이미지', extensions: ['jpg', 'png', 'gif'] },
      { name: '모든 파일', extensions: ['*'] },
    ],
  });

  if (result.canceled) return null;
  return result.filePaths;
});

properties 옵션

옵션설명
openFile파일 선택 허용
openDirectory디렉토리 선택 허용
multiSelections다중 선택 허용
showHiddenFiles숨김 파일 표시
createDirectorymacOS: 디렉토리 생성 버튼 표시

파일 저장 다이얼로그

JAVASCRIPT
ipcMain.handle('dialog:saveFile', async (event, content) => {
  const win = BrowserWindow.fromWebContents(event.sender);
  const result = await dialog.showSaveDialog(win, {
    title: '파일 저장',
    defaultPath: path.join(app.getPath('documents'), 'untitled.txt'),
    filters: [
      { name: '텍스트 파일', extensions: ['txt'] },
      { name: 'Markdown', extensions: ['md'] },
    ],
  });

  if (result.canceled) return false;

  // 선택한 경로에 파일 저장
  await fs.promises.writeFile(result.filePath, content, 'utf-8');
  return true;
});

메시지 박스

JAVASCRIPT
ipcMain.handle('dialog:confirm', async (event, options) => {
  const win = BrowserWindow.fromWebContents(event.sender);
  const result = await dialog.showMessageBox(win, {
    type: 'question',           // none, info, warning, error, question
    title: options.title || '확인',
    message: options.message,
    detail: options.detail,     // 부가 설명
    buttons: ['확인', '취소'],
    defaultId: 0,               // 기본 선택 버튼
    cancelId: 1,                // ESC로 닫을 때 반환값
    checkboxLabel: '다시 묻지 않기',  // 체크박스 (선택)
  });

  return {
    response: result.response,         // 클릭한 버튼 인덱스
    checkboxChecked: result.checkboxChecked,
  };
});

메시지 박스 타입별 아이콘

  • info: 정보 아이콘 (i)
  • warning: 경고 아이콘 (!)
  • error: 에러 아이콘 (x)
  • question: 질문 아이콘 (?)

에러 다이얼로그

JAVASCRIPT
// 앱이 준비되기 전에도 사용 가능
dialog.showErrorBox('치명적 오류', '앱을 시작할 수 없습니다.');

showErrorBox는 동기 함수이고, app.whenReady() 전에도 사용할 수 있어서 초기화 에러 표시에 유용합니다.


실전 패턴: 저장하지 않은 변경사항 확인

JAVASCRIPT
// 메인 프로세스에서 창 닫기 전 확인
mainWindow.on('close', async (event) => {
  if (!hasUnsavedChanges) return;

  event.preventDefault();

  const { response } = await dialog.showMessageBox(mainWindow, {
    type: 'warning',
    title: '저장하지 않은 변경사항',
    message: '변경사항을 저장하시겠습니까?',
    buttons: ['저장', '저장 안 함', '취소'],
    defaultId: 0,
    cancelId: 2,
  });

  switch (response) {
    case 0: // 저장
      await saveDocument();
      mainWindow.destroy();
      break;
    case 1: // 저장 안 함
      mainWindow.destroy();
      break;
    // case 2: 취소 — 아무것도 안 함
  }
});

preload에서의 다이얼로그 API 노출

JAVASCRIPT
// preload.js
contextBridge.exposeInMainWorld('electronAPI', {
  openFile: () => ipcRenderer.invoke('dialog:openFile'),
  saveFile: (content) => ipcRenderer.invoke('dialog:saveFile', content),
  confirm: (options) => ipcRenderer.invoke('dialog:confirm', options),
});
JAVASCRIPT
// renderer.js
document.getElementById('openBtn').addEventListener('click', async () => {
  const files = await window.electronAPI.openFile();
  if (files) {
    files.forEach(f => console.log('선택:', f));
  }
});

document.getElementById('deleteBtn').addEventListener('click', async () => {
  const { response } = await window.electronAPI.confirm({
    title: '삭제 확인',
    message: '정말 삭제하시겠습니까?',
    detail: '이 작업은 되돌릴 수 없습니다.',
  });
  if (response === 0) {
    performDelete();
  }
});

면접 포인트 정리

  • dialog 모듈은 메인 프로세스에서만 사용 가능
  • showOpenDialog, showSaveDialog는 비동기(Promise), showErrorBox는 동기
  • properties 배열로 파일/폴더/다중선택을 세밀하게 제어
  • showMessageBoxcancelId는 ESC키 또는 창 닫기 시 반환값
  • 실전에서는 "저장하지 않은 변경사항" 패턴이 필수

다이얼로그를 마스터했으면, 다음은 Node.js fs 모듈과 연계한 파일 시스템 접근을 다뤄봅시다.

댓글 로딩 중...