본문 바로가기
Converter

글자수 세기 (공백 포함 · 제외)

공백 포함/제외, 바이트, 단어, 줄 수를 동시에

입력한 글은 브라우저 밖으로 나가지 않습니다.

글자수 (공백 포함)

0

띄어쓰기·줄바꿈을 모두 포함

글자수 (공백 제외)

0

띄어쓰기·탭·줄바꿈을 모두 제외 — 자소서 폼 기준

단어 (어절)

0

0

문단

0

UTF-8

0B

EUC-KR

0B

글자수 제한 확인

기준이 제한마다 다릅니다

제한기준현재남은 수
자기소개서 500자공백 제외0 / 500500
자기소개서 1,000자공백 제외0 / 1,0001,000
자기소개서 1,500자공백 제외0 / 1,5001,500
X(트위터) 게시물한글·한자는 2자로 계산돼 실제로는 약 140자공백 포함0 / 280280
네이버 블로그 제목공백 포함0 / 100100
YouTube 영상 제목공백 포함0 / 100100
Instagram 캡션공백 포함0 / 2,2002,200
SMS 단문한글 45자 · 90바이트를 넘으면 LMS로 전환된다EUC-KR 바이트0 / 9090

같은 글인데 사이트마다 글자수가 다른 이유

글자수를 세는 건 쉬운 일처럼 보입니다. 실제로 어려운 건 세는 게 아니라 “글자 하나”가 무엇인지 정하는 일입니다. 놀랍게도 여기에는 정답이 하나가 아니고, 그래서 같은 글을 여러 사이트에 붙여넣으면 다른 숫자가 나옵니다.

자바스크립트에서 "글자".length를 부르면 글자 수가 나오는 것처럼 보입니다. 하지만 이 값이 실제로 세는 건 UTF-16 코드 단위입니다. 한글과 영문은 우연히 1대1로 맞아떨어져서 문제가 드러나지 않을 뿐입니다. 우연이 깨지는 순간 이런 일이 벌어집니다:

입력          .length   [...str]   실제 글자
─────────────────────────────────────────────
가             1         1          1
a              1         1          1
😀             2         1          1
👨‍👩‍👧‍👦            11         7          1
é (e + ́)       2         2          1
한 (ᄒ+ᅡ+ᆫ)     3         3          1

가족 이모지 하나가 11자로 세집니다. 이건 버그가 아니라 정의의 문제입니다. 👨‍👩‍👧‍👦는 사실 남자·여자·여아·남아 네 개의 이모지를 ZWJ(zero-width joiner, U+200D)라는 보이지 않는 접착제로 이어 붙인 것이고, 그 각각이 서로게이트 쌍(2코드 단위)이라 4×2 + 3 = 11이 됩니다. 트위터에 이모지 하나 넣었다고 남은 글자가 11자 줄어드는 경험을 해 봤다면 그 사이트가 .length를 쓰고 있었던 겁니다.

세는 방법은 세 가지고, 각각 다른 답을 준다

  • 코드 단위 (str.length) — 가장 빠르고 가장 틀립니다. 메모리에 몇 칸 차지하는지를 셀 뿐입니다. 그런데 대부분의 글자수 세기 사이트가 이걸 씁니다. 한 줄이면 되니까요.
  • 코드 포인트 ([...str].length) — 이모지 하나는 제대로 1로 셉니다. 스프레드 연산자가 서로게이트 쌍을 붙여서 순회하기 때문입니다. 하지만 ZWJ 시퀀스는 7로, 결합 문자 é는 2로 셉니다. 절반만 맞는 답입니다.
  • Grapheme cluster (Intl.Segmenter)— 유니코드가 정의한 “사람이 글자 하나라고 인식하는 단위”입니다. 위 표의 마지막 열이 이 값이고,이 도구가 쓰는 기준입니다.
const seg = new Intl.Segmenter("ko", { granularity: "grapheme" });
[...seg.segment("👨‍👩‍👧‍👦")].length;  // 1

Segmenter는 브라우저의 ICU 데이터를 쓰기 때문에 .length보다 훨씬 느립니다. 그래도 이걸 쓰는 이유는, 사용자가 “내 글이 몇 자냐”라고 물을 때 알고 싶은 게 메모리 사용량이 아니라 화면에 보이는 글자 개수이기 때문입니다.

“한”이 세 글자가 되는 순간

한글에는 유니코드가 남긴 고약한 함정이 하나 더 있습니다. 같은 글자를 두 가지 방식으로 적을 수 있다는 것입니다.

"한"                    // U+D55C          — 완성형, 1 코드 포인트 (NFC)
"ᄒ" + "ᅡ" + "ᆫ"        // U+1112 U+1161 U+11AB — 조합형, 3 코드 포인트 (NFD)

화면에 렌더된 결과는 픽셀 단위로 동일합니다. 눈으로는 절대 구별할 수 없습니다. 그런데 코드 포인트 수는 1 vs 3이고, UTF-8 바이트는 3 vs 9입니다.

