Planche 사용 설명서

Planche의 기능을 실제 화면과 함께 설명합니다. 스크린샷은 모두 샘플 데이터베이스로 만들었고, 같은 데이터를 브라우저에서 바로 열어 볼 수 있습니다.

시작하기

Planche는 브라우저에서 쓰는 데이터베이스 클라이언트입니다. SQLite 파일은 페이지에서 바로 열고, MySQL·PostgreSQL 같은 네트워크 데이터베이스는 내 컴퓨터에서 실행하는 에이전트를 통해 연결합니다. 두 방식을 함께 사용할 수도 있습니다.

SQLite 파일 열기

.sqlite, .db, .sqlite3 파일을 페이지에 끌어다 놓거나 시작 화면에서 선택하세요. WebAssembly로 컴파일된 SQLite가 페이지 안에서 파일을 읽으므로 파일이 서버로 전송되지 않습니다. 수정 사항은 브라우저가 File System Access API를 지원하면 원본 파일에 저장할 수 있고, 지원하지 않으면 사본을 내려받습니다.

MySQL, PostgreSQL, SQL Server, Oracle, Neon, Supabase, Cloudflare D1: 명령 한 줄

브라우저는 데이터베이스에 TCP로 직접 연결할 수 없습니다. 이 연결은 로컬 에이전트가 대신 처리합니다.

npx planche

이 명령을 실행하면 에이전트가 127.0.0.1:8888에서 대기하고 페어링 링크를 출력합니다. 링크를 눌러 앱을 여세요(--open을 주면 브라우저에서 바로 열립니다). 링크에는 한 번만 쓸 수 있는 코드가 들어 있으며, 앱은 이를 에이전트 토큰과 교환합니다. 토큰 자체는 주소창이나 셸 히스토리에 남지 않습니다. 이후 브라우저는 내 컴퓨터의 127.0.0.1과만 통신하고, 에이전트가 데이터베이스에 연결합니다. 호스트 주소·계정·비밀번호도 내 컴퓨터 밖으로 전송되지 않습니다.

시작 화면. 약관에 동의한 다음, 에이전트를 실행하거나 샘플 데이터베이스를 바로 열어볼 수 있습니다.
시작 화면. 약관에 동의한 다음, 에이전트를 실행하거나 샘플 데이터베이스를 바로 열어볼 수 있습니다.

에이전트에는 Node.js 22 이상이 필요합니다. npx는 npm 레지스트리에서 에이전트를 받아 실행합니다. npx planche@latest는 최신 버전을 실행하며, 특정 버전이 필요하면 latest 대신 버전 번호를 지정하면 됩니다.

npx 대신 설치해서 쓰기

Node.js가 없거나 매번 npx를 거치지 않는 명령을 사용하고 싶다면 아래 명령으로 설치할 수 있습니다.

macOS, Linux

curl -fsSL https://planche.dev/install.sh | sh

Windows

irm https://planche.dev/install.ps1 | iex

파일은 모두 홈 디렉터리에 설치되며 관리자 권한이 필요하지 않습니다. Node.js 22 이상이 있으면 그대로 사용하고, 없으면 공식 런타임을 내려받아 nodejs.org의 체크섬으로 확인합니다. 설치 후에는 planche 명령을 레지스트리 연결 없이 바로 실행할 수 있습니다. 설치 스크립트는 에이전트도 바로 시작합니다. 새 PATH는 새 터미널에서 적용됩니다.

업데이트는 planche upgrade, 삭제는 planche uninstall이며 ~/.planche의 설정은 어느 쪽에서도 지워지지 않습니다. 새 버전이 나오면 에이전트가 하루 한 번까지만 알려주고, PLANCHE_NO_UPDATE_CHECK=1로 끌 수 있습니다. 설치 스크립트는 평범한 텍스트라 실행 전에 읽어볼 수 있습니다: curl -fsSL https://planche.dev/install.sh -o install.sh.

인터넷이 없거나 planche.dev가 차단된 경우에는 에이전트가 이를 감지해 자체 주소에서 앱 사본을 제공합니다. 이 경우에도 작업할 수 있지만 샘플 데이터베이스는 포함되지 않습니다. 앱 버전은 에이전트 버전과 같으므로 npx planche@latest로 실행하면 최신 버전을 사용할 수 있습니다.

사내망·폐쇄망에서 쓰기

외부 네트워크가 필요한 단계는 에이전트를 가져올 때뿐입니다. npx가 npm 레지스트리에서 패키지를 내려받기 때문입니다. 이 경로가 막혀 있다면 npm에 연결되는 컴퓨터에서 설치해 옮기거나(npm i -g planche), npm pack planche으로 tarball을 만들어 반입하거나 사내 레지스트리에 게시하면 됩니다.

그 뒤에는 외부 네트워크 통신이 필요하지 않습니다. 에이전트가 자체 주소에서 앱을 제공하며, 페이지는 내 컴퓨터 밖으로 요청을 보내지 않습니다. 에디터, SQLite 엔진, 아이콘은 모두 번들에 포함돼 CDN·웹 폰트·사용 통계를 사용하지 않습니다. --serve-app을 지정하면 접속 확인 없이 처음부터 로컬 앱을 제공합니다. 캡티브 포털처럼 요청을 차단하지 않고 가로채는 네트워크에서도 이 옵션을 사용할 수 있습니다.

쓸 수 없게 되는 것은 인터넷이 반드시 필요한 기능입니다. 호스팅 서비스(Neon, Supabase, Cloudflare D1), 외부 서버로의 SSH, 샘플 데이터베이스가 여기에 해당합니다. 망 안에 있는 데이터베이스는 팀 전체가 쓰는 게이트웨이를 포함해 다른 환경과 똑같이 동작합니다.

작업 화면

브라우저 탭 하나에서 여러 데이터베이스 연결을 열어 둘 수 있습니다. 연결을 열면 툴바 아래에 탭이 생기고, 탭을 눌러 해당 데이터베이스로 전환합니다.

샘플 데이터베이스를 연 화면. 위쪽에 연결 탭, 왼쪽에 스키마 트리, 가운데에 SQL 에디터, 아래에 결과.
샘플 데이터베이스를 연 화면. 위쪽에 연결 탭, 왼쪽에 스키마 트리, 가운데에 SQL 에디터, 아래에 결과.

연결마다 작업 상태를 따로 유지합니다. 다른 연결로 갔다가 돌아와도 열어 둔 쿼리 탭, 작성 중인 SQL, 조회 결과가 그대로 남아 있습니다.

  • 스키마 트리(왼쪽). 이 연결의 데이터베이스, 테이블, 뷰, 프로시저 같은 객체 목록입니다. 클릭하면 펼쳐지고, 우클릭하면 그 객체에 할 수 있는 동작이 나옵니다.
  • 쿼리 탭(오른쪽 위). 탭 하나가 SQL 에디터 하나입니다. 필요한 만큼 열 수 있습니다. 트리에서 “Open Table”로 연 탭은 에디터 대신 그 테이블의 행을 그리드로 보여 줍니다.
  • 결과 패널(아래). Message에는 각 문장이 무엇을 했는지(영향받은 행 수, 오류, 소요 시간)가 쌓이고, 옆에 Info와 History가 있습니다. 결과 집합이 돌아올 때마다 Result 탭이 하나씩 생깁니다.
  • 푸터 — 지금 보고 있는 연결의 이름, 읽기 전용이거나 트랜잭션이 열려 있을 때 붙는 배지, 마지막 상태 메시지가 표시됩니다.

브라우저를 닫아도 작업 상태는 유지됩니다. 다시 열면 연결과 쿼리 탭, 작성한 SQL이 복원됩니다. 파일에서 연 SQLite 데이터베이스도 파일 접근 권한을 다시 허용하기 전까지는 로컬 사본에서 복원됩니다.

데이터베이스 접속하기

