본문 바로가기

텍스트를 보관하지 않는 텍스트 도구

텍스트를 세고, 비교하고, 정리하고, 읽는 도구 11가지. 초안, 목록, 소스 코드는 절대 저장되지 않습니다.

도구 11개, 회원가입 없음, 워터마크 없음

단어 수 세기와 글자 수 세기는 “얼마나 긴가”에, 텍스트 비교는 “무엇이 바뀌었나”에 답하고, 중복 줄 제거는 목록을 정리합니다. 뷰어는 누군가 보내 준 파일이 제대로 열리지 않을 때 쓰고, 세 가지 코드 압축 도구는 배포 직전의 코드에 씁니다. 목록 아래 내용은 두 도구가 같은 텍스트를 왜 다르게 세는지, 그리고 똑같아 보이는 두 줄이 왜 때로는 전혀 같은 줄이 아닌지 다룹니다.

세기 및 비교

도구 3개

어떤 언어든 단어와 글자 수를 정확히 세고, 두 버전 사이에 무엇이 바뀌었는지 정확히 확인합니다.

뷰어

도구 3개

CSV, XML 파일, 마크다운 문서를 스프레드시트가 망가뜨리지 않은 원래 모습 그대로 제대로 읽어 보세요.

텍스트의 실체, 그리고 도구마다 결과가 다른 이유

텍스트 파일은 바이트와 인코딩으로 이루어지는데, 인코딩은 파일에 저장되지 않습니다. 특정 바이트가 “é”를 뜻한다는 것은 관례로만 전해지며, 그래서 같은 파일이 어떤 곳에서는 제대로 열리고 다른 곳에서는 “é”로 보입니다. UTF-8은 현대의 해답으로, 일반 라틴 문자는 1바이트, 악센트가 붙은 문자는 2바이트, 한중일 문자와 아랍 문자 대부분, 그리고 모든 이모지는 3~4바이트로 저장합니다. UTF-16은 Windows와 JavaScript가 내부적으로 쓰는 방식으로, 거의 모든 문자를 2바이트, 나머지를 4바이트로 저장합니다. Windows-1252와 Latin-1은 오래된 시스템이 아직도 만들어 내는 1바이트 인코딩이며, 글자 깨짐의 흔한 원인입니다. 이 페이지들에 대해 알아 둘 점이 있습니다. CSV 뷰어는 끌어다 놓은 파일의 인코딩을 UTF-16과 Windows-1252까지 감지하고, 직접 바꿀 수도 있게 해 줍니다. 일반 텍스트 입력란은 그렇지 않습니다. 끌어다 놓은 파일을 UTF-8로 읽으므로 Latin-1로 내보낸 파일은 악센트 문자가 잘못 표시되며, 먼저 변환하는 것이 해결책입니다.

“글자”에는 네 가지 의미가 있고, 어느 것이 필요한지는 누가 제한하느냐에 달려 있습니다. 사람이 한 글자로 보는 것은 자소 클러스터(grapheme cluster)입니다. 정규식이 일치시키는 것은 코드 포인트입니다. JavaScript의 string.length가 알려 주는 것은 UTF-16 단위입니다. 데이터베이스 열이나 HTTP 헤더가 재는 것은 UTF-8 바이트입니다. 평범한 영어에서는 넷이 모두 같아서 아무도 눈치채지 못합니다. 그러다 가족 이모지 하나가 자소 1개, 코드 포인트 7개, UTF-16 단위 11개, 25바이트가 되고, 200자짜리 메시지가 255자 제한 필드에서 거부됩니다. 글자 수 세기가 네 가지를 모두 보여 주는 이유가 바로 이것입니다.

보이지 않는 문자도 진짜 문자입니다. 줄바꿈 없는 공백(non-breaking space)은 일반 공백과 똑같아 보이지만 완전히 다른 문자입니다. 웹 페이지나 워드 프로세서에서 복사한 텍스트에 늘 섞여 들어오며, 검색, CSV 파싱, 공백으로 나누는 코드를 망가뜨립니다. 여러 사람이 함께 있는 이모지를 하나로 묶는 것은 폭 없는 결합자(zero-width joiner)입니다. 소프트 하이픈, 방향 표시 문자, 바이트 순서 표시(BOM)도 모두 붙여 넣은 텍스트에 따라옵니다. 어느 것도 화면에 나타나지 않으므로, 유일한 신호는 눈에 보이는 것과 맞지 않는 글자 수입니다. 글자 수 세기의 솔직한 쓰임새 중 하나입니다. 참고로 텍스트 비교의 공백 무시 옵션은 일반 공백과 탭을 합쳐 처리할 뿐, 줄바꿈 없는 공백을 공백으로 취급하지는 않습니다. 둘은 같은 문자가 아니기 때문입니다.