이게 이론상의 이야기가 아닌 이유는 macOS때문입니다. macOS의 파일 시스템은 파일명을 NFD로 저장하고, 일부 앱이 그 형태를 그대로 클립보드에 올립니다. 그래서 맥에서 쓴 글을 회사 폼에 붙여넣었더니 500자 제한에 “1,400자”라고 뜨는 일이 실제로 벌어집니다. 사용자는 자기 글을 세 번 세어 봐도 원인을 찾을 수 없습니다. 보이지 않는 차이니까요.

해법은 세기 전에 정규화하는 것 한 줄입니다:

text.normalize("NFC")   // 조합형 자모를 완성형으로 합친다

이 도구는 입력을 받자마자 NFC로 정규화하고, 그 다음에 셉니다. 그래서 어느 OS에서 붙여넣어도 같은 숫자가 나옵니다. 참고로 grapheme 기준으로는 정규화 없이도 “한”이 1자로 나옵니다 — Segmenter가 자모를 다시 한 덩어리로 묶어 주기 때문입니다. 하지만 바이트 수는 정규화하지 않으면 진짜로 3배가 되고, 여러분이 상대할 폼은 Segmenter를 쓰지 않습니다.

왜 한국에서만 ‘공백 제외’를 이렇게 찾을까

영어권 글자수 도구에는 “excluding spaces”가 구석에 작게 있거나 아예 없습니다. 한국에서만 이게 headline 숫자인 이유는 하나입니다 — 자기소개서 입력 폼이 그렇게 센다.

여기서 사람들이 놓치는 게 줄바꿈도 공백이라는 점입니다. 대부분의 폼은 text.replace(/\s/g, "").length 같은 코드를 쓰고, 정규식의 \s는 스페이스뿐 아니라 탭·줄바꿈·전각 공백(U+3000)·NBSP(U+00A0)까지 전부 포함합니다. 문단을 열 번 나눈 글이라면 그것만으로 수십 자가 사라집니다. 이 도구도 같은 정의를 씁니다.

NBSP와 전각 공백을 굳이 언급하는 이유가 있습니다. 워드에서 복사하면 NBSP가, 한글(HWP)에서 복사하면 전각 공백이 섞여 들어옵니다. 둘 다 눈에는 그냥 공백으로 보이는데, 이걸 빼지 않는 도구를 쓰면 “공백 제외” 숫자가 이유 없이 커집니다.

UTF-8 3바이트 vs EUC-KR 2바이트 — 진짜 사고가 나는 곳

바이트 수는 개발자용 부가 정보처럼 보이지만, 한국에서 실제로 장애를 만드는 값입니다.

"한글"  UTF-8   → 6 바이트  (글자당 3)
"한글"  EUC-KR  → 4 바이트  (글자당 2)
"ab"    둘 다   → 2 바이트  (ASCII 는 1)

이 차이가 VARCHAR(100) 컬럼에 몇 글자가 들어가는지를 바꿉니다. MySQL의 utf8mb4에서 VARCHAR(100)은 100글자지만, 오래된 시스템의 VARCHAR(100)은 100바이트여서 한글은 50자, EUC-KR이면 50자, UTF-8 바이트 기준이면 33자만 들어갑니다. 같은 스키마 정의가 charset에 따라 세 가지 답을 냅니다.

여기서 나오는 전형적인 프로덕션 버그가 “잘린 한글”입니다. 100바이트에서 자르면 33.3번째 글자의 한가운데가 잘려서, 마지막 글자가 ? 로 저장됩니다. 화면 어디선가 깨진 글자가 하나씩 보이기 시작하는데 재현이 안 되는 이유가 이겁니다 — 입력이 딱 경계에 걸릴 때만 터집니다.

그리고 이모지는 UTF-8에서 4바이트입니다. MySQL의 예전 기본값이던 utf8(실제로는 utf8mb3, 최대 3바이트)에 이모지를 넣으면 그대로 에러가 납니다. “한글은 잘 되는데 이모지만 안 저장돼요”의 정체입니다.

위 계산기의 EUC-KR 값에 대해서는 정직하게 밝혀 둡니다. 이건 진짜 CP949 인코딩이 아니라 ASCII는 1, 나머지는 2로 세는 계산입니다. 그런데 이게 바로 관공서·대학 폼과 구형 게시판이 실제로 쓰는 방식입니다. 그쪽 코드는 대개 charAt(i) > 127 ? 2 : 1한 줄이거든요. 사용자가 알고 싶은 건 “CP949 표준이 뭐냐”가 아니라 “그 폼이 내 글을 몇 바이트로 셀 것이냐”이므로, 표준이 아니라 현실을 재현했습니다.

단어 수는 애매하다 — 그리고 그건 고칠 수 없다

영어의 word count는 정의가 명확합니다. 공백으로 끊으면 그게 단어입니다. 한국어는 그렇지 않습니다.

