ICE Canvas — 홈페이지 캔버스를 데스크톱 앱으로 2026.06.14

ICE Canvas 0.2.4 — 데스크톱 캔버스: PDF 열기부터 글자 서식·스포이드까지

웹 캔버스의 새 기능을 데스크톱으로 이식하고(아트보드·슬라이드쇼·잠금 등), PDF '열기'를 기본 앱/Edge로 여는 네이티브 명령으로 고쳤다. 이어 그룹 선 연결·색 UX·Alt 리사이즈, 다크모드 색 자동 보정·스포이드·글자 서식, 그리고 0.2.4에서 서식 단축키·부분 선택·스포이드 핸드툴·도구별 커서까지 다듬었다.

ICE Canvas는 icenovel.com의 웹 캔버스를 인터넷 없이 내 PC에서 쓰는 데스크톱 앱(Tauri 2 + 바닐라 JS)으로 옮긴 것이다. 두 캔버스는 같은 코드 혈통을 공유한다. 그래서 웹 캔버스를 크게 손본 김에 그 변화를 데스크톱에도 옮기고(0.2.1), 며칠 뒤 손에 닿는 마감들을 더 다듬어(0.2.2) 올렸다.

ICE Canvas — 아트보드·그룹·잠긴 카드, 그리고 PDF 노드의 열기/다운로드 버튼

웹에서 데스크톱으로 — 기능 패리티

0.2.1에서 데스크톱으로 넘어온 것들:

  • 아트보드(16:9) + 슬라이드쇼: 캔버스 위에 16:9 프레임을 깔고, Shift + F로 번호 순서대로 전체화면 발표를 돌린다. 방향키·휠·클릭으로 넘기고 ESC로 나온다. 메모판이 슬라이드 덱이 된다.
  • 노드 잠금(Shift + 2 토글): 배경처럼 고정하고 싶은 카드를 잠근다. 도구상자에 자물쇠 버튼도 넣었다.
  • Alt + 드래그 복제, 직접선택 라인 다중선택(드래그로 화살표 여러 개를 한 번에 골라 삭제).
  • 화살표 마무리: 곡선을 더 둥글게, 화살촉을 곡선의 실제 끝 접선에 맞추고 라인을 V노치에서 끊어 끝이 깔끔하게 모이게 했다.
  • 그룹 이름 정렬 · 직접선택으로 그룹 프레임 조정 · 그룹과 그 안 노드 정렬, 노드 내부 여백 조절.
  • 2단 도움말: 한 줄짜리 목록을 왼쪽 카테고리 메뉴 + 오른쪽 단축키 표로 다시 짰다.

슬라이드쇼 — 첫 아트보드가 전체화면으로

이식은 생각보다 깔끔했다. 펜·도형·직접선택을 담은 벡터 모듈은 데스크톱 고유 분기가 없어 웹 최신본을 통째로 가져왔고, 슬라이드쇼 모듈은 새로 추가했다. 다만 코어(app.js)는 사정이 다르다. 데스크톱은 파일을 서버에 올리는 대신 .icv 안에 base64로 품고, 저장도 네이티브 파일 대화상자로 한다. 그래서 코어는 웹 파일로 덮지 않고, 이번에 바뀐 로직만 골라 같은 자리에 이식했다 — 데스크톱의 파일 처리·네이티브 저장은 건드리지 않게.

PDF 열기를 고치다 (0.2.1)

데스크톱에서만 났던 버그다. 캔버스에 넣은 PDF의 "열기(↗)" 버튼이 아무 반응이 없었다. 원인은 저장 방식에 있었다. 데스크톱은 PDF를 data:application/pdf;base64,... 형태로 캔버스 안에 품는데, 이 버튼은 평범한 새 탭 링크(target="_blank")였다. 브라우저라면 새 탭에 PDF를 띄우지만, Tauri 웹뷰는 data URL을 새 창으로 열어주지 않는다. 그래서 클릭해도 조용했다.