줄 끝 문자는 diff에서 가끔 모든 줄이 바뀐 것으로 나오는 이유입니다. Windows는 캐리지 리턴과 라인 피드로 줄을 끝내고, 나머지는 모두 라인 피드만 씁니다. LF 파일을 Windows 편집기에서 저장하면 모든 줄이 보이지 않는 1바이트씩 달라지므로, git diff나 diff(1) 같은 바이트 단위 비교는 파일 전체가 다시 쓰였다고 보고하고 실제로 바꾼 한 곳을 가려 버립니다. 저희 텍스트 비교와 중복 줄 제거는 비교 전에 세 가지 방식을 모두 줄 바꿈으로 인식하므로, 줄 끝 문자만 바뀐 파일이 여기서 온통 빨간색으로 표시되지는 않습니다. 읽기 도구에서는 편리한 점이지만 저장소에서는 함정입니다. 편집기나 git 자체의 줄 끝 설정으로 원인을 고치세요.

똑같아 보이는 두 문자열이 다르게 비교된다면, 대개 정규화가 원인입니다. 유니코드에서는 “é”를 두 가지로 쓸 수 있습니다. 코드 포인트 하나로 쓰거나, 일반 “e” 뒤에 결합용 악센트를 붙여 쓰는 것입니다. 화면에서는 같지만 바이트 배열이 다르므로, 비교, 중복 제거, 데이터베이스 조회에서 서로 다른 값으로 취급됩니다. macOS와 Windows는 파일 이름에 어느 형태를 쓸지 역사적으로 달랐고, 그래서 두 컴퓨터에서 모은 목록에 중복 제거가 안 되는 똑같아 보이는 항목이 생깁니다. 글자 수 세기로 이를 찾아낼 수 있습니다. 두 형태는 자소 수는 같고 코드 포인트 수는 다릅니다. 이 도구들 중 어느 것도 형태를 서로 변환하지 않으며, 그것은 Python의 unicodedata.normalize 같은 유니코드 라이브러리로 스크립트 한 줄이면 되는 작업입니다.

“단어 수”는 측정이 아니라 판단입니다. 공백으로 나누는 것은 영어의 규칙이며, 단어 사이에 공백을 두지 않는 중국어, 일본어, 태국어에 적용하면 긴 글 한 편이 한 단어로 나옵니다. 저희 도구는 대신 브라우저의 유니코드 단어 분할을 사용하므로 모든 문자 체계에서 단어가 어디서 시작하는지 압니다. 남은 차이는 하이픈(“well-known”은 여기와 Word에서는 한 단어, 일부 도구에서는 두 단어), 단독으로 쓰인 숫자, 그리고 무엇을 문장으로 보느냐입니다. “We met Dr. Smith”는 한 문장이지만 단순한 분할기는 두 문장으로 셉니다. 읽는 시간은 그 위에 더한 추정치로, 블로그 글 사이에서 복사되는 어림수가 아니라 메타 분석에서 나온 묵독 기준 분당 238단어를 씁니다.

브라우저가 정말 맞지 않는 경우

이 모듈의 어떤 것도 전송되거나 저장되지 않습니다. 그래서 공개 전 원고나 사내 소스 코드를 붙여 넣어도 안전합니다. 동시에 그것이 한계를 정하기도 하며, 작업 도중에 알게 되시는 것보다 그 한계가 어디인지 미리 말씀드리는 편이 낫습니다.

큰 파일. 텍스트 전체가 탭의 메모리에 올라가고, 입력할 때마다 다시 검사됩니다. 몇 MB는 여유롭지만 수백 MB짜리 로그 파일은 그렇지 않으며, 휴대폰은 노트북보다 먼저 포기합니다. 명령줄은 스트리밍으로 처리하므로 이런 문제가 없습니다. grep과 ripgrep은 메모리보다 큰 파일도 검색하고, sed와 awk는 한 줄씩 변환하며, 고유 옵션을 준 sort는 디스크를 활용해 수천만 줄짜리 목록의 중복을 제거합니다. 모두 무료이고 macOS와 Linux에 이미 설치되어 있습니다.

크게 다른 문서. 텍스트 비교는 차이가 8,000개에 이르면 멈춥니다. 그 이상이면 알고리즘의 메모리 사용량이 급격히 늘어 탭이 멈추고, 그렇게 큰 diff는 어차피 읽을 수 없기 때문입니다. 같은 문서의 두 버전은 이 한도에 거의 닿지 않지만, 서로 무관한 두 문서는 즉시 닿습니다. 코드 검토에는 크기에 상관없는 diff와 git diff를 쓰세요. 제대로 된 3-way 병합 도구는 이 페이지가 전혀 할 수 없는 일을 해 줍니다.

