Tauri 2 · React 19 · CodeMirror 6 · Rust

Oxinot

로컬 우선 마크다운 아웃라이너. 폴더가 곧 사이드바, 블록이 곧 문장, .md 파일이 곧 진실. Tauri 2 셸 + React 19 + CodeMirror 6 + Rust 백엔드로 macOS(aarch64) 네이티브 앱.

역할
기획 · 설계 · 구현 전담 (단독)
환경
React 19 · Mantine UI · CodeMirror 6 · D3 · Zustand
Tauri 2 (Rust) · SQLite 인덱싱 · 시스템 webview
저장
사용자 폴더의 평문 .md 파일 (소스 오브 트루스)
라이선스
GPLv3

1. 파일 트리 — 폴더가 곧 사이드바

별도 파일 탐색기 사이드바가 없다. 워크스페이스 폴더 자체가 아웃라인이고, 메인 뷰에서 바로 펼쳐 본다. 폴더는 자기 이름의 .md 파일을 자동으로 가져 메타데이터를 적을 수 있다.

Oxinot 메인 화면 — Daily Notes / Knowledge / Projects / Research / Welcome가 펼쳐진 파일 트리
워크스페이스 인덱스 · 4개 폴더 + 4개 일일 노트 + 11개 페이지

왼쪽 사이드바 아이콘은 트리 / 검색 / 설정 / 그래프 뷰 / 일일 노트 등 핵심 진입점으로 모든 컨트롤이 타이틀바 안에 통합되어 콘텐츠 공간을 최대한 확보한다.

2. 블록 에디터 — Logseq 스타일 아웃라이너

파일을 열면 블록 단위 편집기로 들어간다. 모든 줄이 자체 ID를 가진 블록이고, Tab/Shift+Tab으로 무한 깊이로 들여쓴다. 입력하는 동시에 마크다운이 렌더링되고, Cmd/Ctrl + K로 검색, Cmd/Ctrl + P로 명령 팔레트를 연다.

Oxinot 프로젝트 페이지 — 헤더, 본문, 코드 블록, TODO 리스트를 가진 블록 에디터. 하단에는 Copilot 인라인 채팅.
블록 에디터 · 1초 디바운스 자동 저장 · 1.5초 후 폴더 단위 동기화

2.1 핵심 인터랙션

2.2 라이브 마크다운 — 입력과 동시에 렌더링

Lezer markdown 파서가 블록 콘텐츠를 파싱하고, CodeMirror 6 위에 즉시 그린다. 코드 펜스는 syntax highlight, 인용은 좌측 바, 리스트는 들여쓰기 깊이만큼 시각적으로 누적된다. 백엔드에는 유효한 CommonMark로 직렬화되어 저장된다.

3. 시스템 설계 — 프론트 / 백 / IPC

핵심 설계 원칙은 “검증은 경계에서”. 파일시스템·워크스페이스 뮤테이션은 src/tauri-api.ts의 타입드 invoke 래퍼를 거치고, 블록 뮤테이션은 스토어에서 직접 invoke를 호출한다. 그 안에서 경로 traversal / 불법 문자 / URL 스킴을 차단한다. UI 어디에도 sanitize 코드가 흩어져 있지 않다.

3.1 한 번의 Tauri invoke 처리 흐름

// 프론트 (React)
const newBlock: BlockData = await invoke('create_block', {
  workspacePath,
  request: { pageId, parentId, content: '' },
});

// 백엔드 (Rust, tauri-api.ts → src-tauri/src/commands/block.rs)
#[tauri::command]
pub async fn create_block(
  workspace_path: String,
  request: CreateBlockRequest,
) -> Result<BlockData, String> {
  // 1) SQLite 트랜잭션 시작
  // 2) 평문 .md 파일에 append
  // 3) 인덱스 갱신
  // 4) 새 BlockData 직렬화해 반환
}

한 번의 호출이 파일 + 인덱스를 atomic하게 갱신한다. 호출이 끝나면 UI는 즉시 새 상태로 re-render되고, 1초 뒤 디바운스 자동 저장이 같은 경로를 한 번 더 안전하게 덮어쓴다.

4. 라이트 모드 + 명령 팔레트

기본은 다크, 설정에서 라이트로 전환 가능 (시스템 설정 따르기 옵션도). 라이트 모드도 같은 디자인 토큰을 공유한다 — 보라색 액센트, Inter 본문 폰트, 동일한 들여쓰기 깊이 시각화.

라이트 모드 Oxinot — 흰 배경, 보라색 액센트, 동일한 블록 들여쓰기 시각화
라이트 모드 · 같은 페이지가 색 테마만 전환

명령 팔레트(Cmd/Ctrl + P)는 모든 페이지·동작을 한 곳에 모은다. 아래는 “oxinot”으로 검색한 결과 — 위키 링크 복사, 페이지 이동, 블록 액션이 한 줄로 보인다.

Oxinot 명령 팔레트 — oxinot 검색 결과: Copy link to [[Oxinot]] 페이지 액션
명령 팔레트 · fuzzy 검색으로 모든 페이지·동작 접근

5. 결과 — 데스크탑 노트 앱의 새로운 모양

~9MB
번들 크기 (.dmg 실측 8.71MB)
GPLv3
오픈소스 라이선스 · 소스 공개

왜 Oxinot을 만들었나. 기존 마크다운 에디터는 “파일 단위” 사고에 묶여 있다. 한 문장을 옮기려면 파일을 통째로 다시 써야 하고, 다른 페이지에서 참조하려면 노션·옵시디언 같은 클라우드 DB가 필요했다. Oxinot은 파일 + 블록 두 추상화를 같이 다룬다 — .md는 그대로, 단위 참조는 블록 단위로. 그리고 그게 어차피 사람이 생각하는 방식이다.

6. 레포지토리

단일 모노레포. 프론트(Vite + React) + 셸(Tauri 2 + Rust) + 자동 릴리스 파이프라인.

데스크탑 빌드는 GitHub Releases에서 macOS(aarch64)용 .dmg로 받는다. 자동 체인지셋 + 릴리스 파이프라인이 커밋 메시지에서 버전을 추론해 PR을 올린다.