고치는 방향은 단순하다 — 브라우저 흉내를 내지 말고, 운영체제에게 맡기자. 네이티브 명령 open_attachment를 추가했다:

  1. data URL을 디코드해 임시 폴더(%TEMP%\ICE Canvas\)에 실제 .pdf 파일로 쓴다.
  2. 윈도우 ShellExecuteWopen 동작으로 시스템 기본 PDF 앱을 띄운다(Acrobat이든 기본 뷰어든, 사용자가 평소 쓰는 그 앱).
  3. 확장자에 연결된 앱이 없으면(SE_ERR_NOASSOC) Microsoft Edge로 폴백한다. PDF 정도는 어느 PC에서나 Edge가 무난히 열어준다.

다운로드(⬇) 버튼은 원래대로 네이티브 저장 대화상자를 띄운다. 이제 ↗는 "보기", ⬇는 "저장"으로 역할이 분명해졌다.

0.2.2 — 손에 더 잡히게

며칠 써 보니 거슬리는 네 군데가 나왔다.

그룹에도 선을 잇는다. 전엔 화살표를 카드에만 연결할 수 있었는데, 이제 그룹끼리, 그룹과 노드를 잇는다. 그룹 가장자리에 연결점이 생기고, 거기서 끌어다 다른 그룹·노드에 떨어뜨리면 된다. 흐름도를 그릴 때 "입력 → 처리 → 결과"처럼 덩어리 단위로 잇는 게 자연스러워졌다.

그룹끼리, 그룹과 노드를 화살표로 연결

도구상자 색이 선택을 따라온다. 노드나 그룹을 고르면 왼쪽 면색·선색 스와치가 그 노드의 실제 색을 보여준다. 전엔 직전 값이 그대로 남아 있어, 색을 바꾸려면 현재 색이 뭔지 모른 채 새로 골라야 했다. 이제 선택 → 스와치에 그 색이 뜨고 → 클릭해서 바로 손본다.

글자색 드래그가 안 버벅인다. 색 피커를 끌면 입력 이벤트가 초당 수십 번 쏟아지는데, 그때마다 캔버스 전체를 다시 그리고 있었다. 노드가 많으면 끔찍하게 끊겼다. 이제 드래그 중엔 해당 노드의 화면 색만 즉시 바꾸고, 색을 확정(마우스를 뗄 때)할 때만 한 번 커밋·렌더한다. 면색·선색 피커도 같은 방식으로 바꿨다.

Alt로 중심에서 키운다. 노드·그룹 크기를 조절할 때 Alt를 누르면 중심을 고정한 채 양쪽으로 대칭으로 늘어난다. 대각 핸들을 잡으면 네 방향으로 한꺼번에. 일러스트레이터의 그 손버릇 그대로다.

0.2.3 — 색과 글자를 더 자유롭게

다크모드를 켜고 끌 때마다 거슬리던 게 있었다. 기본 카드는 테마를 따라 잘 바뀌는데, 직접 칠한 색은 그대로 남아 다크 화면에서 흰 카드만 동동 떠 있었다. 그래서 모드를 바꾸면 커스텀 면·선·글자색의 명도를 자동으로 뒤집어 대비를 맞추게 했다. 색조(hue)는 보존하고 저장값은 손대지 않으니, 라이트로 돌아오면 원래 색 그대로다. 아래는 같은 보드를 라이트/다크로 본 모습이다.

라이트 모드 — 직접 칠한 색과 글자 서식

다크 모드 — 커스텀 색이 자동으로 보정됨

완벽하진 않다. "중간 명도 면 + 극단 글자색"(파란 카드에 흰 글자 같은) 조합은 대비가 약해질 수 있다 — 명도 반전 방식의 한계다. 흔한 경우(흰·연한 카드)는 잘 맞는다.