Connection › Connect(Alt + N)에서 연결 관리자를 열고 Add New를 누른 뒤 DBMS를 선택하세요. 폼에는 선택한 엔진에 필요한 항목만 표시됩니다. Test Connection은 접속 여부만 확인하고, Connect는 연결 탭을 엽니다.

MySQL 프로필을 만드는 중. 왼쪽 목록에 저장된 프로필이 쌓이고, 오른쪽 폼은 고른 엔진에 따라 바뀝니다.
MySQL 프로필을 만드는 중. 왼쪽 목록에 저장된 프로필이 쌓이고, 오른쪽 폼은 고른 엔진에 따라 바뀝니다.

엔진별로 입력할 항목

  • MySQL / MariaDB — 호스트, 포트(3306), 사용자, 비밀번호. 데이터베이스 항목은 비워도 되고, 비우면 트리에 전체 데이터베이스가 나옵니다. 문자셋 기본값은 utf8mb4입니다.
  • PostgreSQL — 호스트, 포트(5432), 사용자, 비밀번호에 더해 데이터베이스를 반드시 지정해야 합니다. PostgreSQL 세션은 접속한 뒤에 데이터베이스를 바꿀 수 없기 때문입니다. 대신 그 데이터베이스 안의 스키마들이 트리에서 “데이터베이스” 자리에 표시되고, 스키마를 옮길 때는 Planche가 SET search_path를 실행합니다.
  • SQL Server — 호스트, 포트(1433), 로그인, 비밀번호, 데이터베이스. PostgreSQL과 마찬가지로 스키마(dbo 등)가 “데이터베이스” 자리에 옵니다. Azure SQL이라면 TLS를 켜고, 사설 인증서를 쓰는 서버라면 서버 인증서 검증은 꺼 두세요.
  • Oracle — 호스트, 포트(1521), 사용자, 비밀번호, 그리고 서비스 이름(예: FREEPDB1). 에이전트가 자바스크립트로만 구현된 thin 드라이버를 쓰므로 Instant Client를 따로 설치하지 않아도 됩니다. Oracle에서는 스키마가 곧 사용자이며, 스키마를 옮길 때 ALTER SESSION SET CURRENT_SCHEMA가 실행됩니다.
  • SQLite — 파일을 여는 방식을 고릅니다. 브라우저에서는 아무것도 설치하지 않는 대신 파일을 메모리에 복사해 다룹니다. 에이전트를 통해는 에이전트가 실행 중인 컴퓨터에서 진짜 SQLite가 파일을 직접 열기 때문에 잠금과 WAL이 정상 동작하고, 그 파일을 쓰는 다른 프로그램과 함께 써도 안전합니다. 이때는 파일 경로를 입력하며, 파일이 없으면 새로 만들게 할 수도 있습니다.
  • Neon / Supabase — 콘솔에서 복사한 연결 문자열을 붙여넣으면 호스트·사용자·비밀번호·데이터베이스가 자동으로 채워집니다. TLS는 항상 켜져 있고 SSH 설정은 없습니다. Supabase에서는 세션 풀러(5432 포트)나 직접 연결을 쓰세요. 6543 포트는 트랜잭션 풀러라 문장마다 다른 백엔드로 갈 수 있고, 그러면 스키마 전환·임시 테이블·수동 트랜잭션이 동작하지 않습니다. 이 포트를 고르면 Planche가 경고를 띄웁니다.
  • Cloudflare D1 — 계정 ID, 데이터베이스 ID, 그리고 D1 Edit 권한(읽기만 할 거라면 D1 Read)이 있는 API 토큰. 에이전트가 이 토큰으로 Cloudflare REST API를 호출하는 방식이라 TCP 접속도 SSH도 없습니다. D1은 요청마다 자동 커밋되므로 수동 트랜잭션 기능은 꺼집니다.
  • Redis — 호스트, 포트(6379), 비밀번호, 그리고 서버에 ACL 사용자가 있으면 그 사용자 이름(default 사용자라면 비워 둡니다). 데이터베이스 항목은 처음 열 논리 데이터베이스입니다(db0). TLS와 SSH는 SQL 엔진과 똑같이 동작합니다.
  • Elasticsearch / OpenSearch — 호스트와 포트(9200). 사용자와 비밀번호를 입력하면 basic auth로 로그인하고, 사용자를 비워 두면 비밀번호를 API 키(인코딩된 id:key)로 보냅니다. https라면 TLS를 켜세요. Elasticsearch 8이 기본으로 쓰는 자체 서명 인증서라면 서버 인증서 검증은 꺼 두세요.
  • Cloudflare DO (wrangler dev) — wrangler dev 서버 URL(기본값 http://localhost:8787)만 필요하며 계정 ID, 토큰, 비밀번호는 없습니다. 로컬 wrangler dev 세션만 읽고 배포된 Durable Objects는 지원하지 않으며, 각 객체가 별도 데이터베이스로 표시됩니다.

비밀번호와 토큰

  • Save password를 꺼 두면 비밀번호는 탭을 닫을 때까지만 유지되고, 켜면 프로필과 함께 이 브라우저에 저장됩니다. 어느 쪽이든 비밀번호는 내 에이전트에만 전달됩니다.
  • Agent token은 비워 두면 페어링할 때 받은 토큰을 씁니다. 에이전트를 여러 개 띄웠거나 수동으로 페어링한 경우에만 직접 입력하세요.
  • 읽기 전용, 환경 색상, 트랜잭션 모드는 프로필마다 따로 지정합니다. 안전 절에서 설명합니다.

SSH 터널

배스천 호스트(Bastion Host)를 통해서만 접근할 수 있는 데이터베이스에는 SSH 터널을 사용합니다. 프로필에서 SSH tunnel을 켜고 배스천 호스트 정보를 입력하면 로컬 에이전트가 터널을 열어 데이터베이스에 연결합니다. 데이터베이스 포트를 외부에 공개할 필요가 없습니다.

SSH 영역. 배스천 호스트 주소와 사용자, 인증 방식을 입력합니다. 위쪽의 호스트·포트는 배스천 호스트에서 봤을 때의 데이터베이스 주소를 뜻합니다.
SSH 영역. 배스천 호스트 주소와 사용자, 인증 방식을 입력합니다. 위쪽의 호스트·포트는 배스천 호스트에서 봤을 때의 데이터베이스 주소를 뜻합니다.

입력 항목

  • SSH Host / Port — 배스천 호스트 주소입니다. ~/.ssh/config에 적어 둔 Host 별칭을 그대로 입력해도 됩니다. Planche가 ssh 명령과 같은 방식으로 그 별칭을 해석해 HostName, User, Port, IdentityFile을 채워 넣습니다. Include로 나뉜 설정 파일도 따라갑니다. 다만 ProxyJump(다단계 경유)는 지원하지 않습니다.
  • SSH User — 비워 두면 설정 파일의 해당 Host 블록에 적힌 사용자를 씁니다.
  • SSH Auth — 인증 방식을 세 가지 중에서 고릅니다.
    • 개인 키: 키 파일을 직접 고르거나, 비워 두면 설정 파일의 IdentityFile을 쓰고 그것도 없으면 ~/.ssh/id_*를 찾습니다. 키에 암호가 걸려 있으면 passphrase 칸에 입력합니다.
    • ssh-agent: npx planche를 실행한 컴퓨터의 ssh-agent 소켓(SSH_AUTH_SOCK)을 그대로 사용합니다. 하드웨어 키나 포워딩해 온 에이전트도 이 방식으로 쓸 수 있습니다.
    • 비밀번호: 배스천 호스트 계정의 비밀번호를 입력합니다.
  • 폼 위쪽의 데이터베이스 호스트와 포트는 배스천 호스트에서 해석됩니다. 그래서 보통 127.0.0.1이나 내부망 도메인을 적게 됩니다.

호스트 키

처음 연결하는 배스천 호스트라면 서버 지문(fingerprint)을 보여 주고 신뢰 여부를 묻습니다. 수락한 키는 ~/.planche/known_hosts에 저장되고 기존 ~/.ssh/known_hosts도 함께 읽습니다. 이후 같은 호스트의 키가 바뀌면 다시 묻지 않고 연결을 거부합니다. ssh 명령과 같은 방식입니다.

알아두면 좋은 것

  • 키 파일 내용과 passphrase는 Save password 설정을 따르며, 브라우저에서 내 로컬 에이전트로만 전달됩니다.
  • 터널은 데이터베이스 연결을 닫을 때 함께 닫힙니다.
  • SSH 인증에 실패하면 데이터베이스 오류와 구분해서 알려 줍니다. 계정 문제인지 DB 문제인지 헷갈릴 일이 없습니다.
  • 에이전트가 ~/.ssh/config와 기본 키를 아예 읽지 않게 하려면 실행 전에 환경 변수 PLANCHE_SSH_CONFIG=none을 지정하세요.

wrangler dev의 Cloudflare Durable Objects

Cloudflare DO (wrangler dev)는 로컬 개발 전용입니다. 내 컴퓨터에서 실행 중인 wrangler dev 세션의 Durable Objects를 읽습니다. 배포된 Durable Objects는 지원하지 않습니다.

객체마다 데이터베이스로 보이는 이유

각 Durable Object는 자체 비공개 SQLite 데이터베이스를 하나씩 가지므로 스키마 트리에는 객체가 각각 별도 데이터베이스로 나타납니다. 이름이 있는 객체는 <namespaceId>/<object> 형식입니다. 예를 들어 do-probe-Counter/probe-one은 do-probe-Counter 네임스페이스의 probe-one 객체이며, 네임스페이스 ID는 <script>-<ClassName>입니다. 일반적인 데이터베이스 이름이 아니라 idFromName()에 전달한 객체 이름입니다. newUniqueId()로 만든 객체는 이름이 없어서 64자리 16진수 ID로 나타납니다.

wrangler는 개발 레지스트리를 유지합니다. 동시에 실행 중인 다른 wrangler dev 세션의 Durable Objects도 표시되므로 Planche 프로필 하나로 여러 로컬 프로젝트를 살펴볼 수 있습니다.

연결

  1. Worker 프로젝트에서 wrangler dev를 실행합니다.
  2. npx planche를 실행한 뒤 Cloudflare DO (wrangler dev) 연결을 만듭니다.
  3. wrangler dev 서버 URL을 입력합니다. 기본값은 http://localhost:8787입니다. 계정 ID, API 토큰, 비밀번호, SSH 설정은 없습니다.

로컬 에이전트는 <devUrl>/cdn-cgi/local/explorer/api에 있는 wrangler의 Local Explorer API를 읽으므로 Worker 쪽에 구성 요소를 설치하거나 배포할 필요가 없습니다. URL은 루프백이어야 합니다. 그렇지 않으면 에이전트가 임의의 호스트로 요청을 전달하는 HTTP 프록시가 되기 때문입니다.

아무것도 수신하지 않으면 다음 오류가 나옵니다: Cannot reach a wrangler dev server at http://localhost:8787 (fetch failed). Run `wrangler dev` in your Worker project and try again.

포트가 다른 서버의 것이면 다음 오류가 나옵니다: ... answered (HTTP 401) but is not a wrangler dev server. Check the port, and that `wrangler dev` (wrangler 4.x) is what is running there.

SQLite 도구와 스토리지

Durable Object 스토리지는 SQLite이므로 SQL 편집기와 ctx.storage.sql 테이블은 다른 SQLite 데이터베이스처럼 동작합니다. Planche는 sqlite_master와 PRAGMA로 테이블, 뷰, 트리거, 컬럼, 인덱스를 읽고, CREATE TABLE DDL과 외래 키 기반 ERD를 지원하며, 단일 테이블 SELECT 결과를 원본 테이블과 연결해 그리드에서 행을 편집할 수 있게 합니다.

Planche는 miniflare의 내부 관리 테이블 __miniflare_do_name을 트리에서 숨깁니다. ctx.storage.put() 데이터가 들어 있는 _cf_KV는 볼 가치가 있으므로 숨기지 않습니다.

모든 요청은 자동 커밋됩니다. BEGIN, COMMIT, ROLLBACK은 설명과 함께 거부되고 Cloudflare D1과 마찬가지로 수동 트랜잭션 옵션도 숨겨집니다.

배포된 객체를 지원하지 않는 이유

Cloudflare 공개 API에 문서화된 Durable Objects 메서드는 네임스페이스 목록과 객체 목록, 두 가지뿐입니다. 객체의 스토리지를 쿼리하는 문서화된 SQL 엔드포인트는 없습니다.

Cloudflare 대시보드에는 배포된 객체를 쿼리하는 Data Studio 탭(Beta)이 있고 그 내부 엔드포인트는 API 토큰으로 접근할 수 있습니다. 하지만 공개 API 레퍼런스에 없고 예고 없이 바뀔 수 있습니다. Durable Objects 전용 토큰 권한도 없습니다. D1의 D1 Read/D1 Edit, Workers KV와 R2의 전용 권한과 달리 이 엔드포인트를 여는 유일한 권한은 Workers Scripts Edit입니다. 이는 계정의 모든 Worker를 배포하고 수정할 수 있는 쓰기 권한입니다. Planche는 데이터를 보기 위해 이 권한을 요구하지 않습니다.

현재 배포된 객체에 접근하려면 대시보드의 Data Studio를 사용하거나 Worker에서 직접 엔드포인트를 노출하세요.

Redis

Redis 프로필은 Redis 6, 7과 같은 프로토콜을 쓰는 서버(Valkey, KeyDB, Dragonfly)에서 동작합니다. 에이전트는 프로필마다 연결 하나를 유지하고, Pub/Sub이나 Monitor 탭이 열려 있는 동안에는 연결을 하나 더 씁니다.

키 트리

트리에는 논리 데이터베이스(기본값 db0~db15)가 키 개수와 함께 나옵니다. 데이터베이스를 펼치면 키가 첫 번째 : 구간(user:, session:)별로 묶이고, 각 묶음도 같은 방식으로 펼쳐집니다. 모든 단계는 SCAN으로 1,000개씩 읽으며, 10,000개에 이르면 멈추고 그 사실을 표시합니다. Planche는 KEYS를 실행하지 않습니다. KEYS는 전체 키 공간을 다 훑을 때까지 서버를 막습니다. 키 이름은 세션 사이에 저장되지 않습니다.

키 뷰어

키를 더블클릭하면 별도 탭에서 열립니다. 헤더에는 타입, TTL, 길이, 메모리(MEMORY USAGE)가 표시됩니다. TTL과 이름은 여기서 바꿀 수 있고, 키는 확인을 거쳐 삭제할 수 있습니다. 이름 변경에는 RENAMENX를 쓰므로 이미 있는 키를 덮어쓰지 않습니다.

  • 해시, 셋, 정렬된 셋 — HSCAN / SSCAN / ZSCAN으로 읽은 테이블입니다. 필터(일반 텍스트, 또는 a* 같은 glob)와 Load more가 있습니다. 값과 점수는 그 자리에서 편집하고, 행은 테이블에서 추가하고 삭제합니다.
  • 리스트 — 인덱스와 값을 200개씩 읽습니다. 요소를 편집하거나 양쪽 끝에 넣거나 삭제할 수 있습니다. Redis는 리스트 요소를 값으로만 삭제할 수 있어서, 삭제할 때는 먼저 요소를 고유한 표식 값으로 덮어쓴 뒤 그 표식을 삭제합니다. 명령이 두 번 나가므로, 그 사이에 다른 클라이언트가 리스트를 밀어내면 인덱스가 어긋날 수 있습니다.
  • 스트림 — 최신 항목부터 필드와 함께 보여 줍니다. 항목을 추가(field value; field value)하거나 삭제할 수 있습니다.
  • 문자열과 RedisJSON — JSON 값은 접고 펼 수 있는 트리로, HTML 값은 렌더링된 페이지로 열립니다. 편집하려면 Text로 전환하세요. 1MB가 넘는 값은 첫 1MB만 불러오고, 나머지는 요청할 때 불러옵니다. HTML은 스크립트를 실행하지 않고 다른 호스트에서 아무것도 불러오지 않는 샌드박스 프레임에서 렌더링됩니다.

콘솔

Redis 연결의 쿼리 탭은 콘솔입니다. 한 줄에 명령 하나를 redis-cli 문법으로 씁니다(큰따옴표 안에서는 \n, \xHH 이스케이프를 쓰고, 작은따옴표는 그대로 읽습니다). #과 // 주석을 쓸 수 있습니다. Ctrl / ⌘ + Enter는 커서가 있는 줄의 명령을 실행하고, 스크립트 전체를 실행하면 명령을 하나씩 차례로 실행합니다. SELECT n을 실행하면 탭이 그 데이터베이스로 옮겨 갑니다. 객체 하나로 된 응답은 JSON으로, 레코드는 테이블로 열리며, 결과 위의 Table / JSON 스위치로 바꿀 수 있습니다.

SUBSCRIBE, PSUBSCRIBE, MONITOR는 콘솔에서 거부됩니다. 이 명령들은 연결을 계속 점유하므로 트리와 다른 모든 탭이 멈추게 됩니다. 대신 Pub/Sub과 Monitor 도구를 쓰세요.

도구

트리의 빈 곳을 우클릭하거나 Tools 메뉴를 쓰세요.

  • Server info — INFO를 카드(버전, 메모리, 적중률, 초당 작업 수, 영속성, 복제)로 보여 주고, 데이터베이스별 키 개수와 전체 필드를 필터와 함께 보여 줍니다. 켜 두면 5초마다 새로 고칩니다.
  • Slow log — SLOWLOG GET의 최신 항목 128개를 실행 시간, 클라이언트와 함께 보여 주고, 항목이 기록되는 기준값도 표시합니다. 비우기 전에는 확인을 받습니다.
  • Clients — CLIENT LIST입니다. 다른 클라이언트는 확인을 거쳐 연결을 끊을 수 있습니다. 앱 자신의 연결은 표시되며 여기서 끊을 수 없습니다.
  • Pub/Sub — 채널과 glob 패턴(news orders.*)을 구독해 도착하는 메시지를 봅니다. 채널에 메시지를 발행하고 구독자 몇 명이 받았는지 확인할 수 있습니다.
  • Monitor — 모든 클라이언트가 실행하는 모든 명령을 실행되는 대로 보여 줍니다. Redis는 명령마다 모든 모니터에 복사본을 보내므로, 바쁜 서버에서는 처리량이 줄어듭니다. 잠깐만 켜 두세요. 이벤트가 에이전트의 한도인 100ms당 500개를 넘으면 건너뛴 명령 수가 표시됩니다.
  • Memory analysis — 데이터베이스를 스캔하고(최대 10,000, 100,000, 1,000,000개 키) 키마다 크기, 타입, 만료를 일괄로 조회합니다. 타입별, 접두사별, 만료별 메모리와 가장 큰 키 50개를 보여 줍니다. 키 20,000개에 약 1초가 걸립니다. MEMORY USAGE는 큰 컬렉션의 크기를 요소 일부를 표본으로 추정합니다. 키를 클릭하면 열리고, 접두사를 클릭하면 그 키들을 삭제할 수 있습니다.
  • Delete keys by pattern — 패턴에 맞는 키를 찾고(한 번에 최대 100,000개), 개수와 그중 20개를 보여 준 뒤 패턴을 다시 입력하게 하고, UNLINK로 500개씩 삭제합니다. 기록에는 실행 한 번이 항목 하나로 남습니다. 데이터베이스나 접두사 노드의 메뉴에도 있습니다.

안전

읽기 전용 프로필은 Planche의 읽기 명령 목록에 있는 명령만 받아들이고, 게이트웨이 에이전트는 각 명령을 서버 자신의 COMMAND INFO 플래그와 대조합니다. FLUSHDB, FLUSHALL, SWAPDB, SHUTDOWN 같은 명령은 실행 전에 확인을 받습니다. AUTH, HELLO … AUTH, MIGRATE … AUTH, CONFIG SET requirepass, ACL SETUSER의 비밀번호는 기록에서 가려집니다.

아직 지원하지 않는 것

Redis Cluster와 Sentinel. 클러스터 노드에 연결하면 Planche는 db0에 그 노드의 키만 보여 주고, 다른 노드가 가진 키는 리디렉션을 따라가는 대신 그 노드를 알려 줍니다.

스키마 트리

스키마 트리 구조는 엔진마다 다릅니다. MySQL과 SQLite는 데이터베이스 › 객체 두 단계이고, PostgreSQL과 SQL Server는 중간에 스키마 단계가 있습니다. 폴더 옆 숫자로 펼치기 전에도 테이블 수를 확인할 수 있습니다.

샘플 데이터베이스의 테이블·뷰·트리거 목록과 각 폴더의 개수.
샘플 데이터베이스의 테이블·뷰·트리거 목록과 각 폴더의 개수.

노드를 우클릭하면 해당 객체에서 사용할 수 있는 동작만 표시됩니다.

  • Open Table — 설정한 행 제한만큼 조회해 데이터 그리드로 엽니다.
  • Generate SQL — 그 테이블의 실제 컬럼과 기본키를 읽어 SELECT·INSERT·UPDATE·DELETE 문의 뼈대를 만들고 커서 위치에 넣어 줍니다.
  • Show Create / Alter — 객체를 만든 DDL을 보여 주거나, 테이블 디자이너를 엽니다.
  • Copy Table to… / 테이블 비교 / 데이터 비교 — 뒤쪽 절에서 설명합니다.
  • Truncate / Drop — 실수로 누르지 않도록 메뉴 맨 아래에 따로 떨어져 있고, 실행하려면 객체 이름을 다시 입력해야 합니다.

SQL 에디터

에디터는 VS Code와 같은 Monaco를 사용하며 앱에 포함돼 있습니다. 자동완성에는 현재 방언의 키워드와 함수, 연결된 데이터베이스의 실제 테이블·컬럼 이름이 표시됩니다.

접속한 데이터베이스의 스키마에서 가져온 자동완성 목록.
접속한 데이터베이스의 스키마에서 가져온 자동완성 목록.

문장 실행하기

  • Ctrl / ⌘ + Enter — 선택한 부분을 실행하고, 선택한 것이 없으면 커서가 놓인 문장 하나만 실행합니다.
  • F9 — 설정 › 안전 › 실행 범위에서 정한 대로 실행합니다. 기본값은 스크립트 전체입니다.
  • Ctrl / ⌘ + Shift + Enter — 설정과 상관없이 스크립트 전체를 실행합니다.

여러 문장을 나눌 때 단순히 세미콜론만 보지 않고 파서로 분석합니다. 따라서 BEGIN … END 안의 세미콜론, 클라이언트 DELIMITER 명령, PostgreSQL의 $$ 달러 인용, SQL Server의 GO, /로 끝나는 Oracle PL/SQL 블록도 올바르게 처리합니다. 문장 종류를 구분해 두기 때문에 행 제한, 파괴적 문장 확인, 드라이런도 적용할 수 있습니다.

행 제한

제한이 없는 SELECT에는 LIMIT(SQL Server는 TOP, Oracle은 FETCH FIRST)을 자동으로 추가합니다. 큰 테이블에 SELECT *를 실행해도 브라우저가 멈추지 않게 하기 위해서입니다. 기본값은 500행이며 제한이 적용되면 결과에 표시됩니다. 이미 LIMIT을 지정한 문장은 바꾸지 않습니다.

실행 기록과 편집 기록

실행한 문장마다 소요 시간, 행 수, 어느 연결에서 실행했는지가 남습니다.
실행한 문장마다 소요 시간, 행 수, 어느 연결에서 실행했는지가 남습니다.

History 탭에는 실행한 문장이 기록됩니다. Query › Local History는 각 쿼리 탭의 SQL을 시점별로 보관하므로, 지운 쿼리나 실행 직전 내용을 복원할 수 있습니다. 저장하기 전에 비밀번호처럼 보이는 문자열은 가려지며, 설정에서 기록 기능을 끌 수도 있습니다.

결과 그리드

그리드는 화면에 보이는 영역만 렌더링하므로 수십만 셀도 부드럽게 스크롤할 수 있습니다. 결과의 모든 컬럼이 같은 테이블에서 왔고 기본 키가 있으면 값을 바로 수정할 수 있습니다.

트리에서 연 테이블. 위쪽에 편집 버튼, 검색, 정렬, 컬럼 표시 설정이 있습니다.
트리에서 연 테이블. 위쪽에 편집 버튼, 검색, 정렬, 컬럼 표시 설정이 있습니다.

값 고치기

셀을 더블클릭하면 그 자리에서 편집할 수 있습니다. 클릭해 둔 셀에서 F2나 Enter를 눌러도 됩니다. 행을 추가할 때는 Add row나 Add with form을, 삭제할 때는 행을 선택한 뒤 삭제를 누릅니다. 여기까지는 아무것도 데이터베이스에 반영되지 않습니다. Commit을 눌러야 실행되고, 기본 설정에서는 실행 직전에 생성된 UPDATE·INSERT·DELETE 문을 보여 줍니다. Discard를 누르면 편집한 내용을 버립니다.

행 선택과 복사

화면의 글자는 드래그로 선택되지 않습니다. 그래서 그리드 위에서 마우스를 끌어도 엉뚱한 텍스트가 잡히지 않습니다. 행은 클릭으로 선택합니다. 한 행을 클릭한 뒤 다른 행을 Shift+클릭하면 두 행 사이가 전부 선택되고, ⌘ / Ctrl+클릭은 그 행만 선택에 넣거나 뺍니다. 이후 셀 우클릭 메뉴에서 고른 동작은 선택한 행 전체에 적용됩니다.

셀 우클릭 메뉴. 링크 따라가기, 값으로 필터, 복사, 편집, 컬럼 숨기기가 한자리에 있습니다.
셀 우클릭 메뉴. 링크 따라가기, 값으로 필터, 복사, 편집, 컬럼 숨기기가 한자리에 있습니다.
  • 필터: 컬럼 = 이 값 — 클릭한 셀의 값과 정확히 일치하는 행만 다시 조회합니다.
  • 복사 — 셀 값 하나, 컬럼 이름, 또는 선택한 행들을 TSV(헤더 포함)·CSV·JSON·바로 실행 가능한 INSERT 문 중 원하는 형식으로 복사합니다.
  • 편집 / NULL로 설정 / 빈 문자열로 설정 / 행 삭제 — 모두 커밋 전까지는 대기 상태로만 표시됩니다.
  • 스크래치패드로 보내기 — 다음 절에서 설명합니다.
  • 컬럼 숨기기 — 툴바의 Columns 버튼에서 다시 켤 수 있습니다.

지난 조회 이후 바뀐 값 표시

테이블 탭에서 Refresh를 누르면 새로 읽은 행과 직전 결과를 기본 키로 비교합니다. 바뀐 셀은 배경색으로 표시되고, 마우스를 올리면 이전 값도 볼 수 있습니다. 새 행에는 별도 표시가 붙고 사라진 행 수는 툴바 배지에 나타납니다. 배포나 배치 작업 뒤의 변화를 확인하기 좋습니다. 비교 결과는 해당 탭에만 남으며 배지 옆 ×로 지울 수 있습니다.

스크래치패드

스크래치패드는 브라우저 안에서 동작하는 SQLite 데이터베이스입니다. 어느 그리드에서나 한 행, 선택한 행, 불러온 전체 행을 복사해 올 수 있습니다.

서버 테이블에서 보낸 행이 스크래치패드의 테이블이 되어, 자유롭게 조회할 수 있는 상태가 됩니다.
서버 테이블에서 보낸 행이 스크래치패드의 테이블이 되어, 자유롭게 조회할 수 있는 상태가 됩니다.

컬럼 타입은 원본 컬럼 타입을 기준으로 정해지며 새 테이블은 즉시 스크래치패드 스키마 트리에 나타납니다. 일반 브라우저 SQLite 연결처럼 조회하고 편집할 수 있고, Connection › Save Database File로 .db 파일에 저장할 수도 있습니다. 내용은 브라우저에 캐시되며 외부로 전송되지 않습니다.

Tools › 스크래치패드로 언제든 열거나 그 탭으로 이동할 수 있습니다.

Federated 쿼리 — 연결 간 조인

스크래치패드의 쿼리 탭에서는 열려 있는 다른 연결의 테이블을 "연결 이름".데이터베이스.테이블 형식으로 적어 조인할 수 있습니다.

SELECT o.id, o.total, u.email
FROM "Shop MySQL".shop.orders o
JOIN "User service".public.users u ON u.id = o.user_id
WHERE o.status = 'paid';

실행 직전에 지정한 테이블을 스크래치패드로 복사한 뒤, SQL이 그 사본을 조회하도록 바꿉니다. 조인은 브라우저 안의 SQLite가 처리하므로 MySQL과 PostgreSQL 테이블도 서버 쪽 설정 없이 함께 조회할 수 있습니다.

원격 테이블을 스크래치패드로 가져와 국가별로 집계한 결과.
원격 테이블을 스크래치패드로 가져와 국가별로 집계한 결과.

사본은 실행할 때마다 새로 가져오며 테이블 하나당 최대 10만 행을 읽습니다. 진행 상황은 푸터에 표시됩니다. Tools › Federated 쿼리를 선택하면 이 문법과 현재 열린 연결 이름이 미리 입력된 탭이 열립니다.

비교와 복사

아래 기능은 스크립트만 생성하며 자동으로 실행하지 않습니다. 내용을 확인하고 필요하면 수정한 뒤 직접 실행하세요.

스키마 비교

두 데이터베이스의 객체 목록. 대상에 없는 것, 정의가 다른 것, 대상에만 있는 것으로 나뉘어 표시됩니다.
두 데이터베이스의 객체 목록. 대상에 없는 것, 정의가 다른 것, 대상에만 있는 것으로 나뉘어 표시됩니다.

Database › 스키마 비교(또는 트리의 “테이블 비교…”)는 열린 두 연결의 테이블·컬럼·인덱스·뷰·프로시저·함수·트리거·이벤트를 비교합니다. CREATE 문은 DEFINER, SQL SECURITY, ALGORITHM, 데이터베이스 접두사처럼 서버마다 달라지는 부분을 제외하고 비교하므로 의미 있는 차이만 볼 수 있습니다. 스크립트를 편집기에서 열기를 누르면 대상 방언에 맞는 ALTER·CREATE 문을 새 쿼리 탭에 넣습니다. DROP 문은 체크박스를 켜기 전까지 주석 처리됩니다.

데이터 비교

원본 테이블의 기본키로 행을 짝지어 비교한 결과.
원본 테이블의 기본키로 행을 짝지어 비교한 결과.

Database › 데이터 비교는 원본 테이블의 기본 키로 양쪽 행을 연결해 값을 비교합니다. 날짜, 소수, JSON처럼 드라이버별 표현이 다른 값은 정규화한 문자열로 비교하므로 표현 차이만으로 다른 값으로 표시되지 않습니다. 결과는 대상에 없는 행, 값이 다른 행, 대상에만 있는 행으로 나뉘며 INSERT·UPDATE·DELETE 스크립트도 생성합니다. DELETE는 기본적으로 주석 처리됩니다. 한쪽당 최대 5만 행을 읽고 진행률을 표시합니다.

테이블 복사

다른 연결에 같은 테이블을 만드는 화면. 구조만 복사할지 데이터까지 복사할지 고릅니다.
다른 연결에 같은 테이블을 만드는 화면. 구조만 복사할지 데이터까지 복사할지 고릅니다.

테이블을 우클릭해 Copy Table to…를 고르면, 열려 있는 다른 연결이나 다른 데이터베이스에 같은 테이블을 만듭니다. CREATE TABLE 문은 복사 대상 방언으로 생성되어 편집 가능한 상태로 보이므로, 타입만 조금 손보면 MySQL 테이블을 PostgreSQL로 옮길 수 있습니다. 데이터는 나눠서 전송되며 진행률이 표시됩니다. 같은 이름의 테이블이 이미 있으면 복사를 중단합니다. “삭제 후 다시 생성”을 고른 경우에는 테이블 이름을 다시 입력해야 진행됩니다.

AI 어시스턴트

오른쪽 패널은 SQL을 작성하는 데 그치지 않고 앱을 직접 다룹니다. 스키마를 읽고, 쿼리 탭을 열어 문장을 실행하며, 데이터를 바꾸기 전에는 승인을 받습니다. 오른쪽 가장자리의 아이콘이나 도구 › AI 어시스턴트로 엽니다.

질문이 답이 되기까지

패널이 스키마를 읽고 탭을 열어 쿼리를 실행한 화면. 답 위의 카드가 그때 부른 도구들입니다.
패널이 스키마를 읽고 탭을 열어 쿼리를 실행한 화면. 답 위의 카드가 그때 부른 도구들입니다.

평소 쓰는 말로 물으면 됩니다. 모델은 화면을 볼 수 없어서, 먼저 무엇이 열려 있는지 앱에 묻고 쓸 테이블의 컬럼을 읽습니다. 모델이 도구를 호출할 때마다 그 내용이 카드로 남으므로, 어떤 근거로 쿼리를 만들었는지 그대로 볼 수 있습니다. 완성된 문장은 쿼리 탭에서 실행됩니다. 실행 과정을 보다가 중간에 멈출 수 있고, 결과는 다른 쿼리와 마찬가지로 정렬하거나 내보낼 수 있습니다.

모델이 작성한 문장은 실행 전에 데이터베이스 엔진이 실행 계획을 먼저 확인합니다. 없는 컬럼을 참조하면 오류 내용을 받은 모델이 문장을 고치므로 잘못된 쿼리가 화면에 표시되지 않고, 큰 테이블 전체를 훑는 실행 계획이라면 실행해도 되는지 먼저 묻습니다.

하지 않는 일

쓰기는 여기서 멈춥니다. 카드가 어떤 문장인지 보여 주고, 미리보기가 바뀔 행 수를 세어 줍니다.
쓰기는 여기서 멈춥니다. 카드가 어떤 문장인지 보여 주고, 미리보기가 바뀔 행 수를 세어 줍니다.
ai-dry-run
  • 연결 하나만 씁니다 — 사용자가 현재 열어 둔 연결만 사용합니다. 다른 연결을 지정할 인자도, 연결을 열거나 닫는 도구도 없습니다. 어떤 데이터베이스를 쓸지는 사용자가 열어 둔 연결에 따라 정해집니다.
  • DROP·TRUNCATE는 실행되지 않습니다 — 승인하거나, 표현을 바꿔 요청하거나, 세미콜론 뒤에 숨겨도 마찬가지입니다. 쿼리 탭에 적어 두고 무엇이 사라지는지 알려 줄 수는 있지만, 실행은 사용자 몫입니다.
  • 쓰기 문장은 먼저 승인을 받습니다 — 사용자가 직접 입력한 문장과 똑같은 확인 절차를 거칩니다. 몇 행이 바뀌는지 보여 주는 드라이런, 파괴적 문장 확인, 읽기 전용 연결 거부가 그대로 걸립니다.

모델은 어디서 오나

설정 › AI. 이 중 둘은 키가 아예 필요 없습니다.
설정 › AI. 이 중 둘은 키가 아예 필요 없습니다.

설정 › AI에서 정합니다. 키는 로컬 에이전트에만 전달되며, 로컬 에이전트가 모델을 호출할 때 사용합니다. 브라우저에 저장되지 않고 planche.dev로도 가지 않으며, SQL과 스키마도 마찬가지입니다.

  • API 키 — Anthropic, OpenAI 호환 엔드포인트, Gemini 중에서 고릅니다. 키를 저장할지는 선택이고, 저장한다면 어느 파일에 쓰는지 먼저 알려 줍니다.
  • 이 컴퓨터에 저장된 로그인 — ant auth login을 해 두면 SDK가 자격 증명을 자동으로 찾으므로 따로 붙여넣지 않아도 됩니다.
  • 로컬 CLI — 이미 설치되어 있고 로그인도 마친 Claude Code나 Codex를 씁니다. 키가 아예 필요 없습니다.

다른 에이전트로 Planche 다루기

도움말 › AI 에이전트 연결. 토큰이 닿는 범위와 붙여 넣을 한 줄.
도움말 › AI 에이전트 연결. 토큰이 닿는 범위와 붙여 넣을 한 줄.

도움말 › AI 에이전트 연결에서 외부 에이전트에 입력할 설정을 복사합니다. HTTP 기반 MCP를 지원하는 프로그램이라면 연결할 수 있으며, 에디터에 포함된 에이전트에서도 같은 도구를 사용할 수 있습니다. 외부 에이전트가 호출한 도구도 브라우저 탭에서 같은 확인 절차를 거쳐 실행됩니다. 쓰기 요청은 브라우저 탭에서 승인을 받아야 하며, 외부에서 온 요청으로 표시됩니다. 발급한 토큰은 해당 엔드포인트에서만 쓸 수 있고 재시작 후에도 유지됩니다. 토큰을 폐기하면 그 토큰을 받은 프로그램의 연결이 모두 끊깁니다.

안전

운영 데이터베이스에서는 WHERE 없는 DELETE나 의도하지 않은 UPDATE가 큰 피해로 이어질 수 있습니다. Planche는 실행 전에 확인할 수 있는 단계를 제공하고, 필요에 따라 설정에서 조정할 수 있습니다.

드라이런: 바꾸기 전에 대상 행을 먼저 봅니다

UPDATE를 실행하기 전에 SELECT로 바꿔 조회한 결과. 몇 행이 바뀌는지, 그게 어떤 행인지 보여 줍니다.
UPDATE를 실행하기 전에 SELECT로 바꿔 조회한 결과. 몇 행이 바뀌는지, 그게 어떤 행인지 보여 줍니다.

에디터에서 UPDATE나 DELETE를 실행하면, Planche가 그 문장이 건드릴 행을 조회하는 SELECT 문으로 바꿔 먼저 실행하고 결과를 보여 줍니다. 여기서 취소하면 원래 문장은 실행되지 않습니다. 조인이 들어간 형태도 방언별로 처리합니다. MySQL의 UPDATE a JOIN b, PostgreSQL의 UPDATE … FROM과 DELETE … USING, SQL Server의 UPDATE 별칭 … FROM, Oracle의 상관 서브쿼리가 모두 해당합니다. 파서가 안전하게 바꿀 수 없는 형태라면, 틀린 미리보기를 보여 주는 대신 미리보기 없이 실행합니다.

그 밖의 확인 장치

  • 파괴적 문장 확인 — DROP, TRUNCATE, WHERE 없는 DELETE·UPDATE는 실행 전에 어떤 문장이 나가는지 그대로 보여 주고 확인을 받습니다. 트리에서 테이블이나 데이터베이스를 삭제할 때는 이름까지 다시 입력해야 합니다.
  • 읽기 전용 연결 — 쓰기 문장이 데이터베이스에 도달하기 전에 거부됩니다.
  • 그리드 커밋 미리보기 — 그리드에서 고친 내용이 반영되기 전에, 생성된 SQL을 먼저 보여 줍니다.
  • 수동 트랜잭션 — 직접 Commit을 누르기 전까지는 확정되지 않습니다.
  • 환경 색상 — 운영 연결에 색을 지정해 두면 탭과 화면 테두리 색이 달라져, 지금 어디에 접속해 있는지 한눈에 보입니다.
설정 › 안전. 위의 확인 장치들을 하나씩 켜고 끌 수 있습니다.
설정 › 안전. 위의 확인 장치들을 하나씩 켜고 끌 수 있습니다.

ERD

Tools › ERD 보기는 선택한 데이터베이스의 외래 키로 ERD를 만듭니다. 관계는 까마귀발 표기로 표시되며 엔티티 위치와 컬럼 너비를 조절할 수 있습니다. 배치는 데이터베이스별로 저장됩니다.

샘플 데이터베이스의 23개 테이블과 그 사이의 외래키.
샘플 데이터베이스의 23개 테이블과 그 사이의 외래키.

직접 만든 컬럼 링크는 점선으로 그려집니다. 링크가 이 다이어그램에 없는 테이블(다른 데이터베이스나 다른 연결의 테이블)을 가리키면, 출발 테이블 옆에 그 테이블을 나타내는 상자를 하나 만들어 관계를 볼 수 있게 합니다.

테이블 설계

Create Table과 Alter Table에서는 컬럼, 인덱스, 그리고 엔진이 지원하는 스토리지 속성을 탭별로 편집합니다.

컬럼 편집 화면. 타입, 길이, 기본값, NULL 허용 여부, 기본키를 지정합니다.
컬럼 편집 화면. 타입, 길이, 기본값, NULL 허용 여부, 기본키를 지정합니다.

SQL 탭에서는 현재 설정으로 실행될 문장을 해당 엔진의 방언으로 보여 줍니다. 폼을 수정하면 즉시 갱신되므로 실행할 SQL을 확인하거나 방언 문법을 살펴볼 때 쓸 수 있습니다.

폼 내용과 항상 일치하는 생성 DDL.
폼 내용과 항상 일치하는 생성 DDL.

나머지 관리 기능은 Table과 Database 메뉴에 있습니다. 이름 변경, 구조만 복제하기, 데이터베이스 생성과 삭제가 있고, 엔진이 지원한다면 사용자 관리·프로세스 목록·서버 변수·상태 조회도 여기에 있습니다.

내보내기

테이블을 CSV로 내보내는 화면. 구분자와 헤더 포함 여부를 고르고, 내보내는 동안 진행률이 표시됩니다.
테이블을 CSV로 내보내는 화면. 구분자와 헤더 포함 여부를 고르고, 내보내는 동안 진행률이 표시됩니다.
  • CSV로 내려받기 — 지금 보고 있는 결과, 또는 테이블 전체를 내보냅니다. 테이블은 기본키 순서로 나눠 읽고, 브라우저가 File System Access API를 지원하면 고른 파일에 곧바로 이어 씁니다. 그래서 메모리보다 큰 테이블도 내보낼 수 있습니다. 진행률이 표시되고 중간에 멈출 수 있습니다.
  • 스키마를 HTML로 — 체크한 테이블들의 컬럼과 인덱스를 정리한 HTML 파일 하나를 만듭니다.
  • 컬럼 링크 내보내기·가져오기 — 직접 만든 가상 외래키를 JSON 파일로 주고받습니다.
  • INSERT로 복사 — 그리드에서 몇 행만 다른 곳으로 옮길 때 씁니다.
  • 데이터베이스 파일 저장 — 브라우저에서 연 SQLite 데이터베이스(스크래치패드 포함)를 디스크에 씁니다.

CSV 값이 =, +, -, @로 시작하면 앞에 작은따옴표를 붙여 내보냅니다. 스프레드시트가 그 값을 수식으로 해석해 실행하는 것을 막기 위해서입니다.

게이트웨이 모드(팀에서 함께 쓰기)

게이트웨이 모드에서는 공용 서버의 에이전트 하나를 팀이 함께 사용합니다. 데이터베이스 접속 정보는 서버 설정 파일에만 두고 브라우저에서는 연결할 프로필 이름만 선택합니다.

Terminal

npx planche --gateway gateway.json --addr 0.0.0.0 --allow-remote \
  --token "$(openssl rand -base64 24)" --public-url https://sql.example.com

gateway.json

{
  "name": "Acme staging",
  "profiles": [
    {
      "name": "Shop (read-only)",
      "driver": "mysql",
      "host": "db.internal",
      "port": 3306,
      "user": "reporting",
      "password": "…",
      "database": "shop"
    },
    {
      "name": "Shop (writable)",
      "readOnly": false,
      "driver": "postgres",
      "host": "pg.internal",
      "port": 5432,
      "user": "app",
      "password": "…",
      "database": "shop"
    }
  ]
}
  • name — 게이트웨이 이름입니다. 연결 화면에 표시됩니다.
  • profiles[].name — 브라우저에 보이는 이름이며, 클라이언트가 서버로 보내는 값은 이 이름뿐입니다.
  • profiles[].readOnly — 생략하면 읽기 전용입니다. 쓰기를 허용하려면 false로 지정하세요.
  • 나머지 항목은 연결 폼에서 입력하던 것과 같은 이름입니다. driver(mysql, postgres, mssql, oracle, sqlite, d1), host, port, user, password, database가 있고, Oracle은 serviceName, SQLite는 file, Cloudflare D1은 accountId·databaseId·apiToken을 씁니다. ssh 블록도 그대로 넣을 수 있습니다.

배스천 호스트를 거쳐야 하는 프로필에는 ssh 블록을 넣습니다. 이때 위쪽의 host·port는 배스천 호스트에서 본 주소이므로 보통 127.0.0.1이 됩니다.

gateway.json (profiles 항목 하나)

{
  "name": "Shop via bastion (read-only)",
  "driver": "mysql",
  "host": "127.0.0.1",
  "port": 3306,
  "user": "reporting",
  "password": "…",
  "database": "shop",
  "ssh": {
    "host": "bastion.example.com",
    "port": 22,
    "user": "deploy",
    "auth": "key"
  }
}
  • auth는 key, agent, password 중 하나입니다. key로 두고 privateKey를 적지 않으면, 게이트웨이 서버의 ~/.ssh/config에서 그 호스트에 지정된 IdentityFile을 쓰고 없으면 ~/.ssh/id_*를 찾습니다. 키가 설정 파일에 남지 않으므로 서버에서는 이 방식이 일반적입니다. agent는 게이트웨이의 SSH_AUTH_SOCK을, password는 password 항목을 사용합니다.
  • privateKey를 직접 적는 경우, 값은 경로가 아니라 키 파일의 내용(PEM / OpenSSH)입니다. 키에 암호가 걸려 있으면 passphrase도 함께 넣습니다.
  • 배스천 호스트의 키는 게이트웨이 서버에 미리 등록돼 있어야 합니다. 그 서버에서 ssh bastion.example.com으로 한 번 접속해 두거나, 프로필의 acceptHostKey에 SHA256:… 지문을 적어 고정하세요. 게이트웨이 모드에서 브라우저가 보내는 것은 프로필 이름뿐이라 “처음 보는 호스트 키” 확인에 답할 수 없습니다.
  • 프로필은 따로 지정하지 않으면 읽기 전용이고, 이 제한은 에이전트가 직접 검사합니다. 요청 하나에 SELECT 계열 문장 하나만 허용하고, 엔진이 지원하면 세션 자체도 읽기 전용으로 설정합니다. 브라우저 쪽 확인 장치는 사용자를 돕는 기능이지만, 이 검사는 클라이언트에서 우회할 수 없습니다.
  • 프로필 이름 대신 접속 정보를 직접 담아 보내는 요청은 거부합니다.
  • 이 모드에서는 에이전트가 웹 앱까지 직접 서빙합니다. 페이지와 API가 같은 주소를 쓰게 되므로 브라우저 보안 정책을 완화하지 않아도 됩니다.
  • 에이전트는 평문 HTTP로 통신하므로, 앞단에 TLS 리버스 프록시를 두고 그 주소를 --public-url로 알려 주세요.

팀원은 그 주소를 열고, 연결 대화상자의 Configure 칸에 토큰을 한 번만 붙여넣으면 됩니다. 그러면 시작 화면과 연결 관리자에 사용할 수 있는 프로필 목록이 나타납니다.

연결 동기화 (종단 간 암호화)

연결 동기화는 연결 프로필을 planche.dev에 보관해 다른 컴퓨터에서도 쓸 수 있게 합니다. 모든 내용은 브라우저에서 암호화한 뒤에 올라가고, 그 키는 서버가 볼 수 없습니다. 연결 › 연결 동기화에서 엽니다. 1.0부터 Pro 기능이 되고, 0.x 버전 동안에는 무료입니다.

켜는 방법

  1. GitHub로 로그인합니다. 로그인은 서버가 어느 볼트가 내 것인지 찾는 데만 씁니다.
  2. 10자 이상의 패스프레이즈를 정하고 두 번 입력합니다. 패스프레이즈를 GitHub 로그인과 일부러 분리했습니다. 로그인 정보는 서버가 볼 수 있으니, 로그인으로 데이터가 풀려서는 안 되기 때문입니다.
  3. 프로필이 암호화되어 올라갑니다. 다른 컴퓨터에서는 같은 계정으로 로그인한 뒤 같은 패스프레이즈를 입력해 잠금을 풉니다.

암호화 방식

  • 브라우저가 패스프레이즈로 256비트 AES-GCM 키를 만듭니다. PBKDF2-SHA256을 60만 회 반복하고, 16바이트 무작위 salt를 씁니다. 저장할 때마다 새 12바이트 nonce를 씁니다.
  • 키는 꺼낼 수 없는(non-extractable) 키로 만들어 탭의 메모리에만 둡니다. 키와 패스프레이즈 모두 디스크에 저장하지 않고 어디로도 보내지 않습니다. 그래서 새 세션마다 패스프레이즈를 다시 묻습니다.
  • 서버는 계정마다 암호화된 볼트 하나를 저장합니다. 그 옆에 평문으로 남는 것은 키를 다시 만드는 데 필요한 값(salt, 반복 횟수), nonce, 버전 번호, 마지막 저장 시각뿐입니다. 이 값들로는 내용을 알 수 없습니다.
  • 계정 정보로는 GitHub ID와 이메일 주소(이메일이 비공개면 GitHub 사용자 이름), 그리고 로그인해 있는 동안의 세션을 보관합니다.

볼트에 들어가는 것

  • 연결 프로필: 호스트, 포트, 사용자, 옵션, 그 프로필에 설정한 컬럼 링크.
  • 비밀번호, SSH 비밀번호, 개인 키. 단, 비밀번호 저장을 켠 프로필만 들어갑니다. 이 컴퓨터에 남기지 않기로 한 비밀번호는 서버에도 남기지 않습니다.
  • 샘플 데이터베이스와 스크래치패드는 넣지 않습니다. 필요한 컴퓨터에서 그때그때 만들어지기 때문입니다.
  • 쿼리 기록, 조회 결과, 데이터베이스 안의 데이터는 절대 들어가지 않습니다.

컴퓨터 두 대에서 쓸 때

프로필마다 마지막으로 바뀐 시각이 함께 저장되고, 두 볼트를 합칠 때는 더 최근 것이 남습니다. 삭제한 기록은 90일 동안 남겨 두기 때문에, 한 컴퓨터에서 지운 프로필이 다른 컴퓨터에서 되살아나지 않습니다. 두 컴퓨터가 동시에 저장하면 서버는 나중 저장을 거부하고, 그 컴퓨터는 덮어쓰는 대신 최신 볼트와 합친 뒤 다시 저장합니다.

패스프레이즈를 잊었을 때

서버의 볼트는 저희를 포함해 누구도 복호화할 수 없어서 복구할 수 없습니다. 프로필이 남아 있는 컴퓨터에서 서버에서 삭제를 누르고, 새 패스프레이즈로 동기화를 다시 켜면 됩니다. 계정 삭제는 볼트와 로그인 정보를 함께 지웁니다. 두 경우 모두 컴퓨터에 있는 프로필은 건드리지 않습니다.

동기화는 planche.dev에서만 됩니다. 로컬 에이전트가 띄워 주는 앱은 인터넷에 접속하지 않으므로 거기서는 동기화를 쓸 수 없습니다.

개인정보와 보안

  • 데이터가 저희 서버로 가지 않습니다. planche.dev는 정적 페이지만 내려줍니다. 쿼리와 결과는 브라우저와 내 에이전트 사이에서만 오가고, 브라우저 SQLite라면 페이지 밖으로 나가지도 않습니다.
  • 접속 정보는 내 컴퓨터에 있습니다. 프로필은 브라우저 저장소에 저장되고, 비밀번호와 SSH 비밀 정보는 저장을 선택하지 않는 한 탭을 닫을 때까지만 유지됩니다. 앱은 루프백 주소(또는 그 페이지를 직접 서빙한 에이전트)가 아닌 곳과는 통신하지 않습니다. 원격 에이전트에 연결한다는 것은 접속 정보를 네트워크로 보낸다는 뜻이기 때문입니다.
  • 에이전트는 모든 요청을 인증합니다. 상태 확인용 경로를 빼면 전부 토큰이 필요하고, 토큰이 여러 번 틀리면 잠시 인증을 막습니다. 허용된 출처에서 온 요청만 받고, 루프백이 아닌 주소에서 대기하려면 별도 옵션과 토큰을 명시해야 합니다.
  • 열 수 있는 SQLite 파일이 제한됩니다. 에이전트는 홈 디렉터리(숨김 폴더와 시스템 폴더는 제외)나 사용자가 지정한 디렉터리 아래의 파일만 엽니다. ATTACH는 따로 허용하지 않는 한 거부합니다.
  • 기록에서 비밀번호를 가립니다. 실행 기록이나 편집 기록을 저장하기 전에 비밀번호로 보이는 문자열을 마스킹하며, 저장 기능 자체를 끌 수도 있습니다.
  • 사용 통계는 익명이고 끌 수 있습니다. 어떤 엔진을 썼는지, 어떤 대화상자를 열었는지, 문장이 성공했는지 같은 범주 값만 집계합니다. SQL 내용, 호스트 주소, 데이터베이스·테이블·파일 이름은 수집하지 않습니다. 설정에서 한 번에 끌 수 있습니다.

이 안전 장치는 실수를 줄이는 보조 수단입니다. 중요한 변경 전에는 백업을 준비하고 실행할 SQL을 검토해야 합니다.

키보드 단축키

에디터 단축키는 SQL 에디터에 커서가 있을 때 동작하고, 나머지는 어느 화면에서나 동작합니다.

키동작
F9실행합니다. 스크립트 전체를 실행할지 커서가 있는 문장만 실행할지는 설정 › 안전 › 실행 범위에서 정합니다.
Ctrl / ⌘ + Enter드래그로 선택한 부분을 실행합니다. 선택한 것이 없으면 커서가 놓인 문장 하나만 실행합니다.
Ctrl / ⌘ + Shift + Enter실행 범위 설정과 상관없이 항상 스크립트 전체를 실행합니다.
Ctrl / ⌘ + K빠른 명령 팔레트를 엽니다. 테이블 이름이나 메뉴 이름을 입력해 바로 이동합니다.
Alt + N연결 관리자를 엽니다.
Alt + T지금 보고 있는 연결에 빈 쿼리 탭을 하나 추가합니다.
Shift / ⌘ / Ctrl + click결과 그리드에서 Shift를 누르고 클릭하면 두 행 사이가 모두 선택되고, ⌘(Ctrl)을 누르고 클릭하면 그 행만 선택에 넣거나 뺍니다.
F2 / Enter결과 그리드에서 클릭해 둔 셀을 편집합니다(더블클릭과 같습니다).
Ctrl / ⌘ + F에디터 안에서 찾기·바꾸기 상자를 엽니다.