보이지 않는 문자란?
화면에는 멀쩡하게 보이는데 코드 비교나 검색에서는 다른 문자열로 인식되는 경험, 한 번쯤 있을 거예요. 데이터를 복사·붙여넣기했더니 갑자기 인식이 안 되거나, 정확히 같은 문자열인데 if 조건에서 false가 나오는 상황이 그렇습니다. 거의 대부분의 원인은 보이지 않는 문자예요. 유니코드에는 글자 폭이 0이거나, 일반 공백처럼 보이지만 실제로는 다른 코드포인트인 문자들이 수십 종 존재합니다. 워드 문서·웹 페이지·SNS·메신저에서 텍스트를 복사하면 이런 문자들이 따라오는 일이 잦아요. 보이지 않으니 디버깅이 까다롭지만 원리만 알면 빠르게 해결할 수 있습니다.
가장 자주 만나는 다섯 가지
실무에서 가장 자주 마주하는 보이지 않는 문자는 다음 다섯 가지입니다.
- U+200B (Zero-Width Space): 폭 0의 공백. 이메일·SNS에서 자동 줄바꿈 보조용으로 들어감.
- U+00A0 (Non-Breaking Space, NBSP): 일반 공백처럼 보이지만 다른 코드. 워드·HTML 에서 옴.
- U+FEFF (BOM, Byte Order Mark): 파일 맨 앞에 붙는 인코딩 표시. UTF-8 with BOM에서 발생.
- U+202E (RTL Override): 텍스트 방향을 거꾸로 만드는 제어 문자. 보안 공격에 악용되기도.
- U+3000 (전각 공백): 한국어·일본어 환경에서 따라오는 두 칸 폭의 공백.
코드에서 if (a === b)가 거짓인데 눈으로는 같아 보일 때, 위 다섯 중 하나를 의심하면 90% 정도 맞습니다.
제로폭 문자의 정체
제로폭 문자 중 가장 유명한 건 U+200B(ZWSP)입니다. 화면에서 폭이 0이라 보이지 않지만, 문자열의 길이는 1로 카운트돼요. 자바스크립트에서 'hello'.length는 5이지만 'hel\u200blo'.length는 6이 됩니다. 이메일이나 메신저에서 긴 URL을 자연스럽게 줄바꿈하기 위해 자동으로 삽입되는 경우가 많고, 일부 SNS는 봇 탐지를 어렵게 하려고 사용자 글에 끼워 넣기도 해요. 또 다른 비슷한 친구로는 U+200C(ZWNJ), U+200D(ZWJ)가 있습니다. 이모지의 변형(예: 가족 이모지의 결합)에 사용되어 정상적인 사용처도 있지만, 일반 텍스트에 섞이면 비교 실패의 원인이 됩니다.
비ASCII 공백 - 똑같이 생긴 다른 문자
진짜 골치 아픈 건 일반 공백(U+0020)과 똑같이 보이는 다른 코드포인트들이에요.
- U+00A0 (NBSP): HTML , 워드의 줄바꿈 방지 공백. 가장 흔함.
- U+2009 (Thin Space): 인쇄 식자에서 쓰는 가는 공백.
- U+202F (Narrow No-Break Space): 시간 표기 등에서 사용.
- U+3000 (Ideographic Space): 한자 문화권의 두 배 폭 공백.
이런 공백이 사용자 입력에 섞이면 trim()이 동작하지 않거나, 주소: 서울 과 주소: 서울 이 다른 문자열로 비교돼요. 정규식 \s 는 일부만 매칭하니 정확히 빼려면 코드포인트 단위로 처리해야 합니다. 한국어·일본어 사용자가 많은 서비스라면 입력 검증에 NBSP·전각 공백 정규화를 꼭 넣어두는 걸 권장해요.
BOM과 인코딩 표시 문자
UTF-8 파일 맨 앞에 가끔 따라붙는 BOM(U+FEFF) 도 자주 문제를 만듭니다. UTF-16에서는 바이트 순서 표시 용도로 쓰이지만, UTF-8에서는 사실상 불필요한데도 Windows의 메모장이나 일부 도구가 자동으로 붙여요. JSON 파일 맨 앞에 BOM이 있으면 JSON.parse가 실패하고, CSV 파일에 BOM이 있으면 첫 컬럼 이름이 id가 아니라 보이지 않는 BOM 문자가 앞에 붙은 형태가 되는 식이에요. shell script 첫 줄이 #!/bin/bash라면 BOM이 붙는 순간 실행이 안 됩니다. 파일을 다른 OS에서 만들었다 가져왔는데 갑자기 동작이 이상해지면 BOM을 의심해보세요.
발견하는 방법 - 디버깅 기법
보이지 않는 문자를 찾는 가장 빠른 방법 몇 가지입니다.
- VS Code의 표시 설정: Editor: Render Whitespace를 all로 켜면 공백 종류별 표시. NBSP는 일반 공백과 다른 점으로 보입니다.
- JS·Python에서 문자열 길이 체크: 눈으로 같은데 length가 다르다면 보이지 않는 문자가 끼어 있어요.
- 코드포인트 출력: Array.from(s).map(c => c.codePointAt(0)) 같은 식으로 각 문자의 코드포인트를 찍어보면 어디에 어떤 문자가 있는지 즉시 보입니다.
- 정규식 탐지: 의심 코드포인트 범위를 정규식으로 잡아서 입력을 거름.
이렇게 한 번 발견하면, 입력 단계에서 normalize·trim하도록 코드에 넣어두는 게 재발 방지에 좋습니다.
도구로 한 번에 정리하기
툴박스의 특수문자 정리기는 텍스트에 섞인 보이지 않는 문자, 비표준 공백, BOM 등을 한 번에 감지해 표시하고, 일반 ASCII 공백·줄바꿈으로 정규화해줍니다. 이메일에서 복사한 텍스트, 워드에서 옮긴 본문, 외부 스프레드시트의 데이터를 정리할 때 빠르게 활용하세요. 사용자 입력을 다루는 코드라면 입력 검증에서 같은 정규화를 적용하면 보이지 않는 문자로 인한 검색·비교 실패를 처음부터 막을 수 있어요.