인코딩 변경이나 유니코드 정규화. 이 페이지들은 읽고 알려 줄 뿐, 인코딩을 변환하지는 않습니다. iconv는 존재하는 모든 인코딩 사이를 변환하고, file 명령은 어떤 인코딩인지 추측하며, 유니코드 정규화는 Python 한 줄이나 ICU의 uconv 호출로 됩니다. 글자가 깨진 내보내기 파일을 고치려면 이 도구들을 쓰세요.

반복 작업. 이 도구들은 사람이 클릭할 때 동작합니다. 문서 400개의 단어 수를 세거나 커밋할 때마다 디렉터리를 압축하는 일은 스크립트나 빌드 단계의 몫입니다. 특히 코드 압축은 빌드 도구가 같은 압축을 해 주며, 붙여 넣기 입력란이 제공할 수 없는 소스 맵, 감시 모드, 캐싱까지 갖추고 있습니다. 이 페이지는 지금 눈앞에 있는 파일 하나를 위한 것입니다.

최신 CSS. CSS 코드 압축은 네이티브 중첩과 최신 미디어 범위 문법을 압축하지 않고 거부합니다. 내부에서 쓰는 압축기가 둘보다 오래되었고, 이해하지 못하는 것은 조용히 지워 버리기 때문입니다. 이것은 기능이 아니라 정직한 거부이며, 해결책은 Sass, PostCSS, Lightning CSS로 먼저 중첩을 컴파일해 없애는 것입니다. 빌드 도구가 이미 그렇게 하고 있을 가능성이 높습니다.

비슷해 보이는 도구 중에서 고르기

단어 수 세기 vs 글자 수 세기. 세는 방식은 같고 앞세우는 숫자가 다릅니다. 단어 수 세기는 단어, 문장, 문단, 읽는 시간을 먼저 보여 주며, 에세이, 기사, 연설문은 이것으로 잽니다. 글자 수 세기는 글자 수, 공백 제외 글자 수, UTF-8 바이트를 먼저 보여 주며, 메타 설명, SMS 한 건, 데이터베이스 필드는 이것으로 잽니다. 텍스트가 너무 길다고 거부당했다면 글자 수 세기, 그중에서도 바이트 수를 보세요.

텍스트 비교 vs 중복 줄 제거. 비교는 “두 버전 사이에 무엇이 바뀌었나”에 답하며 텍스트 두 개가 필요합니다. 중복 줄 제거는 목록 하나를 대상으로 “여기서 두 번 이상 나오는 것은 무엇인가”에 답합니다. 어떤 항목이 몇 번 반복되었는지 알려 주고, item2가 item10보다 먼저 오도록 자연 정렬하며, 정확히 한 번만 나온 줄만 남길 수도 있습니다. 두 목록 중 한쪽에만 있는 항목을 찾는 것은 비교 도구가 아니라 중복 줄 제거가 할 일입니다.

HTML 코드 압축 vs CSS 코드 압축 vs JavaScript 코드 압축. 세 언어에 세 가지 압축 도구이며, 알아 둘 만한 겹치는 부분이 하나 있습니다. HTML 코드 압축은 style 블록 안의 CSS와 script 블록 안의 JavaScript도 나머지 두 페이지와 같은 방식으로 압축합니다. 그래서 HTML 파일 하나에는 도구 셋이 아니라 하나면 됩니다. 별도의 .css와 .js 파일은 각자의 페이지를 쓰세요.

XML 뷰어 vs XML 포맷터와 XML 유효성 검사. 여기 있는 뷰어는 접고 펼 수 있는 트리를 보여 줍니다. 문서가 크고 무언가를 찾고 있을 때 필요한 것이 이것입니다. 개발자 도구에 있는 포맷터와 유효성 검사는 파일에 다시 붙여 넣을 들여쓴 텍스트와, 깨진 곳의 정확한 줄과 열을 알려 줍니다. 읽기냐, 편집하고 고치기냐의 차이입니다.

CSV 뷰어 vs 엑셀에서 파일 열기. 경쟁 도구는 아니지만, 사람들이 실제로 하는 비교가 이것입니다. Excel은 파일을 열면서 묻지도 않고 변환합니다. 상품 코드 00123은 123이 되고, 부품 번호 5-3은 5월 3일이 되며, 긴 주문 번호는 지수 표기로 바뀌고, 독일 시스템에서 세미콜론으로 구분해 내보낸 파일은 전부 A열에 들어갑니다. 뷰어는 모든 값을 저장된 그대로 텍스트로 보여 주므로, 실제로 받은 내용이 무엇인지 확인할 수 있습니다.

