AI로 나만의 노트 앱 만들기 (3) 데스크탑 앱으로 확장

웹 노트 앱을 Tauri 기반 macOS 데스크톱 앱으로 확장했다. 로그인, 단축키, 실시간 동기화, DMG 배포와 자동 업데이트를 구현하며 웹과 데스크톱의 차이를 경험한 과정을 정리했다.

Share

2부에서는 브라우저 안의 노트 도구에 Cloudflare와 Firebase를 연결하고, 실제 URL에서 사용할 수 있는 웹서비스 형태로 확장했다.

AI로 나만의 노트 앱 만들기 (2) 실제 웹서비스로 확장하기
브라우저에만 저장되던 개인용 노트 앱에 Cloudflare와 Firebase를 연결했다. 데이터베이스, 인증, 권한, 자동 배포와 동기화를 적용하며 운영 가능한 웹 앱으로 확장한 과정을 정리했다.

그 상태로도 노트를 작성하고 관리하는 데에는 큰 문제가 없었다. 하지만 실제로 사용하다 보니 브라우저라는 실행 환경의 제약이 눈에 들어오기 시작했다.

Cmd + Z, Delete 키와 같은 일반적인 앱 동작이 브라우저의 기본 기능과 충돌했고, 창을 앱처럼 독립적으로 실행하고 싶었다. 웹과 데스크톱에서 같은 데이터를 사용하면서도 설치된 앱처럼 실행하고, 새로운 버전이 나오면 자동으로 업데이트되는 형태도 가능한지 궁금해졌다.

지금 상태에서도 충분히 사용할 수 있지만 한 단계 더 나아가보았다.

Tauri로 데스크톱 앱 만들기

GPT의 도움을 받아 기존 HTML, CSS, Plain JavaScript 구조를 유지하면서 macOS 앱으로 실행할 수 있는 방법으로 Tauri를 선택했다.

이 프로젝트를 macOS에서 네이티브 앱처럼 실행할 수 있게 변경해주세요.

목표는 브라우저보다 데스크톱 앱에 가까운 사용자 경험입니다.

Cmd + Z, Ctrl + Z 같은 일반적인 앱 동작을 자연스럽게 지원하고, 기존 기능은 유지해주세요.

현재 Cloudflare Pages, Workers, D1은 그대로 사용하고 데이터는 계속 클라우드에 저장되어야 합니다.

기존 HTML, CSS, Plain JavaScript 구조는 최대한 유지하면서 가장 적합한 방식으로 구현해주세요.

Tauri와 Rust를 설치하고 데스크톱 앱을 만들기 시작했다.

브라우저에서 HTML 파일을 실행하던 것과는 달리 Rust를 컴파일하고 macOS 앱을 빌드해야 했다.

2부에서 서버와 인증을 붙이면서 난도가 올라갔다면, 이번에는 실행 환경 자체가 달라졌다.

웹에서는 되는데 데스크톱에서는 안 되는 로그인

웹에서는 Firebase Google 팝업 로그인이 정상적으로 동작했다.

하지만 데스크톱 앱에서는 첫 번째 문제를 만났다.

macOS 데스크탑 앱에서 Firebase: Error (auth/popup-blocked)가 발생해.

브라우저 안에서는 가능했던 팝업 로그인이 데스크톱 앱에서는 차단됐다.

결국 앱 내부에서 팝업을 띄우는 대신 시스템 브라우저를 열어 로그인하도록 방향을 바꿨다.

데스크탑 앱에서 로그인 인증할 때 시스템 브라우저를 열어서 인증하고 싶어.

그러자 이번에는 또 다른 문제가 나타났다.

브라우저를 열 수 없습니다.
Command open_browser_login not allowed by ACL

브라우저를 여는 명령을 만드는 것만으로는 충분하지 않았다. Tauri에서는 해당 명령을 실행할 수 있도록 ACL 권한도 함께 허용해야 했다.

웹에서는 브라우저가 당연하게 제공하던 기능도 데스크톱 앱에서는 하나씩 연결하고 허용해야 했다.

키보드 동작도 달랐다

웹에서는 잘 동작하던 Delete 키가 데스크톱 앱에서는 반응하지 않았다.

웹에서는 잘되는데, 데스크탑 앱에서 노트를 선택하고 Delete 키를 누르면 반응이 없어.

처음에는 같은 HTML과 JavaScript를 사용하니 동작도 같을 것이라고 생각했다.

하지만 브라우저와 macOS WebView는 키보드 이벤트를 처리하는 방식이 완전히 같지 않았다. 텍스트 입력창에 포커스가 있는지, Delete 키가 어떤 값으로 전달되는지 하나씩 확인해야 했다.

Cmd + Z도 단순히 "삭제 복구" 단축키로 등록할 수는 없었다.

노트를 작성하고 있다면 일반적인 텍스트 편집의 실행 취소가 우선이어야 했고, 노트를 삭제한 직후라면 앱 자체의 삭제 복구가 실행되어야 했다.

브라우저보다 앱다운 경험을 만들려고 했지만, 단축키 하나에도 여러 상태를 고려해야 했다.

웹과 데스크톱의 데이터를 어떻게 동기화할 것인가

웹과 데스크톱은 같은 Workers API와 D1을 사용했다.

하지만 한쪽에서 수정한 내용이 다른 쪽에 바로 나타나지는 않았다.

각 화면은 처음 열릴 때 데이터를 가져오고, 자신이 수정했을 때만 목록을 다시 갱신하고 있었다.

그래서 실시간 동기화를 고민했다. GPT와 대화를 통해 WebSocket을 이용하기로 했다.

현재 웹에서 작성한 내용과 데스크탑 앱에서 작성한 내용이 바로 동기화되지 않는 것 같아.