스포이드(i). 일러스트레이터의 그 손버릇이다. 색·글자를 맞추고 싶은 노드를 고르고 i를 누른 뒤, 본받을 원본 노드를 클릭하면 그 외형 — 면색·선색·글자색·글자크기, 선굵기·라운드·여백·정렬·서식까지 — 을 통째로 복제한다.

글자 서식. 볼드·밑줄·취소선을 넣는다. 편집 중 글자를 드래그해 Ctrl+B/Ctrl+U/Ctrl+Shift+S를 누르면 그 부분만(마커 **·__·~~), 노드만 선택한 상태에선 인스펙터 B/U/S 버튼으로 노드 전체에 토글된다(노드 속성이라 마커 충돌이 없다).

0.2.4 — 글자 서식과 스포이드를 손에 붙게

며칠 더 쓰며 거슬리던 여섯 가지를 한 번에 정리했다. 홈페이지 캔버스와 똑같이 고쳤다.

0.2.4 — 글자 서식(볼드·밑줄·취소선)과 도구상자에 자리 잡은 스포이드

  • 단축키가 노드에도 듣는다. 전엔 글자를 편집 중일 때만 Ctrl+B/Ctrl+U/Ctrl+Shift+S가 먹었는데, 이제 노드만 골라도 같은 단축키로 볼드·밑줄·취소선을 토글한다.
  • 브라우저 단축키를 가로챈다. Ctrl+U(소스 보기)·Ctrl+S(페이지 저장) 같은 게 끼어들지 않도록, 서식 대상이 있을 땐 기본 동작을 막는다.
  • 일부만 골라도 그 부분에만 적용된다. 드래그로 일부 글자를 고른 뒤 인스펙터 아이콘을 눌러 편집기가 닫혀도, 그 선택 범위를 기억해 정확히 거기에만 마커(**·__·~~)를 씌운다.
  • 스포이드 + Space = 핸드툴. 스포이드 상태에서 노드 위에 있어도 Space를 누르는 동안은 화면을 끌어 옮긴다. 원본을 찾아 캔버스를 움직이다 엉뚱한 노드를 복제하던 일이 사라졌다.
  • 스포이드를 도구상자에. 왼쪽 도구막대에 스포이드 버튼을 더했다(단축키 i와 같다).
  • 도구마다 커서가 바뀐다. 펜·스포이드·직접선택이 저마다 다른 커서를 쓰고, 스포이드+Space일 땐 손 모양으로 바뀐다.

웹 빌드처럼 jsdom으로 이 여섯 가지를 코드로 눌러보고(9/9 통과), tauri build로 0.2.4 MSI를 구워 덮어 설치했다.

검증과 배포

웹과 같은 방식으로, 실제 빌드 전 헤드리스 DOM(jsdom)에 모듈을 띄워 아트보드·슬라이드쇼·잠금·라인 다중선택·정렬, PDF 버튼의 네이티브 라우팅, 그리고 0.2.2의 그룹 연결·색 동기화·글자색 라이브 갱신·Alt 중심 리사이즈까지 코드로 눌러봤다. Rust 쪽은 빌드가 통과하면 명령이 제대로 등록된 것이니 cargo가 1차 검증을 해준다.

그다음 tauri build로 MSI를 굽고(의존성 캐시 덕에 30여 초), 관리자 권한으로 조용히 덮어 설치했다. 설치된 버전이 0.2.2로 바뀐 걸 레지스트리와 실행 파일 양쪽에서 확인했다.

여전히 빌드 도구 없는 바닐라 JS와 얇은 Rust 한 겹. 웹과 데스크톱이 같은 캔버스를 공유하니, 한쪽을 손보면 다른 쪽으로 옮기는 일이 점점 수월해진다. 큰 기능을 얹는 단계는 지났고, 이제부터는 이렇게 손에 닿는 자잘한 마감을 줍는 재미다.

ICE Canvas — 홈페이지 캔버스를 데스크톱 앱으로 프로젝트로