마크다운 미리보기 vs 마크다운 PDF 변환. 미리보기는 README가 GitHub에서와 똑같이 보이는지 입력하면서 실시간으로 확인하는 도구입니다. 문서 도구에 있는 마크다운 PDF 변환은 페이지 나눔이 있는 완성된 문서를 만드는 도구입니다. 여기서 확인하고, 거기서 완성하세요.

이 도구들의 기반 기술

실제 작업을 수행하는 오픈 소스 엔진과, 이들이 구현한 규격입니다.

  • Unicode Annex #15Specification — 정규화 설명 — 똑같아 보이는 두 문자열이 다를 수 있는 이유.
  • Unicode Annex #29Specification — “글자 하나”의 진짜 의미인 자소 클러스터(grapheme cluster) 정의.
  • cssoMIT — CSS 압축.
  • TerserBSD-2-Clause — JavaScript 압축.
  • markdown-itMIT — 마크다운 미리보기 렌더링.

자주 묻는 질문

제 텍스트가 어딘가에 저장되나요?

아니요. 아무것도 저장하지 않고, 기록하지 않으며, 요청도 보내지 않습니다. 페이지가 로드된 뒤 인터넷 연결을 끊어도 모든 기능이 그대로 동작합니다. 텍스트에서는 이 점이 생각보다 중요합니다. 사람들이 온라인 글자 수 세기나 비교 도구에 붙여 넣는 것은 공개 전 원고, 법률 문서 초안, 학생 과제, 사내 소스 코드이기 때문입니다.

단어 수가 Microsoft Word나 다른 사이트와 다른 이유는 무엇인가요?

세는 데에도 선택이 필요하기 때문입니다. 하이픈으로 연결된 단어, 단독 숫자, 문장이 끝나는 곳, 문단을 나누는 기준은 모두 결정할 문제이고, 도구마다 다르게 정합니다. 저희는 “well-known”을 한 단어로 세고, 모든 줄 바꿈이 아니라 빈 줄을 문단 경계로 보며, “Dr.” 같은 약어 뒤에서 문장을 나누지 않습니다. 또 유니코드 단어 분할을 쓰므로 중국어와 일본어도 거대한 한 단어로 나오지 않고 제대로 셉니다. 일반적인 글에서는 숫자가 거의 일치하지만, 부품 번호 목록이라면 일치하지 않습니다.

끌어다 놓은 파일이 “é” 대신 “é”로 보이는 이유는 무엇인가요?

UTF-8이 아니기 때문입니다. 텍스트 입력란은 끌어다 놓은 파일을 UTF-8로 읽으며, 이번 세기에 만들어진 파일은 거의 다 UTF-8입니다. 하지만 오래된 내보내기 파일은 Windows-1252나 Latin-1일 수 있고, 이런 파일의 바이트는 다른 뜻을 갖습니다. iconv로 한 번 변환하면 영구히 해결됩니다. 이 도구들 중 CSV 뷰어만은 예외로, 인코딩을 감지하고 감지가 틀렸다면 바꿀 수 있게 해 줍니다.

중복을 제거했는데도 중복이 남아 있는 이유는 무엇인가요?

거의 언제나 줄 끝의 공백 때문입니다. 보이지 않지만 두 줄을 실제로 다르게 만듭니다. 그래서 비교 전 공백 제거가 기본으로 켜져 있으며, 이 설정은 비교에만 영향을 줄 뿐 남는 줄은 원래 텍스트를 그대로 유지합니다. 또 다른 원인은 유니코드입니다. 악센트 문자를 한 글자로 쓴 것과 글자에 결합용 악센트를 붙여 쓴 것은 똑같아 보이지만 같지 않습니다. 여기서는 이를 정규화해 주지 않습니다.

워드 문서, PDF, 스프레드시트에도 쓸 수 있나요?

직접은 안 됩니다. 이 도구들은 텍스트를 다루며, 그래서 즉시 동작합니다. 먼저 변환하세요. [PDF 텍스트 추출](pdf-to-text)과 [DOCX TXT 변환](docx-to-txt)이 바로 그 일을 하며, 결과를 여기에 그대로 붙여 넣으면 됩니다. CSV는 예외로, CSV 뷰어에서 바로 열립니다.

크기나 하루 사용량 제한이 있나요?

계정도, 할당량도, 하루 제한도 없습니다. 횟수를 세는 서버가 없기 때문입니다. 한계는 기기의 메모리입니다. 명시적인 제한은 텍스트 비교에 하나 있는데, 차이가 8,000개에 이르면 탭을 멈추게 하는 대신 멈추고 그 사실을 알려 줍니다. 같은 문서의 두 버전을 비교할 때는 거의 이 한도에 닿지 않습니다.