“학교에서”는 공백 기준으로 1어절이지만, 형태소로 쪼개면 학교 + 에서 로 2개입니다. “만났다”는 만나 + 았 + 다 로 3개입니다. 어느 쪽이 “단어 수”냐는 질문에는 국어학적으로도 맥락에 따라 답이 갈립니다.

형태소 분석은 사전과 통계 모델이 필요한 작업이고, 타이핑할 때마다 브라우저에서 돌릴 수 있는 일이 아닙니다. 그래서 이 도구는 공백 기준 어절로 정의하고 화면에도 그렇게 적었습니다. 애매한 값을 “단어 수”라는 이름으로 그럴듯하게 감추는 것보다, 무엇을 세고 있는지 밝히는 편이 쓸모 있습니다. 영어 원고의 단어 수를 볼 때는 이 값이 정확합니다.

정리하면

  • 글자수는 하나의 숫자가 아닙니다. 이모지·결합 문자가 없다면 어떤 방법으로 세도 같지만, 하나라도 있으면 세 가지 다른 답이 나옵니다. 이 도구는 사람이 보는 단위를 기준으로 삼습니다.
  • 제출 직전에는 실제 폼에 붙여넣어 확인하세요. 이 도구가 아무리 정확해도, 여러분을 심사하는 건 그 폼의 계산식입니다. 500자 제한에 499자를 채워 놓는 것보다 480자쯤에 여유를 두는 게 안전합니다.
  • 숫자가 예상과 다르면 보이지 않는 문자를 의심하세요. NFD로 분해된 자모, 워드에서 딸려 온 NBSP, 윈도우의 CR — 전부 눈에 보이지 않으면서 숫자를 바꿉니다.

자주 묻는 질문

사이트마다 글자수가 다르게 나오는데 어느 쪽이 맞나요?
이모지나 결합 문자가 없는 순수 한글·영문이라면 어디서 세든 같은 숫자가 나와야 정상이고, 다르다면 공백을 세는 기준이 다른 것입니다. 반대로 이모지가 들어 있으면 사이트마다 다른 게 당연합니다. 대부분의 글자수 세기 사이트가 자바스크립트의 .length를 그대로 쓰는데, 이건 글자가 아니라 UTF-16 코드 단위를 세는 값이라 😀 하나를 2로 셉니다. 이 도구는 Intl.Segmenter로 사람이 보는 글자(grapheme cluster) 단위를 세기 때문에 1로 나옵니다.
자기소개서의 '공백 제외'에 줄바꿈도 포함되나요?
네, 이 도구는 띄어쓰기·탭·줄바꿈을 모두 공백으로 보고 뺍니다. 대부분의 채용 사이트 입력 폼도 같은 방식(정규식 \s 제거)으로 계산합니다. 문단을 많이 나눈 글이라면 줄바꿈만으로 수십 자가 차이 날 수 있으니, 제출 직전에는 실제 폼에 붙여넣어 최종 확인하는 것이 안전합니다.
맥에서 복사한 글을 붙여넣으니 글자수가 이상하게 늘어납니다.
macOS는 유니코드를 NFD(분해형)로 저장하는 곳이 있어서, '한'이 초성 ᄒ + 중성 ᅡ + 종성 ᆫ 세 개의 코드 포인트로 들어오는 경우가 있습니다. 화면에 보이는 모양은 완전히 같은데 숫자만 최대 3배가 됩니다. 이 도구는 입력을 먼저 NFC로 정규화하기 때문에 어느 쪽으로 붙여넣어도 같은 숫자가 나오지만, 다른 사이트나 폼에서는 그대로 3배로 세질 수 있습니다.
UTF-8 바이트와 EUC-KR 바이트는 왜 다른가요?
같은 한글 한 글자를 UTF-8은 3바이트로, EUC-KR(CP949)은 2바이트로 저장하기 때문입니다. 관공서·대학 폼이나 오래된 게시판은 아직 EUC-KR 기준으로 글자수를 제한하는 경우가 많고, SMS 90바이트 제한도 이쪽 계산을 씁니다. 다만 이 도구의 EUC-KR 값은 'ASCII는 1, 나머지는 2'라는 계산으로, 그런 폼들이 실제로 쓰는 방식을 그대로 재현한 근사값입니다.
단어 수는 어떤 기준으로 세나요?
공백으로 끊은 어절을 셉니다. '학교에서 만났다'는 2로 나옵니다. 한국어에서 '단어'를 형태소 단위로 보면 학교 + 에서 + 만나 + 았 + 다처럼 훨씬 많아지지만, 그건 사전과 분석기가 필요한 작업이라 브라우저에서 즉시 계산할 수 있는 범위를 넘습니다. 영어 원고의 단어 수(word count)를 확인하는 용도로는 그대로 신뢰해도 됩니다.
입력한 글이 서버로 전송되나요?
아닙니다. 모든 계산은 브라우저 안에서 끝나고, 입력한 텍스트는 어디로도 전송되거나 저장되지 않습니다. 자기소개서처럼 민감한 글을 붙여넣어도 페이지를 닫는 순간 사라집니다.