웹이나 데스크탑 앱에서 수정했을 때 서로 다른 곳에 접속 중이어도 바로 업데이트되게 하고 싶어.

WebSocket을 붙이고 싶어.

WebSocket을 사용하면 변경 사항을 즉시 전달할 수 있었다.

하지만 연결 유지, 재접속, 여러 창과 여러 사용자, 이벤트 중복, 변경 순서와 충돌 처리까지 함께 해결해야 했다.

2부에서는 Local First 구조를 고민했다면, 이번에는 실시간 동기화라는 또 다른 형태의 복잡성을 마주하게 됐다.

웹과 데스크톱은 배포 방식도 달랐다

웹에서는 GitHub에 커밋하면 Cloudflare Pages를 통해 최신 버전이 배포됐다.

하지만 데스크톱 앱은 사용자의 컴퓨터에 설치되는 프로그램이었다.

배포를 통해 웹이 개선되었을 때 데스크탑 앱도 매번 빌드해야 하나?

언제 빌드해야 하는지 궁금해.

원격 웹사이트를 그대로 불러오면 웹을 수정하는 것만으로도 앱에 반영할 수 있었다.

반대로 HTML, CSS와 JavaScript를 앱 안에 포함하면 오프라인에서도 실행할 수 있었지만, 프론트엔드가 바뀔 때마다 새로운 앱을 다시 빌드해야 했다.

웹과 같은 배포 방식을 기대했지만, 데스크톱 앱은 또 다른 선택이 필요했다.

버전 업데이트도 신경쓸게 많다

사용자가 매번 새 버전을 설치하지 않아도 되도록 최신 버전 업데이트도 적용해 보고 싶었다.

데스크탑 앱에서 현재 버전을 확인하고, 최신 버전이 아니면 업데이트 버튼을 보여줄 수 있을까?

업데이트 버튼을 누르면 최신 버전으로 업데이트되게 할 수 있을까?

동시에 최초 설치도 개발 환경에서 직접 빌드하는 대신 파일을 내려받는 형태로 제공하고자 했다.

최초 한 번 설치할 때 빌드 방식이 아니라 DMG 다운로드 방식으로 할 수 있나요?

macOS 환경에 맞춘 질문

처음에는 업데이트 버튼 하나를 추가하는 정도라고 생각했다.

하지만 실제로는 버전 관리, GitHub Release 업로드, 업데이트 파일 서명, 공개키와 비밀키 관리까지 함께 구성해야 했다.

웹에서는 배포만 하면 끝났지만, 데스크톱 앱에서는 배포 이후 업데이트까지 관리할것이 더 많다.

하나의 프로젝트였지만 관리 포인트는 여러곳이었다

여러명이 사용하기 위한 데스크탑 앱을 만들기 위해서는 기본적인 화면, 기능 개발과 배포로 끝나지 않는다.

웹을 수정하면 Pages를 배포하고, API를 수정하면 Workers를 배포해야 했다.

데이터 구조가 바뀌면 Migration을 적용해야 했고, 데스크톱 앱 코드가 바뀌면 새로운 앱 버전을 빌드해야 했다.

처음에는 단순히 하나의 앱을 만드는 줄 알았지만, 실제로는 여러 실행 환경과 배포 과정을 함께 관리하는게 필요하다.

GitHub에 무엇을 올려도 될까

마지막으로 Tauri, Rust, Firebase, Cloudflare, 자동 업데이트까지 프로젝트가 커지면서 GitHub에 어떤 파일을 올려도 되는지도 다시 확인했다.

현재 프로젝트 코드를 GitHub에 올려도 되나?

Tauri, Rust 등을 설치했는데 보안상 문제가 없는지 궁금해.

이 저장소를 다른 컴퓨터에서 내려받아 실행할 수 있는지도 궁금해.

중요한 것은 코드 자체보다 비밀값과 로컬 환경 파일을 제외하는 것이었다.

Cloudflare API Token, Firebase 서비스 계정 키, 업데이트 서명 비밀키는 저장소에 포함하면 안 됐다.

반대로 프로젝트 설정과 소스 코드는 다른 컴퓨터에서도 같은 환경을 재현할 수 있도록 함께 관리해야 했다.

AI에게 기능을 구현받는 것뿐 아니라, 다른 환경에서도 다시 실행할 수 있는 프로젝트를 만드는 것도 중요한 작업이었다.

마무리

1부에서는 브라우저에서 동작하는 개인용 노트 도구를 만들었다.

2부에서는 Cloudflare와 Firebase를 연결해 여러 기기에서 사용할 수 있는 웹서비스로 확장했다.

3부에서는 같은 코드를 기반으로 macOS 데스크톱 앱까지 만들었다.

브라우저 안에서는 당연했던 기능들이 데스크톱 앱에서는 하나씩 다시 구현해야 했다. 로그인 방식도 달랐고, 키보드 이벤트도 달랐으며, 배포와 업데이트 방식도 달랐다.

이번 프로젝트를 진행하면서 가장 크게 느낀 점은 기능을 구현하는 것뿐 아니라 실행 환경이 달라질 때 고려해야 할 것 또한 매우 많다는 것이었다.

웹에서 끝났다면 고민하지 않았을 문제들이 데스크톱 앱에서는 모두 새로운 과제가 됐다. 반대로 AI 덕분에 이런 영역까지 직접 시도해 볼 수 있었고, 웹과 데스크톱이 어떻게 다른지 실제로 경험할 수 있었다.

지금은 새로운 기능을 계속 추가하기보다 실제로 이 노트 앱을 사용하면서 필요한 부분을 조금씩 다듬어 볼 생각이다. 결국 중요한 것은 많은 기능보다도, 사람들과 나눈 대화를 꾸준히 기록하게 만드는 도구가 되는 것이기 때문이다.