왜 모든 게 브라우저에서 도는가
이 사이트를 시작한 이유는, 2018년에 우리가 믿고 쓰던 거의 모든 JSON 포매터가 입력을 서버로 보내고 있었기 때문입니다. 내부 API 응답을 포맷해서 보려던 참이었습니다. 붙여넣었더니 페이지가 1초쯤 멈추고, 누군가가 방금 고객 레코드 절반의 사본을 가졌다는 사실을 깨달았습니다. 큰일은 없었지만 머리에 남는 종류의 순간이었습니다.
저는 한 번 프로덕션 AWS 액세스 키를, 헤더까지 친절하게 로그하는 '무료' JWT 디코더에 붙여넣어서 유출시킨 적이 있습니다. 그 토큰은 같은 시간 안에 Lambda 호출에 엮여 들어갔습니다. 15분 안에 키를 회전시키고 배포 파이프라인을 다시 만들었습니다. 그 경험이 이 사이트가 존재하는 전체 이유이고, 모든 도구가 정적 SvelteKit 페이지로 동작하면서 우리 인프라가 아니라 여러분의 브라우저에서 작업을 처리하는 이유입니다.
우리 네트워크 로그는 지루합니다. 페이지에 대한 GET 한 번, 폰트와 스크립트 번들을 위한 요청 몇 개, 그게 끝입니다. 여러분의 입력을 조용히 받아갈 POST 엔드포인트는 없습니다. 확인하고 싶으면 DevTools를 열고 200KB 텍스트를 인코딩하면서 Network 탭을 보세요. 외부로 나가는 요청은 정확히 0건입니다.
실제로 측정한 성능
Chrome 130을 돌리는 2024 M2 MacBook Pro에서 우리 JSON 포매터는 50MB 페이로드를 약 1.18초에 끝까지 처리하고, 렌더된 트리가 보이기까지 240밀리초가 더 걸립니다. 테스트는 GitHub events 아카이브로 합니다. 거기 들어 있는 중첩 배열이 우리가 비교한 다른 포매터 셋 중 셋을 무너뜨렸기 때문입니다.
같은 머신에서 100MB 바이너리 데이터를 Base64 인코딩하는 데 380밀리초 걸립니다. 디코딩은 같은 페이로드에 410밀리초 — 입력 길이에 대한 sanity check를 돌리기 때문에 더 느립니다. Chrome 130을 돌리는 Pixel 8에서는 같은 수치가 1.4초와 1.6초입니다. 베스트 케이스 대신 워스트 케이스를 적습니다. 베스트 케이스는 거짓말을 하니까요.
해시 계산은 WebCrypto API를 직접 씁니다. M2에서 SHA-256으로 100MB는 220밀리초, Pixel에서는 480밀리초입니다. MD5는 (호환성 때문에 들어 있는 레거시) 순수 JS로 직접 썼고, SHA-256보다 대략 4배 느립니다 — 그 격차가 브라우저 네이티브 구현이 없는 값입니다. 보안 목적으로 MD5가 정말 필요하다면, 그러시면 안 됩니다. 도구를 만든 이유는 옛날 시스템 체크섬이 아직도 그걸 요구하기 때문입니다.
이 사이트를 어떻게 만들었나
전체가 Vite 위에 SvelteKit입니다. 2024년에 React 대신 Svelte를 고른 이유는 도구 사이트의 번들 크기는 작아야 했기 때문입니다 — JSON 포매터가 80KB가 아니라 14KB의 프레임워크 코드와 함께 로드됩니다. 트레이드오프는 Svelte 생태계가 작다는 것이고, 신택스 하이라이팅 라이브러리를 고를 때 진짜로 그게 느껴져서 결국 diff 도구용으로는 직접 썼습니다.
배포는 Cloudflare Pages로 합니다. 빌드는 보통 30초 안에 끝나고, 도구 페이지의 cold-start 시간은 네트워크가 아니라 SvelteKit 하이드레이션 단계가 지배적입니다. 하이브리드 SSR + CSR 모드를 씁니다. 페이지는 검색 크롤러와 AI 요약기가 진짜 콘텐츠를 보도록 마크업을 미리 렌더링한 채로 나가고, 여러분이 도착하면 JavaScript가 실제 도구를 하이드레이트합니다.
전체 레포가 3천 줄 미만의 TypeScript입니다. 이 코드를 읽는 사람은 기존 도구 하나를 복사해서 약 90분 만에 새 도구를 추가할 수 있어야 합니다 — 의도적인 설계 제약이었어요. 회사에서 어떤 use case를 만나면 즉시 도구를 하나 더 만들 수 있어야 했기 때문입니다. 여기 있는 도구 절반쯤은 'Slack에서 누가 사적인 버전이 있었으면'이라고 한 메시지에서 시작됐습니다.
우리가 아닌 것
SaaS가 아닙니다. 계정도, 사용량 티어도, API 토큰도 없습니다. 이 도구들을 스크립트로 돌리고 싶다면, 이들이 감싸고 있는 npm 패키지가 보통 검색 한 번 거리에 있습니다 — 각 도구의 문서 페이지에서 링크를 겁니다.
PII 저장도 다루지 않습니다. 모든 게 로컬에서 돌아가긴 하지만, localStorage에도 기본적으로 아무것도 저장하지 않습니다. 몇 개 도구(카운터, 컬러 피커)는 마지막 값을 기억하도록 opt-in 되어 있지만, 페이지에 그렇다고 적혀 있고 직접 지울 수 있습니다.
존재하는 모든 도구를 쫓아가지 않습니다. 우리가 아는 개발자가 요청했거나 한 주에 두 번 필요했을 때만 추가합니다. 이 글을 쓰는 시점에 23개 도구가 있습니다. 더 늘 거지만 천천히 늘 겁니다.
보기보다 오래 걸린 작은 결정들
다크 테마는 시스템 설정이 아니라 다크 자체로 기본값입니다. 한 달 동안 시스템 선호도 모드로 테스트했는데, Windows가 기본 라이트로 잡혀 있지만 화면은 색이 빠진 싸구려 노트북 사용자들의 이탈률이 올라가는 걸 봤습니다. 다크 기본값에 명확한 토글을 두는 쪽이 더 잘 동작했습니다 — '잘 동작했다'는 건 사람들이 도구를 쓸 만큼 페이지에 머물렀다는 뜻입니다.
입력 필드는 모노스페이스, 나머지는 비례폰트로 골랐습니다. 당연한 얘기로 들리지만, 이전 버전은 한 가지 폰트로 통일했고 사람들은 긴 URL과 JWT 문자열이 깨져 보인다고 계속 신고했습니다. 수정은 15분짜리 CSS 변경이었습니다. 진짜 진단을 찾는 데 히트맵 녹화를 노려보는 몇 주가 걸렸습니다.
모든 도구에 '샘플' 버튼이 있어서 대표 입력을 로드합니다. 사용자가 도구를 열고, 빈 입력 박스를 10초 쳐다보다가, 떠나는 세션 리플레이를 보고 추가했습니다. 샘플은 일부러 완벽하게 깨끗하지 않습니다. 절반쯤은 사실 깨진 입력을 디버깅하고 싶어서 들어오니까요.